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

utility-components.mddocs/

0

# Utility Components

1

2

Additional UI components and utility functions that support accessibility, navigation, layout, and component development patterns within the @keystone-ui/core ecosystem.

3

4

## Capabilities

5

6

### VisuallyHidden Component

7

8

Accessibility component that hides content visually while keeping it available to screen readers and assistive technologies.

9

10

```typescript { .api }

11

/**

12

* Component for screen reader-only content

13

* @param props - Content and element type props

14

* @returns JSX element hidden visually but accessible to screen readers

15

*/

16

function VisuallyHidden(props: VisuallyHiddenProps): JSX.Element;

17

18

interface VisuallyHiddenProps {

19

/** Content to hide visually but keep accessible */

20

children?: ReactNode;

21

/** Element or component to render as */

22

as?: ElementType;

23

}

24

25

/**

26

* CSS styles object for creating visually hidden content

27

*/

28

const visuallyHiddenStyles: {

29

readonly border: 0;

30

readonly clip: 'rect(0, 0, 0, 0)';

31

readonly height: 1;

32

readonly overflow: 'hidden';

33

readonly padding: 0;

34

readonly position: 'absolute';

35

readonly whiteSpace: 'nowrap';

36

readonly width: 1;

37

};

38

```

39

40

**Usage Examples:**

41

42

```typescript

43

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

44

45

// Screen reader instructions

46

<button>

47

<IconEdit />

48

<VisuallyHidden>Edit user profile</VisuallyHidden>

49

</button>

50

51

// Form labels for icon-only inputs

52

<div>

53

<VisuallyHidden as="label" htmlFor="search">

54

Search products

55

</VisuallyHidden>

56

<input id="search" type="search" placeholder="Search..." />

57

</div>

58

59

// Skip navigation link

60

<VisuallyHidden as="a" href="#main-content">

61

Skip to main content

62

</VisuallyHidden>

63

64

// Custom element type

65

<VisuallyHidden as="h2">

66

Section heading for screen readers only

67

</VisuallyHidden>

68

```

69

70

### Link Component

71

72

Styled link component with theme-integrated colors and hover states.

73

74

```typescript { .api }

75

/**

76

* Themed link component with hover states

77

* @param props - Link styling and content props

78

* @returns JSX element with theme-based link styling

79

*/

80

function Link(props: LinkProps): JSX.Element;

81

82

interface LinkProps {

83

/** Element or component to render as */

84

as?: ElementType;

85

/** Child content */

86

children?: ReactNode;

87

/** All other HTML anchor attributes */

88

[key: string]: any;

89

}

90

```

91

92

**Usage Examples:**

93

94

```typescript

95

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

96

97

// Basic themed link

98

<Link href="/about">About Us</Link>

99

100

// Custom element (React Router Link)

101

<Link as={RouterLink} to="/dashboard">

102

Dashboard

103

</Link>

104

105

// External link

106

<Link href="https://keystonejs.com" target="_blank" rel="noopener">

107

KeystoneJS

108

</Link>

109

110

// Button-styled link

111

<Link

112

as="button"

113

onClick={handleClick}

114

style={{ background: 'none', border: 'none' }}

115

>

116

Click me

117

</Link>

118

```

119

120

### Divider Component

121

122

Visual separator component with horizontal or vertical orientation and theme-integrated styling.

123

124

```typescript { .api }

125

/**

126

* Visual separator with orientation support

127

* @param props - Divider styling and layout props

128

* @returns JSX element as visual separator

129

*/

130

function Divider(props: DividerProps): JSX.Element;

131

132

interface DividerProps extends MarginProps {

133

/** Divider color from theme palette */

134

color?: ResponsiveProp<keyof Theme['palette']>;

135

/** Divider orientation */

136

orientation?: 'horizontal' | 'vertical';

137

/** CSS class name */

138

className?: string;

139

/** No children allowed */

140

children?: never;

141

}

142

```

143

144

**Usage Examples:**

145

146

```typescript

147

import { Divider, Stack, Inline, Text } from "@keystone-ui/core";

148

149

// Horizontal divider (default)

150

<Stack gap="medium">

151

<Text>Section 1</Text>

152

<Divider />

153

<Text>Section 2</Text>

154

</Stack>

155

156

// Vertical divider

157

<Inline gap="medium" align="center">

158

<Text>Item 1</Text>

159

<Divider orientation="vertical" />

160

<Text>Item 2</Text>

161

</Inline>

162

163

// Custom colored divider with spacing

164

<Divider

165

color="blue300"

166

marginY="large"

167

orientation="horizontal"

168

/>

169

170

// Responsive divider color

171

<Divider color={["neutral300", "neutral400"]} />

172

```

173

174

### Center Component

175

176

Layout component for centering content both horizontally and vertically.

177

178

