or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-wrapper.mdemotion-integration.mdindex.mdlayout-components.mdstate-management.mdtheme-system.mdtypography-components.mdutility-components.md
tile.json

emotion-integration.mddocs/

0

# Emotion Integration

1

2

@keystone-ui/core provides re-exported Emotion functions to ensure consistent CSS-in-JS usage across the KeystoneJS ecosystem. These re-exports guarantee version compatibility and provide a single import source for Emotion functionality.

3

4

## Capabilities

5

6

### CSS Styling Function

7

8

Core CSS-in-JS styling function for creating dynamic styles with full TypeScript support.

9

10

```typescript { .api }

11

/**

12

* CSS-in-JS styling function from @emotion/react

13

* @param template - Template literal with CSS styles

14

* @param args - Interpolated values and functions

15

* @returns Serialized CSS styles for use with css prop

16

*/

17

function css(template: TemplateStringsArray, ...args: any[]): SerializedStyles;

18

19

/**

20

* CSS styling function for object-based styles

21

* @param styles - CSS styles as JavaScript object

22

* @returns Serialized CSS styles for use with css prop

23

*/

24

function css(styles: CSSObject): SerializedStyles;

25

```

26

27

**Usage Examples:**

28

29

```typescript

30

import { css, useTheme } from "@keystone-ui/core";

31

32

// Template literal styles

33

const buttonStyles = css`

34

padding: 12px 24px;

35

border-radius: 6px;

36

background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);

37

color: white;

38

border: none;

39

cursor: pointer;

40

41

&:hover {

42

transform: translateY(-2px);

43

box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);

44

}

45

`;

46

47

// Object-based styles with theme integration

48

function ThemedButton() {

49

const theme = useTheme();

50

51

const styles = css({

52

padding: theme.spacing.medium,

53

backgroundColor: theme.colors.linkColor,

54

color: theme.colors.background,

55

borderRadius: theme.radii.small,

56

border: 'none',

57

fontFamily: theme.typography.fontFamily.body,

58

fontSize: theme.typography.fontSize.medium,

59

fontWeight: theme.typography.fontWeight.medium,

60

cursor: 'pointer',

61

62

'&:hover': {

63

backgroundColor: theme.colors.linkHoverColor,

64

},

65

66

'&:focus': {

67

outline: 'none',

68

boxShadow: `0 0 0 2px ${theme.colors.focusRing}`,

69

}

70

});

71

72

return <button css={styles}>Themed Button</button>;

73

}

74

75

// Dynamic styles with interpolation

76

const getDynamicStyles = (isActive: boolean, theme: Theme) => css`

77

color: ${isActive ? theme.colors.linkColor : theme.colors.foreground};

78

font-weight: ${isActive ? theme.typography.fontWeight.bold : theme.typography.fontWeight.regular};

79

80

${isActive && `

81

&::after {

82

content: '';

83

position: absolute;

84

bottom: -2px;

85

left: 0;

86

right: 0;

87

height: 2px;

88

background: ${theme.colors.linkColor};

89

}

90

`}

91

`;

92

```

93

94

### JSX Pragma

95

96

JSX pragma function required for Emotion's CSS-in-JS functionality in older JSX runtime configurations.

97

98

```typescript { .api }

99

/**

100

* JSX pragma function for Emotion CSS-in-JS support

101

* @param type - React element type

102

* @param props - Element props including css prop

103

* @param children - Child elements

104

* @returns React element with Emotion styles applied

105

*/

106

function jsx(type: any, props: any, ...children: any[]): any;

107

```

108

109

**Usage Examples:**

110

111

```typescript

112

/** @jsxRuntime classic */

113

/** @jsx jsx */

114

import { jsx, css } from "@keystone-ui/core";

115

116

// Component using jsx pragma (legacy)

117

function LegacyComponent() {

118

return (

119

<div css={css`

120

padding: 16px;

121

background: #f5f5f5;

122

`}>

123

Content with Emotion styles

124

</div>

125

);

126

}

127

128

// Modern usage with automatic JSX runtime (recommended)

129

import { css } from "@keystone-ui/core";

130

131

function ModernComponent() {

132

return (

133

<div css={css`

134

padding: 16px;

135

background: #f5f5f5;

136

`}>

137

Content with Emotion styles

138

</div>

139

);

140

}

141

```

142

143

### CSS Keyframes Animation

144

145

Function for creating CSS keyframe animations with Emotion.

146

147

