or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-models.mddashboard.mddata-connection.mddata-formatting.mdindex.mdplugin-system.mdtranslation.mdui-styling.mdvalidation-math.md

ui-styling.mddocs/

0

# UI & Styling

1

2

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.

3

4

## Overview

5

6

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.

7

8

## Theme System

9

10

### Core Theme Integration { .api }

11

12

Emotion-based styling system with comprehensive theme support:

13

14

```typescript

15

import {

16

ThemeProvider,

17

useTheme,

18

styled,

19

css,

20

jsx,

21

withTheme,

22

SupersetTheme,

23

SupersetThemeProps,

24

supersetTheme,

25

emotionCache,

26

EmotionCacheProvider,

27

createEmotionCache

28

} from '@superset-ui/core';

29

30

// Theme provider for React context

31

const ThemeProvider: React.ComponentType<{ theme: SupersetTheme; children: React.ReactNode }>;

32

33

// Hook to access theme context

34

function useTheme(): SupersetTheme;

35

36

// Styled components factory

37

const styled: typeof emotionStyled;

38

39

// CSS template literal function

40

const css: typeof emotionCss;

41

42

// JSX pragma for Emotion

43

const jsx: typeof emotionJsx;

44

45

// Higher-order component for theme access

46

const withTheme: typeof emotionWithTheme;

47

48

// Emotion cache providers

49

const EmotionCacheProvider: typeof CacheProvider;

50

function createEmotionCache(options?: { key?: string }): EmotionCache;

51

52

// Default emotion cache instance

53

const emotionCache: EmotionCache;

54

```

55

56

### SupersetTheme Interface { .api }

57

58

Comprehensive theme structure with design tokens:

59

60

```typescript

61

interface SupersetTheme {

62

// Layout and spacing

63

borderRadius: number;

64

gridUnit: number;

65

transitionTiming: number;

66

67

// Color system

68

colors: {

69

text: {

70

label: string;

71

help: string;

72

};

73

primary: ColorScale;

74

secondary: ColorScale;

75

grayscale: ColorScale;

76

error: ColorScale;

77

warning: ColorScale;

78

alert: ColorScale;

79

success: ColorScale;

80

info: ColorScale;

81

};

82

83

// Typography system

84

typography: {

85

families: {

86

sansSerif: string;

87

serif: string;

88

monospace: string;

89

};

90

weights: {

91

light: number;

92

normal: number;

93

medium: number;

94

bold: number;

95

};

96

sizes: {

97

xxs: number;

98

xs: number;

99

s: number;

100

m: number;

101

l: number;

102

xl: number;

103

xxl: number;

104

};

105

};

106

107

// Opacity levels

108

opacity: {

109

light: string;

110

mediumLight: string;

111

mediumHeavy: string;

112

heavy: string;

113

};

114

115

// Z-index management

116

zIndex: {

117

aboveDashboardCharts: number;

118

dropdown: number;

119

max: number;

120

};

121

}

122

123

// Color scale structure

124

interface ColorScale {

125

base: string;

126

dark1: string;

127

dark2: string;

128

light1: string;

129

light2: string;

130

light3?: string;

131

light4?: string;

132

light5?: string;

133

}

134

135

// Component props interface for themed components

136

interface SupersetThemeProps {

137

theme: SupersetTheme;

138

}

139

140

// Default theme instance

141

const supersetTheme: SupersetTheme;

142

```

143

144

## Color Management

145

146

### Color Scheme System { .api }

147

148

Comprehensive color scheme management for data visualization:

149

150