```typescript { .api }

179

/**

180

* Component for centering content horizontally and vertically

181

* @param props - Center layout and styling props

182

* @returns JSX element with centered content

183

*/

184

function Center(props: CenterProps): JSX.Element;

185

186

interface CenterProps extends BoxProps {

187

/** Fill entire viewport height and width */

188

fillView?: boolean;

189

}

190

```

191

192

**Usage Examples:**

193

194

```typescript

195

import { Center, Text, Stack } from "@keystone-ui/core";

196

197

// Center content in container

198

<Center height="200px" background="neutral100">

199

<Text>Centered content</Text>

200

</Center>

201

202

// Full viewport centering for loading states

203

<Center fillView>

204

<Stack gap="medium" align="center">

205

<Spinner />

206

<Text>Loading...</Text>

207

</Stack>

208

</Center>

209

210

// Center with additional styling

211

<Center

212

height="300px"

213

background="blue50"

214

rounding="large"

215

padding="xlarge"

216

>

217

<Text size="large" textAlign="center">

218

Welcome Message

219

</Text>

220

</Center>

221

```

222

223

## Utility Functions

224

225

### Polymorphic Component Helper

226

227

Utility function for creating components that support the `as` prop for element/component polymorphism.

228

229

```typescript { .api }

230

/**

231

* Creates a component with polymorphic `as` prop support

232

* @param render - Render function receiving props and ref

233

* @returns Component with polymorphic behavior

234

*/

235

function forwardRefWithAs<DefaultElementType extends ElementType, BaseProps>(

236

render: (

237

props: BaseProps & { as?: ElementType },

238

ref: React.Ref<any>

239

) => ReactNode

240

): CompWithAsProp<BaseProps, DefaultElementType>;

241

242

type CompWithAsProp<Props, DefaultElementType extends ElementType> = <

243

Comp extends ElementType = DefaultElementType

244

>(

245

props: AsProp<Comp, Props> & Props

246

) => ReactElement;

247

```

248

249

**Usage Examples:**

250

251

```typescript

252

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

253

254

// Create custom polymorphic component

255

const MyButton = forwardRefWithAs<'button', { variant?: 'primary' | 'secondary' }>(

256

({ variant = 'primary', as: Tag = 'button', ...props }, ref) => {

257

return (

258

<Tag

259

ref={ref}

260

className={`btn btn-${variant}`}

261

{...props}

262

/>

263

);

264

}

265

);

266

267

// Usage with different elements

268

<MyButton>Default button</MyButton>

269

<MyButton as="a" href="/link">Link button</MyButton>

270

<MyButton as={CustomComponent}>Custom component</MyButton>

271

```

272

273

### Element Tag Helper

274

275

Utility function to determine appropriate child element based on parent element context.

276

277

```typescript { .api }

278

/**

279

* Returns appropriate child tag for a parent element

280

* @param parentTag - Parent element type

281

* @returns Appropriate child element tag

282

*/

283

function getChildTag(parentTag?: ElementType): ElementType;

284

```

285

286

**Usage Examples:**

287

288

```typescript

289

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

290

291

// Used internally by Stack and Inline components

292

function MyListComponent({ as = 'div', children }) {

293

const ChildTag = getChildTag(as);

294

295

return (

296

<as>

297

{children.map(child => (

298

<ChildTag key={child.id}>

299

{child.content}

300

</ChildTag>

301

))}

302

</as>

303

);

304

}

305

306

// Returns 'li' for 'ul' or 'ol', 'div' for others

307

getChildTag('ul'); // 'li'

308

getChildTag('ol'); // 'li'

309

getChildTag('div'); // 'div'

310

```

311

312

### ID Generation Utilities

313

314

Utilities for generating unique IDs for accessibility and component relationships.

315

316

```typescript { .api }

317

/**

318

* Generates unique ID for components, with SSR support

319

* @param idFromProps - Optional ID provided via props

320

* @returns Unique string ID or undefined

321

*/

322

function useId(idFromProps?: string | null): string | undefined;

323

324

/**

325

* Creates compound ID from multiple inputs

326

* @param args - String, number, or null/undefined values to combine

327

* @returns Compound ID string with null/undefined values filtered out

328

*/

329

function makeId(...args: (string | number | null | undefined)[]): string;

330

```

331

332

**Usage Examples:**

333

334

```typescript

335

import { useId, makeId } from "@keystone-ui/core";

336

337

function FormField({ id: providedId, label, ...props }) {

338

// Generate ID if not provided

339

const id = useId(providedId);

340

const labelId = makeId(id, 'label');

341

const helpId = makeId(id, 'help');

342

343

return (

344

<div>

345

<label id={labelId} htmlFor={id}>

346

{label}

347

</label>

348

<input

349

id={id}

350

aria-labelledby={labelId}

351

aria-describedby={helpId}

352

{...props}

353

/>

354

<div id={helpId}>

355

Help text

356

</div>

357

</div>

358

);

359

}

360

361

// makeId filters out null/undefined values

362

makeId('field', null, 'label', undefined); // 'field--label'

363

makeId('modal', 123, 'content'); // 'modal--123--content'

364

```

