Core utilities and components for Apache Superset's frontend UI framework providing data visualization, formatting, and chart composition capabilities
—
This module provides comprehensive styling infrastructure for Superset applications, including the theme system with Emotion integration, color scheme management, text dimension calculations, and layout utilities. It enables consistent styling across components with support for theming, color scales, and responsive design.
The UI & styling system is built around three core areas: the theme system powered by Emotion for CSS-in-JS styling, the color management system with support for categorical and sequential color schemes, and the dimension utilities for text measurement and layout calculations.
Emotion-based styling system with comprehensive theme support:
import {
ThemeProvider,
useTheme,
styled,
css,
jsx,
withTheme,
SupersetTheme,
SupersetThemeProps,
supersetTheme,
emotionCache,
EmotionCacheProvider,
createEmotionCache
} from '@superset-ui/core';
// Theme provider for React context
const ThemeProvider: React.ComponentType<{ theme: SupersetTheme; children: React.ReactNode }>;
// Hook to access theme context
function useTheme(): SupersetTheme;
// Styled components factory
const styled: typeof emotionStyled;
// CSS template literal function
const css: typeof emotionCss;
// JSX pragma for Emotion
const jsx: typeof emotionJsx;
// Higher-order component for theme access
const withTheme: typeof emotionWithTheme;
// Emotion cache providers
const EmotionCacheProvider: typeof CacheProvider;
function createEmotionCache(options?: { key?: string }): EmotionCache;
// Default emotion cache instance
const emotionCache: EmotionCache;Comprehensive theme structure with design tokens:
interface SupersetTheme {
// Layout and spacing
borderRadius: number;
gridUnit: number;
transitionTiming: number;
// Color system
colors: {
text: {
label: string;
help: string;
};
primary: ColorScale;
secondary: ColorScale;
grayscale: ColorScale;
error: ColorScale;
warning: ColorScale;
alert: ColorScale;
success: ColorScale;
info: ColorScale;
};
// Typography system
typography: {
families: {
sansSerif: string;
serif: string;
monospace: string;
};
weights: {
light: number;
normal: number;
medium: number;
bold: number;
};
sizes: {
xxs: number;
xs: number;
s: number;
m: number;
l: number;
xl: number;
xxl: number;
};
};
// Opacity levels
opacity: {
light: string;
mediumLight: string;
mediumHeavy: string;
heavy: string;
};
// Z-index management
zIndex: {
aboveDashboardCharts: number;
dropdown: number;
max: number;
};
}
// Color scale structure
interface ColorScale {
base: string;
dark1: string;
dark2: string;
light1: string;
light2: string;
light3?: string;
light4?: string;
light5?: string;
}
// Component props interface for themed components
interface SupersetThemeProps {
theme: SupersetTheme;
}
// Default theme instance
const supersetTheme: SupersetTheme;Comprehensive color scheme management for data visualization:
import {
ColorScheme,
CategoricalScheme,
SequentialScheme,
CategoricalColorScale,
getCategoricalSchemeRegistry,
getSequentialSchemeRegistry,
BRAND_COLOR
} from '@superset-ui/core';
// Base color scheme class
class ColorScheme {
readonly id: string;
readonly label: string;
readonly colors: string[];
readonly isDefault?: boolean;
constructor(config: {
id: string;
label: string;
colors: string[];
isDefault?: boolean;
});
getColors(numColors?: number): string[];
}
// Categorical color scheme for discrete data
class CategoricalScheme extends ColorScheme {
constructor(config: CategoricalSchemeConfig);
}
// Sequential color scheme for continuous data
class SequentialScheme extends ColorScheme {
constructor(config: SequentialSchemeConfig);
}
// Categorical color scale for data mapping
class CategoricalColorScale {
constructor(colors: string[], forced?: boolean);
getColor(key: string): string;
setColor(key: string, color: string): this;
getColorMap(): { [key: string]: string };
copy(): CategoricalColorScale;
}
// Registry access functions
function getCategoricalSchemeRegistry(): RegistryWithDefaultKey<CategoricalScheme>;
function getSequentialSchemeRegistry(): RegistryWithDefaultKey<SequentialScheme>;
// Brand color constant
const BRAND_COLOR = '#00A699';Advanced color management with namespaces for consistent color assignment:
import { CategoricalColorNamespace, getSharedLabelColor } from '@superset-ui/core';
// Categorical color namespace utilities
namespace CategoricalColorNamespace {
function getNamespace(namespace?: string): CategoricalColorScale;
function getScale(schemeId?: string, namespace?: string): CategoricalColorScale;
function setColor(key: string, color: string, namespace?: string): void;
function getColor(key: string, schemeId?: string, namespace?: string): string;
}
// Shared label color management
function getSharedLabelColor(): SharedLabelColor;
class SharedLabelColor {
getColorMap(scheme?: string, namespace?: string): { [key: string]: string };
addSlice(label: string, color: string, scheme?: string, namespace?: string): void;
removeSlice(label: string, scheme?: string, namespace?: string): void;
clear(scheme?: string, namespace?: string): void;
}Utilities for measuring text dimensions and calculating font sizes:
import {
getTextDimension,
getMultipleTextDimensions,
computeMaxFontSize,
Dimension,
TextStyle
} from '@superset-ui/core';
// Single text measurement
function getTextDimension(config: {
text: string;
style?: TextStyle;
}): Dimension;
// Multiple text measurements (more efficient for batch operations)
function getMultipleTextDimensions(config: {
texts: string[];
style?: TextStyle;
}): Dimension[];
// Calculate maximum font size that fits constraints
function computeMaxFontSize(config: {
text: string;
idealFontSize: number;
maxWidth: number;
maxHeight: number;
style?: TextStyle;
}): number;
// Dimension interface
interface Dimension {
width: number;
height: number;
}
// Text style configuration
interface TextStyle {
fontSize?: string | number;
fontFamily?: string;
fontWeight?: string | number;
fontStyle?: string;
letterSpacing?: string | number;
lineHeight?: string | number;
}Utilities for margin handling and CSS length parsing:
import { mergeMargin, parseLength, Margin } from '@superset-ui/core';
// Merge margin objects with proper handling of undefined values
function mergeMargin(...margins: (Partial<Margin> | undefined)[]): Margin;
// Parse CSS length values to numeric values
function parseLength(input: string | number): number;
// Margin interface
interface Margin {
top: number;
right: number;
bottom: number;
left: number;
}import React from 'react';
import {
ThemeProvider,
supersetTheme,
emotionCache,
EmotionCacheProvider
} from '@superset-ui/core';
// App-level theme setup
const App: React.FC = ({ children }) => (
<EmotionCacheProvider value={emotionCache}>
<ThemeProvider theme={supersetTheme}>
{children}
</ThemeProvider>
</EmotionCacheProvider>
);
// Custom theme configuration
const customTheme = {
...supersetTheme,
colors: {
...supersetTheme.colors,
primary: {
...supersetTheme.colors.primary,
base: '#FF6B6B' // Custom primary color
}
}
};import React from 'react';
import { styled, useTheme, css } from '@superset-ui/core';
// Basic styled component with theme access
const StyledButton = styled.button`
background-color: ${({ theme }) => theme.colors.primary.base};
color: ${({ theme }) => theme.colors.grayscale.light5};
border: none;
border-radius: ${({ theme }) => theme.borderRadius}px;
padding: ${({ theme }) => theme.gridUnit * 2}px ${({ theme }) => theme.gridUnit * 4}px;
font-family: ${({ theme }) => theme.typography.families.sansSerif};
font-size: ${({ theme }) => theme.typography.sizes.m}px;
font-weight: ${({ theme }) => theme.typography.weights.medium};
transition: all ${({ theme }) => theme.transitionTiming}s ease;
&:hover {
background-color: ${({ theme }) => theme.colors.primary.dark1};
}
&:disabled {
opacity: ${({ theme }) => theme.opacity.mediumHeavy};
cursor: not-allowed;
}
`;
// Component using theme hook
const ThemedCard: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const theme = useTheme();
return (
<div
css={css`
background: ${theme.colors.grayscale.light5};
border: 1px solid ${theme.colors.grayscale.light2};
border-radius: ${theme.borderRadius}px;
padding: ${theme.gridUnit * 4}px;
box-shadow: 0 ${theme.gridUnit}px ${theme.gridUnit * 3}px ${theme.colors.grayscale.light2};
`}
>
{children}
</div>
);
};import {
getCategoricalSchemeRegistry,
CategoricalColorNamespace,
CategoricalColorScale
} from '@superset-ui/core';
// Register custom color scheme
const customColors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#FFA07A', '#98D8C8'];
const customScheme = new CategoricalScheme({
id: 'custom',
label: 'Custom Colors',
colors: customColors
});
getCategoricalSchemeRegistry().registerValue('custom', customScheme);
// Use color scale for data visualization
const createColorScale = (data: string[]) => {
const scale = CategoricalColorNamespace.getScale('custom', 'myChart');
// Assign colors to data categories
data.forEach(category => {
CategoricalColorNamespace.getColor(category, 'custom', 'myChart');
});
return scale;
};
// Get colors for chart data
const chartData = ['Category A', 'Category B', 'Category C'];
const colorScale = createColorScale(chartData);
const colors = chartData.map(category => colorScale.getColor(category));import {
getTextDimension,
computeMaxFontSize,
getMultipleTextDimensions
} from '@superset-ui/core';
// Measure single text element
const textDimension = getTextDimension({
text: 'Chart Title',
style: {
fontSize: 16,
fontFamily: 'Inter, Arial, sans-serif',
fontWeight: 'bold'
}
});
console.log(`Text size: ${textDimension.width} x ${textDimension.height}`);
// Calculate optimal font size for container
const optimalFontSize = computeMaxFontSize({
text: 'Long chart title that needs to fit',
idealFontSize: 18,
maxWidth: 200,
maxHeight: 30,
style: {
fontFamily: 'Inter, Arial, sans-serif',
fontWeight: 'bold'
}
});
// Batch text measurement for better performance
const labels = ['Label 1', 'Label 2', 'Label 3', 'Very Long Label Name'];
const labelDimensions = getMultipleTextDimensions({
texts: labels,
style: { fontSize: 12, fontFamily: 'Inter' }
});
// Find maximum width for layout calculations
const maxLabelWidth = Math.max(...labelDimensions.map(d => d.width));import { styled, css, useTheme } from '@superset-ui/core';
// Conditional styling based on props
interface CardProps {
variant?: 'primary' | 'secondary' | 'danger';
size?: 'small' | 'medium' | 'large';
}
const StyledCard = styled.div<CardProps>`
${({ theme }) => css`
border-radius: ${theme.borderRadius}px;
padding: ${theme.gridUnit * 2}px;
font-family: ${theme.typography.families.sansSerif};
transition: all ${theme.transitionTiming}s ease;
`}
${({ theme, variant = 'primary' }) => {
const colorMap = {
primary: theme.colors.primary,
secondary: theme.colors.secondary,
danger: theme.colors.error
};
const colors = colorMap[variant];
return css`
background-color: ${colors.light4};
border: 1px solid ${colors.light2};
color: ${colors.dark2};
`;
}}
${({ theme, size = 'medium' }) => {
const sizeMap = {
small: theme.gridUnit * 2,
medium: theme.gridUnit * 4,
large: theme.gridUnit * 6
};
return css`
padding: ${sizeMap[size]}px;
font-size: ${theme.typography.sizes[size === 'small' ? 's' : size === 'large' ? 'l' : 'm']}px;
`;
}}
`;
// Dynamic styling with CSS variables
const DynamicStyledComponent = styled.div`
${({ theme }) => {
// Set CSS custom properties from theme
return css`
--primary-color: ${theme.colors.primary.base};
--secondary-color: ${theme.colors.secondary.base};
--border-radius: ${theme.borderRadius}px;
--grid-unit: ${theme.gridUnit}px;
background: var(--primary-color);
border-radius: var(--border-radius);
padding: calc(var(--grid-unit) * 2);
.nested-element {
background: var(--secondary-color);
margin: var(--grid-unit);
}
`;
}}
`;import { styled, css } from '@superset-ui/core';
// Responsive breakpoints (not in theme but commonly used)
const breakpoints = {
xs: '0px',
sm: '576px',
md: '768px',
lg: '992px',
xl: '1200px'
};
const media = {
xs: `@media (min-width: ${breakpoints.xs})`,
sm: `@media (min-width: ${breakpoints.sm})`,
md: `@media (min-width: ${breakpoints.md})`,
lg: `@media (min-width: ${breakpoints.lg})`,
xl: `@media (min-width: ${breakpoints.xl})`
};
// Responsive styled component
const ResponsiveGrid = styled.div`
${({ theme }) => css`
display: grid;
gap: ${theme.gridUnit * 2}px;
padding: ${theme.gridUnit * 2}px;
${media.xs} {
grid-template-columns: 1fr;
}
${media.sm} {
grid-template-columns: repeat(2, 1fr);
}
${media.md} {
grid-template-columns: repeat(3, 1fr);
}
${media.lg} {
grid-template-columns: repeat(4, 1fr);
}
`}
`;import {
CategoricalColorNamespace,
getSharedLabelColor,
BRAND_COLOR
} from '@superset-ui/core';
// Shared color management across dashboard
const labelColorManager = getSharedLabelColor();
// Add colors for specific data labels
labelColorManager.addSlice('Sales', '#FF6B6B', 'd3Category10', 'dashboard_1');
labelColorManager.addSlice('Marketing', '#4ECDC4', 'd3Category10', 'dashboard_1');
// Get consistent colors across charts
const getConsistentColor = (label: string, namespace: string) => {
return CategoricalColorNamespace.getColor(label, 'd3Category10', namespace);
};
// Clear colors when dashboard changes
const clearDashboardColors = (namespace: string) => {
labelColorManager.clear('d3Category10', namespace);
};
// Use brand color for primary elements
const brandButton = styled.button`
background-color: ${BRAND_COLOR};
color: white;
`;import { mergeMargin, parseLength } from '@superset-ui/core';
// Merge multiple margin configurations
const baseMargin = { top: 10, right: 15, bottom: 10, left: 15 };
const titleMargin = { top: 20, bottom: 5 };
const finalMargin = mergeMargin(baseMargin, titleMargin);
// Result: { top: 20, right: 15, bottom: 5, left: 15 }
// Parse CSS length values
const numericValue1 = parseLength('16px'); // 16
const numericValue2 = parseLength('1.5em'); // Converted to pixels based on context
const numericValue3 = parseLength(20); // 20
// Calculate responsive margins
const calculateResponsiveMargin = (baseSize: number) => {
const sm = parseLength(`${baseSize * 0.5}px`);
const md = parseLength(`${baseSize}px`);
const lg = parseLength(`${baseSize * 1.5}px`);
return { sm, md, lg };
};Install with Tessl CLI
npx tessl i tessl/npm-superset-ui--core@0.18.1