```typescript

151

import {

152

ColorScheme,

153

CategoricalScheme,

154

SequentialScheme,

155

CategoricalColorScale,

156

getCategoricalSchemeRegistry,

157

getSequentialSchemeRegistry,

158

BRAND_COLOR

159

} from '@superset-ui/core';

160

161

// Base color scheme class

162

class ColorScheme {

163

readonly id: string;

164

readonly label: string;

165

readonly colors: string[];

166

readonly isDefault?: boolean;

167

168

constructor(config: {

169

id: string;

170

label: string;

171

colors: string[];

172

isDefault?: boolean;

173

});

174

175

getColors(numColors?: number): string[];

176

}

177

178

// Categorical color scheme for discrete data

179

class CategoricalScheme extends ColorScheme {

180

constructor(config: CategoricalSchemeConfig);

181

}

182

183

// Sequential color scheme for continuous data

184

class SequentialScheme extends ColorScheme {

185

constructor(config: SequentialSchemeConfig);

186

}

187

188

// Categorical color scale for data mapping

189

class CategoricalColorScale {

190

constructor(colors: string[], forced?: boolean);

191

192

getColor(key: string): string;

193

setColor(key: string, color: string): this;

194

getColorMap(): { [key: string]: string };

195

copy(): CategoricalColorScale;

196

}

197

198

// Registry access functions

199

function getCategoricalSchemeRegistry(): RegistryWithDefaultKey<CategoricalScheme>;

200

function getSequentialSchemeRegistry(): RegistryWithDefaultKey<SequentialScheme>;

201

202

// Brand color constant

203

const BRAND_COLOR = '#00A699';

204

```

205

206

### Color Namespace Management { .api }

207

208

Advanced color management with namespaces for consistent color assignment:

209

210

```typescript

211

import { CategoricalColorNamespace, getSharedLabelColor } from '@superset-ui/core';

212

213

// Categorical color namespace utilities

214

namespace CategoricalColorNamespace {

215

function getNamespace(namespace?: string): CategoricalColorScale;

216

function getScale(schemeId?: string, namespace?: string): CategoricalColorScale;

217

function setColor(key: string, color: string, namespace?: string): void;

218

function getColor(key: string, schemeId?: string, namespace?: string): string;

219

}

220

221

// Shared label color management

222

function getSharedLabelColor(): SharedLabelColor;

223

224

class SharedLabelColor {

225

getColorMap(scheme?: string, namespace?: string): { [key: string]: string };

226

addSlice(label: string, color: string, scheme?: string, namespace?: string): void;

227

removeSlice(label: string, scheme?: string, namespace?: string): void;

228

clear(scheme?: string, namespace?: string): void;

229

}

230

```

231

232

## Text and Layout Utilities

233

234

### Text Dimension Calculation { .api }

235

236

Utilities for measuring text dimensions and calculating font sizes:

237

238

```typescript

239

import {

240

getTextDimension,

241

getMultipleTextDimensions,

242

computeMaxFontSize,

243

Dimension,

244

TextStyle

245

} from '@superset-ui/core';

246

247

// Single text measurement

248

function getTextDimension(config: {

249

text: string;

250

style?: TextStyle;

251

}): Dimension;

252

253

// Multiple text measurements (more efficient for batch operations)

254

function getMultipleTextDimensions(config: {

255

texts: string[];

256

style?: TextStyle;

257

}): Dimension[];

258

259

// Calculate maximum font size that fits constraints

260

function computeMaxFontSize(config: {

261

text: string;

262

idealFontSize: number;

263

maxWidth: number;

264

maxHeight: number;

265

style?: TextStyle;

266

}): number;

267

268

// Dimension interface

269

interface Dimension {

270

width: number;

271

height: number;

272

}

273

274

// Text style configuration

275

interface TextStyle {

276

fontSize?: string | number;

277

fontFamily?: string;

278

fontWeight?: string | number;

279

fontStyle?: string;

280

letterSpacing?: string | number;

281

lineHeight?: string | number;

282

}

283

```

284

285

### Layout Utilities { .api }

286

287

Utilities for margin handling and CSS length parsing:

288

289