365

366

### Development Warning Utility

367

368

Development-only warning utility for component validation and debugging.

369

370

```typescript { .api }

371

/**

372

* Logs warning to console in development mode only

373

* @param condition - When true, warning will be logged

374

* @param message - Warning message to display

375

*/

376

function devWarning(condition: boolean, message: string): void;

377

```

378

379

**Usage Examples:**

380

381

```typescript

382

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

383

384

function MyComponent({ value, onChange }) {

385

// Warn about missing onChange handler

386

devWarning(

387

value !== undefined && !onChange,

388

'MyComponent: controlled component is missing onChange handler'

389

);

390

391

// Warn about invalid prop combinations

392

devWarning(

393

variant === 'custom' && !customStyle,

394

'MyComponent: customStyle prop is required when variant="custom"'

395

);

396

397

return <div>{/* component content */}</div>;

398

}

399

```

400

401

### Responsive Prop Mapping

402

403

Utility function for mapping responsive prop values to theme scales, used internally by components for responsive design.

404

405

```typescript { .api }

406

/**

407

* Maps responsive prop values to theme scale values

408

* @param value - Single value or array of responsive values

409

* @param valueMap - Theme scale object to map values against

410

* @returns Mapped value(s) for CSS properties

411

*/

412

function mapResponsiveProp<

413

Map extends Record<string, string | number>,

414

Keys extends keyof Map

415

>(

416

value: Keys | readonly (Keys | null)[],

417

valueMap: Map

418

): string | number | (string | number | null)[];

419

```

420

421

**Usage Examples:**

422

423

```typescript

424

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

425

426

function CustomComponent({ padding, margin }) {

427

const theme = useTheme();

428

429

// Map single values

430

const paddingValue = mapResponsiveProp(padding, theme.spacing);

431

// padding = "medium" -> theme.spacing.medium (12)

432

433

// Map responsive arrays

434

const marginValue = mapResponsiveProp(

435

["small", "medium", "large"],

436

theme.spacing

437

);

438

// Returns [8, 12, 16]

439

440

// Handle null values in arrays

441

const responsiveValue = mapResponsiveProp(

442

["small", null, "large"],

443

theme.spacing

444

);

445

// Returns [8, null, 16]

446

447

return (

448

<div style={{

449

padding: paddingValue,

450

margin: marginValue

451

}}>

452

Content

453

</div>

454

);

455

}

456

457

// Used internally by Box component

458

const boxStyles = {

459

padding: mapResponsiveProp(paddingProp, theme.spacing),

460

backgroundColor: mapResponsiveProp(backgroundProp, theme.palette)

461

};

462

```

463

464

### Portal Component

465

466

Utility component for rendering content outside the normal component tree using React portals.

467

468

```typescript { .api }

469

/**

470

* Renders children in a portal to document.body

471

* @param props - Portal props with children

472

* @returns React portal or null for SSR compatibility

473

*/

474

function Portal(props: PortalProps): React.ReactPortal | null;

475

476

interface PortalProps {

477

children: ReactElement;

478

}

479

```

480

481

**Usage Examples:**

482

483

```typescript

484

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

485

486

function Modal({ isOpen, children }) {

487

if (!isOpen) return null;

488

489

return (

490

<Portal>

491

<div className="modal-overlay">

492

<div className="modal-content">

493

{children}

494

</div>

495

</div>

496

</Portal>

497

);

498

}

499

500

function Tooltip({ content, children }) {

501

return (

502

<div>

503

{children}

504

<Portal>

505

<div className="tooltip">

506

{content}

507

</div>

508

</Portal>

509

</div>

510

);

511

}

512

```

513

514

## TypeScript Utilities

515

516

### Identity Type Helper

517

518

TypeScript utility for preserving generic type information while enabling type inference.

519

520

```typescript { .api }

521

/**

522

* TypeScript utility for preserving generic types with inference

523

* @returns Function that preserves and validates generic type

524

*/

525

function identityType<T>(): <U extends T>(u: U) => U;

526

```

527

528

**Usage Examples:**

529

530

```typescript

531

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

532

533

// Define strongly-typed configuration objects

534

const createConfig = identityType<{ name: string; value: number }>()({

535

name: 'example',

536

value: 42

537

// TypeScript will enforce this shape

538

});

539

540

// Used internally for theme type safety

541

const toneConfig = identityType<Record<string, ToneColor>>()({

542

primary: { fill: '#blue', tint: '#lightblue' },

543

secondary: { fill: '#gray', tint: '#lightgray' }

544

});

545

```

546

547

All utility components and functions are designed to work seamlessly with the theme system and provide consistent behavior across the @keystone-ui/core ecosystem.