```typescript { .api }

148

/**

149

* Creates CSS keyframes for animations

150

* @param template - Template literal with keyframe definitions

151

* @param args - Interpolated values

152

* @returns Keyframes object for use in animation properties

153

*/

154

function keyframes(template: TemplateStringsArray, ...args: any[]): Keyframes;

155

156

/**

157

* Creates CSS keyframes from object definition

158

* @param keyframeObject - Object with keyframe percentages and styles

159

* @returns Keyframes object for use in animation properties

160

*/

161

function keyframes(keyframeObject: Record<string, CSSObject>): Keyframes;

162

```

163

164

**Usage Examples:**

165

166

```typescript

167

import { keyframes, css, useTheme } from "@keystone-ui/core";

168

169

// Fade in animation

170

const fadeIn = keyframes`

171

from {

172

opacity: 0;

173

transform: translateY(20px);

174

}

175

to {

176

opacity: 1;

177

transform: translateY(0);

178

}

179

`;

180

181

// Pulse animation with theme colors

182

function PulseLoader() {

183

const theme = useTheme();

184

185

const pulse = keyframes`

186

0%, 100% {

187

background-color: ${theme.colors.linkColor};

188

transform: scale(1);

189

}

190

50% {

191

background-color: ${theme.colors.linkHoverColor};

192

transform: scale(1.1);

193

}

194

`;

195

196

const styles = css`

197

width: 40px;

198

height: 40px;

199

border-radius: 50%;

200

animation: ${pulse} 1.5s ease-in-out infinite;

201

`;

202

203

return <div css={styles} />;

204

}

205

206

// Object-based keyframes

207

const slideIn = keyframes({

208

'0%': {

209

transform: 'translateX(-100%)',

210

opacity: 0

211

},

212

'100%': {

213

transform: 'translateX(0)',

214

opacity: 1

215

}

216

});

217

218

const slideInStyles = css`

219

animation: ${slideIn} 0.3s ease-out;

220

`;

221

```

222

223

### Global Styles Component

224

225

Component for applying global CSS styles to the entire application.

226

227

```typescript { .api }

228

/**

229

* Component for injecting global CSS styles

230

* @param props - Global styles configuration

231

* @returns JSX element that applies global styles

232

*/

233

function Global(props: GlobalProps): JSX.Element;

234

235

interface GlobalProps {

236

/** CSS styles to apply globally */

237

styles: CSSObject | SerializedStyles | string;

238

}

239

```

240

241

**Usage Examples:**

242

243

```typescript

244

import { Global, css, useTheme } from "@keystone-ui/core";

245

246

// Global reset styles

247

function GlobalReset() {

248

return (

249

<Global

250

styles={css`

251

* {

252

box-sizing: border-box;

253

}

254

255

body {

256

margin: 0;

257

padding: 0;

258

}

259

260

h1, h2, h3, h4, h5, h6 {

261

margin: 0;

262

}

263

`}

264

/>

265

);

266

}

267

268

// Theme-based global styles

269

function ThemedGlobalStyles() {

270

const theme = useTheme();

271

272

return (

273

<Global

274

styles={{

275

body: {

276

fontFamily: theme.typography.fontFamily.body,

277

fontSize: theme.typography.fontSize.medium,

278

lineHeight: theme.typography.leading.base,

279

color: theme.colors.foreground,

280

backgroundColor: theme.colors.background

281

},

282

283

'h1, h2, h3, h4, h5, h6': {

284

fontFamily: theme.typography.fontFamily.heading,

285

color: theme.colors.foregroundMuted

286

},

287

288

'a': {

289

color: theme.colors.linkColor,

290

'&:hover': {

291

color: theme.colors.linkHoverColor

292

}

293

}

294

}}

295

/>

296

);

297

}

298

```

299

300

### ClassNames Render Prop Component

301

302

Component providing render prop pattern for dynamic CSS class generation.

303

304

```typescript { .api }

305

/**

306

* Render prop component for dynamic class name generation

307

* @param props - ClassNames render prop configuration

308

* @returns Result of children render function

309

*/

310

function ClassNames(props: ClassNamesProps): ReactNode;

311

312

interface ClassNamesProps {

313

/** Render function receiving class name utilities */

314

children: (utilities: ClassNameUtilities) => ReactNode;

315

}

316

317

interface ClassNameUtilities {

318

/** Function to generate CSS class names from styles */

319

css: (...styles: (CSSObject | SerializedStyles)[]) => string;

320

/** CSS styling function */

321

cx: typeof css;

322

}

323

```

324

325

**Usage Examples:**

326

327