```typescript

290

import { mergeMargin, parseLength, Margin } from '@superset-ui/core';

291

292

// Merge margin objects with proper handling of undefined values

293

function mergeMargin(...margins: (Partial<Margin> | undefined)[]): Margin;

294

295

// Parse CSS length values to numeric values

296

function parseLength(input: string | number): number;

297

298

// Margin interface

299

interface Margin {

300

top: number;

301

right: number;

302

bottom: number;

303

left: number;

304

}

305

```

306

307

## Usage Examples

308

309

### Basic Theme Setup

310

311

```typescript

312

import React from 'react';

313

import {

314

ThemeProvider,

315

supersetTheme,

316

emotionCache,

317

EmotionCacheProvider

318

} from '@superset-ui/core';

319

320

// App-level theme setup

321

const App: React.FC = ({ children }) => (

322

<EmotionCacheProvider value={emotionCache}>

323

<ThemeProvider theme={supersetTheme}>

324

{children}

325

</ThemeProvider>

326

</EmotionCacheProvider>

327

);

328

329

// Custom theme configuration

330

const customTheme = {

331

...supersetTheme,

332

colors: {

333

...supersetTheme.colors,

334

primary: {

335

...supersetTheme.colors.primary,

336

base: '#FF6B6B' // Custom primary color

337

}

338

}

339

};

340

```

341

342

### Styled Components with Theme

343

344

```typescript

345

import React from 'react';

346

import { styled, useTheme, css } from '@superset-ui/core';

347

348

// Basic styled component with theme access

349

const StyledButton = styled.button`

350

background-color: ${({ theme }) => theme.colors.primary.base};

351

color: ${({ theme }) => theme.colors.grayscale.light5};

352

border: none;

353

border-radius: ${({ theme }) => theme.borderRadius}px;

354

padding: ${({ theme }) => theme.gridUnit * 2}px ${({ theme }) => theme.gridUnit * 4}px;

355

font-family: ${({ theme }) => theme.typography.families.sansSerif};

356

font-size: ${({ theme }) => theme.typography.sizes.m}px;

357

font-weight: ${({ theme }) => theme.typography.weights.medium};

358

transition: all ${({ theme }) => theme.transitionTiming}s ease;

359

360

&:hover {

361

background-color: ${({ theme }) => theme.colors.primary.dark1};

362

}

363

364

&:disabled {

365

opacity: ${({ theme }) => theme.opacity.mediumHeavy};

366

cursor: not-allowed;

367

}

368

`;

369

370

// Component using theme hook

371

const ThemedCard: React.FC<{ children: React.ReactNode }> = ({ children }) => {

372

const theme = useTheme();

373

374

return (

375

<div

376

css={css`

377

background: ${theme.colors.grayscale.light5};

378

border: 1px solid ${theme.colors.grayscale.light2};

379

border-radius: ${theme.borderRadius}px;

380

padding: ${theme.gridUnit * 4}px;

381

box-shadow: 0 ${theme.gridUnit}px ${theme.gridUnit * 3}px ${theme.colors.grayscale.light2};

382

`}

383

>

384

{children}

385

</div>

386

);

387

};

388

```

389

390

### Color Scheme Usage

391

392

```typescript

393

import {

394

getCategoricalSchemeRegistry,

395

CategoricalColorNamespace,

396

CategoricalColorScale

397

} from '@superset-ui/core';

398

399

// Register custom color scheme

400

const customColors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#FFA07A', '#98D8C8'];

401

const customScheme = new CategoricalScheme({

402

id: 'custom',

403

label: 'Custom Colors',

404

colors: customColors

405

});

406

407

getCategoricalSchemeRegistry().registerValue('custom', customScheme);

408

409

// Use color scale for data visualization

410

const createColorScale = (data: string[]) => {

411

const scale = CategoricalColorNamespace.getScale('custom', 'myChart');

412

413

// Assign colors to data categories

414

data.forEach(category => {

415

CategoricalColorNamespace.getColor(category, 'custom', 'myChart');

416

});

417

418

return scale;

419

};

420

421

// Get colors for chart data

422

const chartData = ['Category A', 'Category B', 'Category C'];

423

const colorScale = createColorScale(chartData);

424

const colors = chartData.map(category => colorScale.getColor(category));

425

```

426

427

### Text Measurement and Font Sizing

428

429

```typescript

430

import {

431

getTextDimension,

432

computeMaxFontSize,

433

getMultipleTextDimensions

434

} from '@superset-ui/core';

435

436

// Measure single text element

437

const textDimension = getTextDimension({

438

text: 'Chart Title',

439

style: {

440

fontSize: 16,

441

fontFamily: 'Inter, Arial, sans-serif',

442

fontWeight: 'bold'

443

}

444

});

445

446

console.log(`Text size: ${textDimension.width} x ${textDimension.height}`);

447

448

// Calculate optimal font size for container

449

const optimalFontSize = computeMaxFontSize({

450

text: 'Long chart title that needs to fit',

451

idealFontSize: 18,

452

maxWidth: 200,

453

maxHeight: 30,

454

style: {

455

fontFamily: 'Inter, Arial, sans-serif',

456

fontWeight: 'bold'

457

}

458

});

459

460

// Batch text measurement for better performance

461

const labels = ['Label 1', 'Label 2', 'Label 3', 'Very Long Label Name'];

462

const labelDimensions = getMultipleTextDimensions({

463

texts: labels,

464

style: { fontSize: 12, fontFamily: 'Inter' }

465

});

466

467

// Find maximum width for layout calculations

468

const maxLabelWidth = Math.max(...labelDimensions.map(d => d.width));

469

```

470

471

### Advanced Styling Patterns

472

473

```typescript

474

import { styled, css, useTheme } from '@superset-ui/core';

475

476

// Conditional styling based on props

477

interface CardProps {

478

variant?: 'primary' | 'secondary' | 'danger';

479

size?: 'small' | 'medium' | 'large';

480

}

481

482

const StyledCard = styled.div<CardProps>`

483

${({ theme }) => css`

484

border-radius: ${theme.borderRadius}px;

485

padding: ${theme.gridUnit * 2}px;

486

font-family: ${theme.typography.families.sansSerif};

487

transition: all ${theme.transitionTiming}s ease;

488

`}

489

490

${({ theme, variant = 'primary' }) => {

491

const colorMap = {

492

primary: theme.colors.primary,

493

secondary: theme.colors.secondary,

494

danger: theme.colors.error

495

};

496

497

const colors = colorMap[variant];

498

499

return css`

500

background-color: ${colors.light4};

501

border: 1px solid ${colors.light2};

502

color: ${colors.dark2};

503

`;

504

}}

505

506

${({ theme, size = 'medium' }) => {

507

const sizeMap = {

508

small: theme.gridUnit * 2,

509

medium: theme.gridUnit * 4,

510

large: theme.gridUnit * 6

511

};

512

513

return css`

514

padding: ${sizeMap[size]}px;

515

font-size: ${theme.typography.sizes[size === 'small' ? 's' : size === 'large' ? 'l' : 'm']}px;

516

`;

517

}}

518

`;

519

520

// Dynamic styling with CSS variables

521

const DynamicStyledComponent = styled.div`

522

${({ theme }) => {

523

// Set CSS custom properties from theme

524

return css`

525

--primary-color: ${theme.colors.primary.base};

526

--secondary-color: ${theme.colors.secondary.base};

527

--border-radius: ${theme.borderRadius}px;

528

--grid-unit: ${theme.gridUnit}px;

529

530

background: var(--primary-color);

531

border-radius: var(--border-radius);

532

padding: calc(var(--grid-unit) * 2);

533

534

.nested-element {

535

background: var(--secondary-color);

536

margin: var(--grid-unit);

537

}

538

`;

539

}}

540