```typescript

328

import { ClassNames, useTheme } from "@keystone-ui/core";

329

330

// Dynamic class names with conditional styling

331

function ConditionalButton({ variant, isActive }) {

332

const theme = useTheme();

333

334

return (

335

<ClassNames>

336

{({ css, cx }) => (

337

<button

338

className={cx(

339

css({

340

padding: theme.spacing.medium,

341

border: 'none',

342

borderRadius: theme.radii.small,

343

fontFamily: theme.typography.fontFamily.body,

344

cursor: 'pointer'

345

}),

346

347

variant === 'primary' && css({

348

backgroundColor: theme.colors.linkColor,

349

color: theme.colors.background

350

}),

351

352

variant === 'secondary' && css({

353

backgroundColor: theme.colors.backgroundMuted,

354

color: theme.colors.foreground,

355

border: `1px solid ${theme.colors.border}`

356

}),

357

358

isActive && css({

359

transform: 'scale(0.95)',

360

opacity: 0.8

361

})

362

)}

363

>

364

Dynamic Button

365

</button>

366

)}

367

</ClassNames>

368

);

369

}

370

371

// Integration with external class libraries

372

function StyledComponent({ className }) {

373

return (

374

<ClassNames>

375

{({ css, cx }) => (

376

<div

377

className={cx(

378

className, // External classes

379

css` // Emotion styles

380

padding: 16px;

381

margin: 8px;

382

`

383

)}

384

>

385

Combined styling

386

</div>

387

)}

388

</ClassNames>

389

);

390

}

391

```

392

393

## TypeScript Integration

394

395

All Emotion functions include full TypeScript support with proper type inference:

396

397

```typescript

398

import { css, keyframes, Theme } from "@keystone-ui/core";

399

400

// Type-safe theme usage

401

const createThemedStyles = (theme: Theme) => css({

402

color: theme.colors.foreground, // ✓ Type-safe

403

fontSize: theme.typography.fontSize.large, // ✓ Type-safe

404

// invalidProperty: theme.nonexistent // ✗ TypeScript error

405

});

406

407

// Typed keyframes

408

const typedAnimation: Keyframes = keyframes`

409

from { opacity: 0; }

410

to { opacity: 1; }

411

`;

412

413

// Template literals with interpolation

414

const dynamicStyles = (isVisible: boolean) => css`

415

opacity: ${isVisible ? 1 : 0};

416

transition: opacity 0.2s ease;

417

`;

418

```

419

420

## Performance Considerations

421

422

### Style Caching

423

424

Emotion automatically caches generated styles for optimal performance:

425

426

```typescript

427

// Styles are cached by their serialized form

428

const cachedStyles = css`

429

color: red;

430

font-size: 16px;

431

`;

432

433

// Reusing the same styles won't regenerate CSS

434

const sameStyles = css`

435

color: red;

436

font-size: 16px;

437

`; // Uses cached version

438

```

439

440

### Bundle Size Optimization

441

442

The re-exported functions help minimize bundle size by ensuring only one Emotion version is included in the final bundle.

443

444

### Server-Side Rendering

445

446

All Emotion functions are fully compatible with server-side rendering when used within the @keystone-ui/core ecosystem.

447

448

## CSS Normalization

449

450

### Normalize Styles

451

452

Pre-built CSS normalization styles for consistent cross-browser rendering.

453

454

```typescript { .api }

455

/**

456

* CSS normalization styles based on normalize.css v8.0.1

457

* Provides consistent default styling across browsers

458

*/

459

const normalize: SerializedStyles;

460

```

461

462

**Usage Examples:**

463

464

```typescript

465

import { normalize, Global } from "@keystone-ui/core";

466

467

// Apply normalize globally

468

function App() {

469

return (

470

<>

471

<Global styles={normalize} />

472

<div>Your app content with normalized styles</div>

473

</>

474

);

475

}

476

477

// Combine with custom global styles

478

function AppWithCustomGlobals() {

479

return (

480

<>

481

<Global styles={[

482

normalize,

483

css`

484

body {

485

font-family: system-ui, sans-serif;

486

line-height: 1.6;

487

}

488

489

* {

490

box-sizing: border-box;

491

}

492

`

493

]} />

494

<div>Your app content</div>

495

</>

496

);

497

}

498

499

// Use with Core component (recommended)

500

import { Core } from "@keystone-ui/core";

501

502

function AppWithCore() {

503

return (

504

<Core>

505

{/* Core component automatically includes normalize when includeNormalize=true */}

506

<div>Your app content</div>

507

</Core>

508

);

509

}

510

```

511

512

The normalize styles include:

513

- Consistent box model defaults

514

- Form element styling normalization

515

- Typography baseline normalization

516

- Focus outline removal (replaced by theme-based focus indicators)

517

- Cross-browser compatibility fixes