`;

541

```

542

543

### Responsive Design with Theme

544

545

```typescript

546

import { styled, css } from '@superset-ui/core';

547

548

// Responsive breakpoints (not in theme but commonly used)

549

const breakpoints = {

550

xs: '0px',

551

sm: '576px',

552

md: '768px',

553

lg: '992px',

554

xl: '1200px'

555

};

556

557

const media = {

558

xs: `@media (min-width: ${breakpoints.xs})`,

559

sm: `@media (min-width: ${breakpoints.sm})`,

560

md: `@media (min-width: ${breakpoints.md})`,

561

lg: `@media (min-width: ${breakpoints.lg})`,

562

xl: `@media (min-width: ${breakpoints.xl})`

563

};

564

565

// Responsive styled component

566

const ResponsiveGrid = styled.div`

567

${({ theme }) => css`

568

display: grid;

569

gap: ${theme.gridUnit * 2}px;

570

padding: ${theme.gridUnit * 2}px;

571

572

${media.xs} {

573

grid-template-columns: 1fr;

574

}

575

576

${media.sm} {

577

grid-template-columns: repeat(2, 1fr);

578

}

579

580

${media.md} {

581

grid-template-columns: repeat(3, 1fr);

582

}

583

584

${media.lg} {

585

grid-template-columns: repeat(4, 1fr);

586

}

587

`}

588

`;

589

```

590

591

### Color Utilities and Helpers

592

593

```typescript

594

import {

595

CategoricalColorNamespace,

596

getSharedLabelColor,

597

BRAND_COLOR

598

} from '@superset-ui/core';

599

600

// Shared color management across dashboard

601

const labelColorManager = getSharedLabelColor();

602

603

// Add colors for specific data labels

604

labelColorManager.addSlice('Sales', '#FF6B6B', 'd3Category10', 'dashboard_1');

605

labelColorManager.addSlice('Marketing', '#4ECDC4', 'd3Category10', 'dashboard_1');

606

607

// Get consistent colors across charts

608

const getConsistentColor = (label: string, namespace: string) => {

609

return CategoricalColorNamespace.getColor(label, 'd3Category10', namespace);

610

};

611

612

// Clear colors when dashboard changes

613

const clearDashboardColors = (namespace: string) => {

614

labelColorManager.clear('d3Category10', namespace);

615

};

616

617

// Use brand color for primary elements

618

const brandButton = styled.button`

619

background-color: ${BRAND_COLOR};

620

color: white;

621

`;

622

```

623

624

### Layout Margin Utilities

625

626

```typescript

627

import { mergeMargin, parseLength } from '@superset-ui/core';

628

629

// Merge multiple margin configurations

630

const baseMargin = { top: 10, right: 15, bottom: 10, left: 15 };

631

const titleMargin = { top: 20, bottom: 5 };

632

const finalMargin = mergeMargin(baseMargin, titleMargin);

633

// Result: { top: 20, right: 15, bottom: 5, left: 15 }

634

635

// Parse CSS length values

636

const numericValue1 = parseLength('16px'); // 16

637

const numericValue2 = parseLength('1.5em'); // Converted to pixels based on context

638

const numericValue3 = parseLength(20); // 20

639

640

// Calculate responsive margins

641

const calculateResponsiveMargin = (baseSize: number) => {

642

const sm = parseLength(`${baseSize * 0.5}px`);

643

const md = parseLength(`${baseSize}px`);

644

const lg = parseLength(`${baseSize * 1.5}px`);

645

646

return { sm, md, lg };

647

};

648

```

649

650

## Related Documentation

651

652

- [Core Models & Utilities](./core-models.md) - Registry system for color schemes

653

- [Data Formatting](./data-formatting.md) - Formatter integration with styling

654

- [Plugin System](./plugin-system.md) - Chart component styling

655

- [Dashboard Components](./dashboard.md) - Dashboard layout and styling