@mond-design-system/react 1.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1306 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.css +1389 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.cts +942 -0
- package/dist/index.d.ts +942 -0
- package/dist/index.js +1246 -0
- package/dist/index.js.map +1 -0
- package/package.json +54 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,942 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { CSSProperties, HTMLAttributes, JSX, ReactElement, ReactNode, ButtonHTMLAttributes, ElementType, Ref, AnchorHTMLAttributes, InputHTMLAttributes, TextareaHTMLAttributes, SelectHTMLAttributes, LiHTMLAttributes, MouseEventHandler, RefObject, KeyboardEvent } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Join class names, dropping anything falsy.
|
|
6
|
+
*
|
|
7
|
+
* Every component takes a `className` from the call site and owns one of its
|
|
8
|
+
* own from a CSS Module, so the merge happens in one place rather than in
|
|
9
|
+
* forty slightly different inline expressions.
|
|
10
|
+
*/
|
|
11
|
+
declare function cx(...parts: Array<string | false | null | undefined>): string;
|
|
12
|
+
/**
|
|
13
|
+
* A style object that may also carry CSS custom properties.
|
|
14
|
+
*
|
|
15
|
+
* `React.CSSProperties` has no index signature, so `{ '--mds-x': 1 }` is a
|
|
16
|
+
* type error against it. Values that genuinely vary per render (a slider's
|
|
17
|
+
* percent, an avatar's pixel size) belong in a custom property the stylesheet
|
|
18
|
+
* reads — this types that without an assertion.
|
|
19
|
+
*/
|
|
20
|
+
type CSSVars = CSSProperties & Record<`--${string}`, string | number>;
|
|
21
|
+
|
|
22
|
+
type TextVariant = "body" | "label" | "note" | "meta" | "eyebrow";
|
|
23
|
+
type TextTone = "primary" | "secondary" | "muted" | "inverse" | "accent" | "on-media" | "danger" | "warning" | "success";
|
|
24
|
+
interface TextProps extends HTMLAttributes<HTMLElement> {
|
|
25
|
+
/** Type role from the core scale. Default "body". */
|
|
26
|
+
variant?: TextVariant;
|
|
27
|
+
/** Element override when the default doesn't fit the markup. */
|
|
28
|
+
as?: keyof JSX.IntrinsicElements;
|
|
29
|
+
/** Semantic color. Variants carry sensible defaults. */
|
|
30
|
+
tone?: TextTone;
|
|
31
|
+
align?: "left" | "center" | "right";
|
|
32
|
+
/** Single-line ellipsis. */
|
|
33
|
+
truncate?: boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Body-copy primitive. One class per type role — screens never hand-roll styled tags.
|
|
37
|
+
*
|
|
38
|
+
* ```tsx
|
|
39
|
+
* <Text>Body copy.</Text>
|
|
40
|
+
* <Text variant="label" as="span">Field label</Text>
|
|
41
|
+
* <Text variant="meta" tone="muted">Updated 2h ago</Text>
|
|
42
|
+
* <Text truncate>Very long single line…</Text>
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
declare function Text({ variant, as, tone, align, truncate, className, ...rest }: TextProps): ReactElement;
|
|
46
|
+
|
|
47
|
+
type HeadingVariant = "display" | "title" | "subtitle";
|
|
48
|
+
type HeadingLevel = 1 | 2 | 3 | 4;
|
|
49
|
+
type HeadingTone = "primary" | "secondary" | "inverse" | "accent" | "on-media";
|
|
50
|
+
interface HeadingProps extends HTMLAttributes<HTMLHeadingElement> {
|
|
51
|
+
/** Document outline level → h1–h4, with a matching default type role. Default 2. */
|
|
52
|
+
level?: HeadingLevel;
|
|
53
|
+
/** Type role override — outline level and visual size are separate concerns. */
|
|
54
|
+
variant?: HeadingVariant;
|
|
55
|
+
tone?: HeadingTone;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Brand headings on the core roles. `level` = semantics, `variant` = size.
|
|
59
|
+
*
|
|
60
|
+
* ```tsx
|
|
61
|
+
* <Heading level={1}>Sessions</Heading>
|
|
62
|
+
* <Heading level={2} variant="subtitle" tone="secondary">This week</Heading>
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
declare function Heading({ level, variant, tone, className, ...rest }: HeadingProps): ReactElement;
|
|
66
|
+
|
|
67
|
+
interface SpinnerProps extends HTMLAttributes<HTMLSpanElement> {
|
|
68
|
+
/** Diameter in px. Default 20. */
|
|
69
|
+
size?: number;
|
|
70
|
+
/** Accessible label. Default "Loading". */
|
|
71
|
+
label?: string;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Indeterminate loading ring. Arc takes currentColor, so it matches whatever
|
|
75
|
+
* text it sits beside. Keyframe is local: CSS Modules localizes
|
|
76
|
+
* animation-name, a global one resolves to nothing. base.css stops it under
|
|
77
|
+
* prefers-reduced-motion.
|
|
78
|
+
*
|
|
79
|
+
* ```tsx
|
|
80
|
+
* <Spinner label="Loading sessions" />
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
declare function Spinner({ size, label, className, style, ...rest }: SpinnerProps): ReactElement;
|
|
84
|
+
|
|
85
|
+
interface IconRenderProps {
|
|
86
|
+
/** Pixel size of the requested step. */
|
|
87
|
+
size: number;
|
|
88
|
+
}
|
|
89
|
+
/** Brand-owned glyph resolver: name → rendered glyph (svg, font ligature, …). */
|
|
90
|
+
type IconRender = (name: string, props: IconRenderProps) => ReactNode;
|
|
91
|
+
interface IconProviderProps {
|
|
92
|
+
render: IconRender;
|
|
93
|
+
children: ReactNode;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Registry seam. The system never bundles an icon set — the app registers its
|
|
97
|
+
* own (lucide, Material Symbols, …) once, at the root. Iconography is brand,
|
|
98
|
+
* like color.
|
|
99
|
+
*
|
|
100
|
+
* ```tsx
|
|
101
|
+
* // App root: map names to your icon set once.
|
|
102
|
+
* <IconProvider render={(name, { size }) => <MyGlyph name={name} width={size} />}>
|
|
103
|
+
* <App />
|
|
104
|
+
* </IconProvider>
|
|
105
|
+
*
|
|
106
|
+
* // Anywhere below:
|
|
107
|
+
* <Icon name="check" size="sm" />
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
declare function IconProvider({ render, children }: IconProviderProps): ReactElement;
|
|
111
|
+
type IconSize = "sm" | "md" | "lg";
|
|
112
|
+
interface IconProps extends HTMLAttributes<HTMLSpanElement> {
|
|
113
|
+
/** Glyph name in the app's registered set. */
|
|
114
|
+
name: string;
|
|
115
|
+
/** Default "md". */
|
|
116
|
+
size?: IconSize;
|
|
117
|
+
/** Accessible name. Omitted = decorative (aria-hidden). */
|
|
118
|
+
label?: string;
|
|
119
|
+
}
|
|
120
|
+
/** A glyph from the app-registered set, sized on the core scale. */
|
|
121
|
+
declare function Icon({ name, size, label, className, ...rest }: IconProps): ReactElement;
|
|
122
|
+
|
|
123
|
+
type ButtonVariant = "primary" | "secondary" | "ghost" | "danger";
|
|
124
|
+
type ButtonSize = "sm" | "md" | "lg";
|
|
125
|
+
interface ButtonBaseProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "type"> {
|
|
126
|
+
variant?: ButtonVariant;
|
|
127
|
+
size?: ButtonSize;
|
|
128
|
+
/** Glyph slots — pass an <Icon> or any node. Agnostic of icon set. */
|
|
129
|
+
iconLeft?: ReactNode;
|
|
130
|
+
iconRight?: ReactNode;
|
|
131
|
+
/** Spinner replaces the left slot; disables and announces busy. */
|
|
132
|
+
loading?: boolean;
|
|
133
|
+
fullWidth?: boolean;
|
|
134
|
+
type?: "button" | "submit" | "reset";
|
|
135
|
+
/** Renders an <a> — for navigation styled as a button. */
|
|
136
|
+
href?: string;
|
|
137
|
+
/** Element override, e.g. a router's Link. */
|
|
138
|
+
as?: ElementType;
|
|
139
|
+
ref?: Ref<HTMLButtonElement>;
|
|
140
|
+
}
|
|
141
|
+
type IconOnlyEnforcement = {
|
|
142
|
+
iconOnly: true;
|
|
143
|
+
"aria-label": string;
|
|
144
|
+
} | {
|
|
145
|
+
iconOnly?: false | undefined;
|
|
146
|
+
};
|
|
147
|
+
type ButtonProps = ButtonBaseProps & IconOnlyEnforcement;
|
|
148
|
+
/**
|
|
149
|
+
* The tappable action. Semantics: button by default, link when `href`/`as` says so.
|
|
150
|
+
*
|
|
151
|
+
* ```tsx
|
|
152
|
+
* <Button onClick={save}>Save</Button>
|
|
153
|
+
* <Button variant="secondary" size="sm">Cancel</Button>
|
|
154
|
+
* <Button variant="danger" loading={deleting} onClick={remove}>Delete</Button>
|
|
155
|
+
* <Button iconOnly aria-label="Close" variant="ghost"><Icon name="close" /></Button>
|
|
156
|
+
* <Button href="/settings">Settings</Button>
|
|
157
|
+
* ```
|
|
158
|
+
*/
|
|
159
|
+
declare function Button({ variant, size, iconLeft, iconRight, loading, disabled, fullWidth, iconOnly, type, href, as, className, children, ...rest }: ButtonProps): ReactElement;
|
|
160
|
+
|
|
161
|
+
type LinkVariant = "inline" | "standalone";
|
|
162
|
+
interface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
163
|
+
/** inline = underlined, lives in running text. standalone = nav/action link. */
|
|
164
|
+
variant?: LinkVariant;
|
|
165
|
+
/** Opens in a new tab with rel protection. */
|
|
166
|
+
external?: boolean;
|
|
167
|
+
/** Element override, e.g. a router's Link. */
|
|
168
|
+
as?: ElementType;
|
|
169
|
+
ref?: Ref<HTMLAnchorElement>;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Text link. Inline links keep their underline: color alone fails WCAG 1.4.1
|
|
173
|
+
* for links inside prose.
|
|
174
|
+
*
|
|
175
|
+
* ```tsx
|
|
176
|
+
* <Text>Read the <Link href="/terms">terms</Link>.</Text>
|
|
177
|
+
* <Link variant="standalone" href="https://example.com" external>Docs</Link>
|
|
178
|
+
* <Link as={NextLink} href="/about">About</Link>
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
declare function Link({ variant, external, as: Element, className, ...rest }: LinkProps): ReactElement;
|
|
182
|
+
|
|
183
|
+
type AvatarSize = "sm" | "md" | "lg";
|
|
184
|
+
interface AvatarProps extends HTMLAttributes<HTMLSpanElement> {
|
|
185
|
+
/** Person's display name — accessible name and initials source. */
|
|
186
|
+
name: string;
|
|
187
|
+
/** Image URL; initials render when absent or empty. */
|
|
188
|
+
src?: string;
|
|
189
|
+
size?: AvatarSize;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Person marker. Image when available, initials otherwise — never an empty circle.
|
|
193
|
+
*
|
|
194
|
+
* ```tsx
|
|
195
|
+
* <Avatar name="Ada Lovelace" src="/ada.jpg" />
|
|
196
|
+
* <Avatar name="Grace Hopper" size="lg" />
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
199
|
+
declare function Avatar({ name, src, size, className, ...rest }: AvatarProps): ReactElement;
|
|
200
|
+
|
|
201
|
+
interface AvatarGroupProps extends HTMLAttributes<HTMLDivElement> {
|
|
202
|
+
/** Avatar children. */
|
|
203
|
+
children: ReactNode;
|
|
204
|
+
/** Visible cap; the rest collapse into "+N". Default 4. */
|
|
205
|
+
max?: number;
|
|
206
|
+
/** Sizes the overflow chip to match the avatars. Default "md". */
|
|
207
|
+
size?: AvatarSize;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Overlapping stack of avatars with a "+N" chip past `max`.
|
|
211
|
+
*
|
|
212
|
+
* ```tsx
|
|
213
|
+
* <AvatarGroup max={3}>
|
|
214
|
+
* <Avatar name="Ada Lovelace" />
|
|
215
|
+
* <Avatar name="Grace Hopper" />
|
|
216
|
+
* <Avatar name="Margaret Hamilton" />
|
|
217
|
+
* <Avatar name="Katherine Johnson" />
|
|
218
|
+
* </AvatarGroup>
|
|
219
|
+
* ```
|
|
220
|
+
*/
|
|
221
|
+
declare function AvatarGroup({ children, max, size, className, ...rest }: AvatarGroupProps): ReactElement;
|
|
222
|
+
|
|
223
|
+
type BadgeTone = "neutral" | "accent" | "danger" | "warning" | "success";
|
|
224
|
+
interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {
|
|
225
|
+
tone?: BadgeTone;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Small status marker — counts, "new", state words. Soft fill, strong text.
|
|
229
|
+
*
|
|
230
|
+
* ```tsx
|
|
231
|
+
* <Badge tone="success">Paid</Badge>
|
|
232
|
+
* <Badge tone="danger">3</Badge>
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
declare function Badge({ tone, className, ...rest }: BadgeProps): ReactElement;
|
|
236
|
+
|
|
237
|
+
type TagTone = "neutral" | "accent";
|
|
238
|
+
interface TagProps extends HTMLAttributes<HTMLSpanElement> {
|
|
239
|
+
children: ReactNode;
|
|
240
|
+
tone?: TagTone;
|
|
241
|
+
/** Renders a labelled ✕ button. Label reads "Remove <content>" when content is text. */
|
|
242
|
+
onRemove?: () => void;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Content label chip — categories, filters, topics.
|
|
246
|
+
*
|
|
247
|
+
* ```tsx
|
|
248
|
+
* <Tag>Design</Tag>
|
|
249
|
+
* <Tag tone="accent" onRemove={() => remove(id)}>Beginner</Tag>
|
|
250
|
+
* ```
|
|
251
|
+
*/
|
|
252
|
+
declare function Tag({ children, tone, onRemove, className, ...rest }: TagProps): ReactElement;
|
|
253
|
+
|
|
254
|
+
interface DividerProps extends HTMLAttributes<HTMLDivElement> {
|
|
255
|
+
orientation?: "horizontal" | "vertical";
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Visual separator. Semantic separator role via <hr>-equivalent div.
|
|
259
|
+
*
|
|
260
|
+
* ```tsx
|
|
261
|
+
* <Divider />
|
|
262
|
+
* <Divider orientation="vertical" />
|
|
263
|
+
* ```
|
|
264
|
+
*/
|
|
265
|
+
declare function Divider({ orientation, className, ...rest }: DividerProps): ReactElement;
|
|
266
|
+
|
|
267
|
+
type SkeletonVariant = "text" | "rect" | "circle";
|
|
268
|
+
interface SkeletonProps extends HTMLAttributes<HTMLSpanElement> {
|
|
269
|
+
variant?: SkeletonVariant;
|
|
270
|
+
/** Any CSS length. Text defaults to full width, one line tall. */
|
|
271
|
+
width?: string;
|
|
272
|
+
height?: string;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Loading placeholder. aria-hidden — the loading announcement belongs to the
|
|
276
|
+
* region (aria-busy), not to each shimmering box.
|
|
277
|
+
*
|
|
278
|
+
* ```tsx
|
|
279
|
+
* <div aria-busy={loading}>
|
|
280
|
+
* {loading ? (
|
|
281
|
+
* <Stack gap="tight">
|
|
282
|
+
* <Skeleton width="40%" />
|
|
283
|
+
* <Skeleton />
|
|
284
|
+
* <Skeleton variant="rect" height="8rem" />
|
|
285
|
+
* </Stack>
|
|
286
|
+
* ) : (
|
|
287
|
+
* content
|
|
288
|
+
* )}
|
|
289
|
+
* </div>
|
|
290
|
+
* ```
|
|
291
|
+
*/
|
|
292
|
+
declare function Skeleton({ variant, width, height, className, style, ...rest }: SkeletonProps): ReactElement;
|
|
293
|
+
|
|
294
|
+
interface ProgressBarProps extends HTMLAttributes<HTMLDivElement> {
|
|
295
|
+
/** 0–100; clamped. Ignored when indeterminate. */
|
|
296
|
+
value?: number;
|
|
297
|
+
/** Accessible name — required. A bare bar announces nothing useful. */
|
|
298
|
+
label: string;
|
|
299
|
+
indeterminate?: boolean;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Determinate or indeterminate progress track.
|
|
303
|
+
*
|
|
304
|
+
* ```tsx
|
|
305
|
+
* <ProgressBar label="Upload" value={64} />
|
|
306
|
+
* <ProgressBar label="Syncing" indeterminate />
|
|
307
|
+
* ```
|
|
308
|
+
*/
|
|
309
|
+
declare function ProgressBar({ value, label, indeterminate, className, style, ...rest }: ProgressBarProps): ReactElement;
|
|
310
|
+
|
|
311
|
+
interface FieldContextValue {
|
|
312
|
+
/** Control id — the label points here. */
|
|
313
|
+
id: string;
|
|
314
|
+
/** Space-joined ids of hint/error, for aria-describedby. */
|
|
315
|
+
describedBy: string | undefined;
|
|
316
|
+
invalid: boolean;
|
|
317
|
+
}
|
|
318
|
+
/** Controls call this to pick up Field wiring. Null outside a Field. */
|
|
319
|
+
declare function useFieldContext(): FieldContextValue | null;
|
|
320
|
+
interface FieldProps {
|
|
321
|
+
label: string;
|
|
322
|
+
children: ReactNode;
|
|
323
|
+
/** Guidance under the control. */
|
|
324
|
+
hint?: string;
|
|
325
|
+
/** Validation message; replaces the hint and flags the control invalid. */
|
|
326
|
+
error?: string;
|
|
327
|
+
required?: boolean;
|
|
328
|
+
className?: string;
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Label + control + hint/error, wired for assistive tech. The control inside
|
|
332
|
+
* (Input, Textarea, Select, …) picks up id, aria-describedby and aria-invalid
|
|
333
|
+
* from context — no manual plumbing at call sites.
|
|
334
|
+
*
|
|
335
|
+
* ```tsx
|
|
336
|
+
* <Field label="Email" hint="Work email preferred" error={errors.email} required>
|
|
337
|
+
* <Input type="email" value={email} onChange={(e) => setEmail(e.target.value)} />
|
|
338
|
+
* </Field>
|
|
339
|
+
* ```
|
|
340
|
+
*/
|
|
341
|
+
declare function Field({ label, children, hint, error, required, className }: FieldProps): ReactElement;
|
|
342
|
+
|
|
343
|
+
type InputSize = "sm" | "md" | "lg";
|
|
344
|
+
interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "size"> {
|
|
345
|
+
size?: InputSize;
|
|
346
|
+
ref?: Ref<HTMLInputElement>;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Single-line text input. Inside a Field it inherits id/description/invalid.
|
|
350
|
+
*
|
|
351
|
+
* ```tsx
|
|
352
|
+
* <Field label="Name">
|
|
353
|
+
* <Input value={name} onChange={(e) => setName(e.target.value)} />
|
|
354
|
+
* </Field>
|
|
355
|
+
*
|
|
356
|
+
* <Input aria-label="Amount" type="number" size="sm" />
|
|
357
|
+
* ```
|
|
358
|
+
*/
|
|
359
|
+
declare function Input({ size, className, ...rest }: InputProps): ReactElement;
|
|
360
|
+
|
|
361
|
+
type PasswordInputProps = Omit<InputProps, "type">;
|
|
362
|
+
/**
|
|
363
|
+
* Password field with a reveal toggle. Composes Input, so inside a Field it
|
|
364
|
+
* inherits id/description/invalid the same way.
|
|
365
|
+
*
|
|
366
|
+
* ```tsx
|
|
367
|
+
* <Field label="Password" hint="At least 12 characters">
|
|
368
|
+
* <PasswordInput autoComplete="new-password" />
|
|
369
|
+
* </Field>
|
|
370
|
+
* ```
|
|
371
|
+
*/
|
|
372
|
+
declare function PasswordInput({ className, ...rest }: PasswordInputProps): ReactElement;
|
|
373
|
+
|
|
374
|
+
interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
375
|
+
/** Character counter under the control; pairs with native maxLength. */
|
|
376
|
+
showCount?: boolean;
|
|
377
|
+
ref?: Ref<HTMLTextAreaElement>;
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Multi-line text input. Inside a Field it inherits id/description/invalid.
|
|
381
|
+
*
|
|
382
|
+
* ```tsx
|
|
383
|
+
* <Field label="Bio">
|
|
384
|
+
* <Textarea maxLength={160} showCount />
|
|
385
|
+
* </Field>
|
|
386
|
+
* ```
|
|
387
|
+
*/
|
|
388
|
+
declare function Textarea({ rows, showCount, className, ...rest }: TextareaProps): ReactElement;
|
|
389
|
+
|
|
390
|
+
type SelectSize = "sm" | "md" | "lg";
|
|
391
|
+
interface SelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, "size"> {
|
|
392
|
+
size?: SelectSize;
|
|
393
|
+
ref?: Ref<HTMLSelectElement>;
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Native select, styled. Native = free keyboard, mobile pickers, screen
|
|
397
|
+
* reader behavior; a custom popover earns its complexity only when options
|
|
398
|
+
* need rich content.
|
|
399
|
+
*
|
|
400
|
+
* ```tsx
|
|
401
|
+
* <Field label="Language">
|
|
402
|
+
* <Select value={lang} onChange={(e) => setLang(e.target.value)}>
|
|
403
|
+
* <option value="de">Deutsch</option>
|
|
404
|
+
* <option value="en">English</option>
|
|
405
|
+
* </Select>
|
|
406
|
+
* </Field>
|
|
407
|
+
* ```
|
|
408
|
+
*/
|
|
409
|
+
declare function Select({ size, className, children, ...rest }: SelectProps): ReactElement;
|
|
410
|
+
|
|
411
|
+
interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "size"> {
|
|
412
|
+
/** Inline label — part of the click target. */
|
|
413
|
+
label: string;
|
|
414
|
+
ref?: Ref<HTMLInputElement>;
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Native checkbox, styled box. Label is the touch target too.
|
|
418
|
+
*
|
|
419
|
+
* ```tsx
|
|
420
|
+
* <Checkbox label="Remember me" defaultChecked />
|
|
421
|
+
* <Checkbox
|
|
422
|
+
* label="Accept terms"
|
|
423
|
+
* checked={accepted}
|
|
424
|
+
* onChange={(e) => setAccepted(e.target.checked)}
|
|
425
|
+
* />
|
|
426
|
+
* ```
|
|
427
|
+
*/
|
|
428
|
+
declare function Checkbox({ label, className, ...rest }: CheckboxProps): ReactElement;
|
|
429
|
+
|
|
430
|
+
interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "size"> {
|
|
431
|
+
/** Inline label — part of the click target. */
|
|
432
|
+
label: string;
|
|
433
|
+
ref?: Ref<HTMLInputElement>;
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Native radio, styled dot. Group by `name`; wrap the group in
|
|
437
|
+
* `<fieldset>`/`<legend>` for a group label.
|
|
438
|
+
*
|
|
439
|
+
* ```tsx
|
|
440
|
+
* <fieldset>
|
|
441
|
+
* <legend>Plan</legend>
|
|
442
|
+
* <Radio name="plan" label="Free" checked={plan === "free"} onChange={() => setPlan("free")} />
|
|
443
|
+
* <Radio name="plan" label="Pro" checked={plan === "pro"} onChange={() => setPlan("pro")} />
|
|
444
|
+
* </fieldset>
|
|
445
|
+
* ```
|
|
446
|
+
*/
|
|
447
|
+
declare function Radio({ label, className, ...rest }: RadioProps): ReactElement;
|
|
448
|
+
|
|
449
|
+
interface SwitchProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "size"> {
|
|
450
|
+
/** Inline label — part of the click target. */
|
|
451
|
+
label: string;
|
|
452
|
+
ref?: Ref<HTMLInputElement>;
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* On/off toggle. Checkbox under the hood with role="switch" — native
|
|
456
|
+
* semantics and forms integration, switch announcement.
|
|
457
|
+
*
|
|
458
|
+
* ```tsx
|
|
459
|
+
* <Switch
|
|
460
|
+
* label="Notifications"
|
|
461
|
+
* checked={enabled}
|
|
462
|
+
* onChange={(e) => setEnabled(e.target.checked)}
|
|
463
|
+
* />
|
|
464
|
+
* ```
|
|
465
|
+
*/
|
|
466
|
+
declare function Switch({ label, className, ...rest }: SwitchProps): ReactElement;
|
|
467
|
+
|
|
468
|
+
interface SegmentOption<T extends string = string> {
|
|
469
|
+
value: T;
|
|
470
|
+
label: string;
|
|
471
|
+
}
|
|
472
|
+
interface SegmentedControlProps<T extends string = string> {
|
|
473
|
+
/** Accessible group name. */
|
|
474
|
+
label: string;
|
|
475
|
+
options: readonly SegmentOption<T>[];
|
|
476
|
+
value: T;
|
|
477
|
+
onChange: (value: T) => void;
|
|
478
|
+
className?: string;
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Exclusive choice among few visible options. Native radios under the hood —
|
|
482
|
+
* free keyboard model and semantics.
|
|
483
|
+
*
|
|
484
|
+
* ```tsx
|
|
485
|
+
* <SegmentedControl
|
|
486
|
+
* label="View"
|
|
487
|
+
* options={[
|
|
488
|
+
* { value: "list", label: "List" },
|
|
489
|
+
* { value: "grid", label: "Grid" },
|
|
490
|
+
* ]}
|
|
491
|
+
* value={view}
|
|
492
|
+
* onChange={setView}
|
|
493
|
+
* />
|
|
494
|
+
* ```
|
|
495
|
+
*/
|
|
496
|
+
declare function SegmentedControl<T extends string = string>({ label, options, value, onChange, className, }: SegmentedControlProps<T>): ReactElement;
|
|
497
|
+
|
|
498
|
+
interface SearchFieldProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "size" | "value" | "onChange"> {
|
|
499
|
+
/** Accessible name. */
|
|
500
|
+
label: string;
|
|
501
|
+
value: string;
|
|
502
|
+
/** Receives the new text — "" when cleared. */
|
|
503
|
+
onChange: (value: string) => void;
|
|
504
|
+
ref?: Ref<HTMLInputElement>;
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Controlled search input with a clear affordance once there is text.
|
|
508
|
+
*
|
|
509
|
+
* ```tsx
|
|
510
|
+
* <SearchField label="Search sessions" value={query} onChange={setQuery} />
|
|
511
|
+
* ```
|
|
512
|
+
*/
|
|
513
|
+
declare function SearchField({ label, value, onChange, className, ...rest }: SearchFieldProps): ReactElement;
|
|
514
|
+
|
|
515
|
+
interface ListGroupProps extends HTMLAttributes<HTMLUListElement> {
|
|
516
|
+
children: ReactNode;
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* Card-styled list container for ListItems.
|
|
520
|
+
*
|
|
521
|
+
* ```tsx
|
|
522
|
+
* <ListGroup>
|
|
523
|
+
* <ListItem
|
|
524
|
+
* title="Profile"
|
|
525
|
+
* description="Name, avatar"
|
|
526
|
+
* leading={<Icon name="user" />}
|
|
527
|
+
* href="/profile"
|
|
528
|
+
* />
|
|
529
|
+
* <ListItem title="Log out" onClick={logout} />
|
|
530
|
+
* </ListGroup>
|
|
531
|
+
* ```
|
|
532
|
+
*/
|
|
533
|
+
declare function ListGroup({ className, ...rest }: ListGroupProps): ReactElement;
|
|
534
|
+
interface ListItemProps extends Omit<LiHTMLAttributes<HTMLLIElement>, "title" | "onClick"> {
|
|
535
|
+
title: string;
|
|
536
|
+
description?: string;
|
|
537
|
+
/** Slot before the text — Avatar, Icon, … */
|
|
538
|
+
leading?: ReactNode;
|
|
539
|
+
/** Slot after the text — Badge, chevron, … */
|
|
540
|
+
trailing?: ReactNode;
|
|
541
|
+
/** Makes the whole row a button. */
|
|
542
|
+
onClick?: () => void;
|
|
543
|
+
/** Makes the whole row a link. Wins over onClick. */
|
|
544
|
+
href?: string;
|
|
545
|
+
}
|
|
546
|
+
/** One row. Static by default; interactive as one whole-row button/link. */
|
|
547
|
+
declare function ListItem({ title, description, leading, trailing, onClick, href, className, ...rest }: ListItemProps): ReactElement;
|
|
548
|
+
|
|
549
|
+
interface EmptyStateProps {
|
|
550
|
+
title: string;
|
|
551
|
+
description?: string;
|
|
552
|
+
/** Illustration or Icon slot. */
|
|
553
|
+
icon?: ReactNode;
|
|
554
|
+
/** Usually a Button. */
|
|
555
|
+
action?: ReactNode;
|
|
556
|
+
className?: string;
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Nothing-here view: explains the empty screen and offers the next step.
|
|
560
|
+
*
|
|
561
|
+
* ```tsx
|
|
562
|
+
* <EmptyState
|
|
563
|
+
* icon={<Icon name="inbox" size="lg" />}
|
|
564
|
+
* title="No sessions yet"
|
|
565
|
+
* description="Create your first session to get started."
|
|
566
|
+
* action={<Button onClick={create}>New session</Button>}
|
|
567
|
+
* />
|
|
568
|
+
* ```
|
|
569
|
+
*/
|
|
570
|
+
declare function EmptyState({ title, description, icon, action, className }: EmptyStateProps): ReactElement;
|
|
571
|
+
|
|
572
|
+
interface TabsProps {
|
|
573
|
+
value: string;
|
|
574
|
+
onChange: (value: string) => void;
|
|
575
|
+
children: ReactNode;
|
|
576
|
+
}
|
|
577
|
+
/**
|
|
578
|
+
* Controlled tabs root. Compose with TabList, Tab, TabPanel.
|
|
579
|
+
*
|
|
580
|
+
* ```tsx
|
|
581
|
+
* <Tabs value={tab} onChange={setTab}>
|
|
582
|
+
* <TabList label="Session details">
|
|
583
|
+
* <Tab value="info">Info</Tab>
|
|
584
|
+
* <Tab value="notes">Notes</Tab>
|
|
585
|
+
* </TabList>
|
|
586
|
+
* <TabPanel value="info">…</TabPanel>
|
|
587
|
+
* <TabPanel value="notes">…</TabPanel>
|
|
588
|
+
* </Tabs>
|
|
589
|
+
* ```
|
|
590
|
+
*/
|
|
591
|
+
declare function Tabs({ value, onChange, children }: TabsProps): ReactElement;
|
|
592
|
+
interface TabListProps extends HTMLAttributes<HTMLDivElement> {
|
|
593
|
+
/** Accessible name for the tab set. */
|
|
594
|
+
label: string;
|
|
595
|
+
children: ReactNode;
|
|
596
|
+
}
|
|
597
|
+
declare function TabList({ label, className, children, ...rest }: TabListProps): ReactElement;
|
|
598
|
+
interface TabProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "value" | "type"> {
|
|
599
|
+
value: string;
|
|
600
|
+
children: ReactNode;
|
|
601
|
+
}
|
|
602
|
+
declare function Tab({ value, className, children, ...rest }: TabProps): ReactElement;
|
|
603
|
+
interface TabPanelProps extends HTMLAttributes<HTMLDivElement> {
|
|
604
|
+
value: string;
|
|
605
|
+
children: ReactNode;
|
|
606
|
+
}
|
|
607
|
+
declare function TabPanel({ value, className, children, ...rest }: TabPanelProps): ReactElement;
|
|
608
|
+
|
|
609
|
+
type ToastTone = "neutral" | "success" | "danger";
|
|
610
|
+
interface ToastOptions {
|
|
611
|
+
title: string;
|
|
612
|
+
description?: string | undefined;
|
|
613
|
+
tone?: ToastTone | undefined;
|
|
614
|
+
/** ms until auto-dismiss. 0 = stays until dismissed. Default 5000. */
|
|
615
|
+
duration?: number | undefined;
|
|
616
|
+
}
|
|
617
|
+
interface ToastContextValue {
|
|
618
|
+
toast: (options: ToastOptions) => number;
|
|
619
|
+
dismiss: (id: number) => void;
|
|
620
|
+
}
|
|
621
|
+
declare function useToast(): ToastContextValue;
|
|
622
|
+
interface ToastProviderProps {
|
|
623
|
+
children: ReactNode;
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* Mount once near the root. Renders the notification region itself.
|
|
627
|
+
*
|
|
628
|
+
* ```tsx
|
|
629
|
+
* // App root
|
|
630
|
+
* <ToastProvider>
|
|
631
|
+
* <App />
|
|
632
|
+
* </ToastProvider>
|
|
633
|
+
*
|
|
634
|
+
* // Anywhere below
|
|
635
|
+
* const { toast } = useToast();
|
|
636
|
+
* toast({ title: "Saved", tone: "success" });
|
|
637
|
+
* ```
|
|
638
|
+
*/
|
|
639
|
+
declare function ToastProvider({ children }: ToastProviderProps): ReactElement;
|
|
640
|
+
|
|
641
|
+
type StackGap = "hairline" | "tight" | "base" | "loose" | "section";
|
|
642
|
+
type StackAlign = "start" | "center" | "end" | "stretch";
|
|
643
|
+
interface StackProps extends HTMLAttributes<HTMLElement> {
|
|
644
|
+
/** Space between children, on the gap scale. Default "base". */
|
|
645
|
+
gap?: StackGap;
|
|
646
|
+
/** Cross-axis alignment. Default "stretch". */
|
|
647
|
+
align?: StackAlign;
|
|
648
|
+
/** Element to render. Default div. */
|
|
649
|
+
as?: ElementType;
|
|
650
|
+
}
|
|
651
|
+
/**
|
|
652
|
+
* Vertical flow. The parent owns spacing between siblings via gap —
|
|
653
|
+
* children carry no outer margins. Token-bounded on purpose: no arbitrary
|
|
654
|
+
* lengths, no style prop.
|
|
655
|
+
*
|
|
656
|
+
* ```tsx
|
|
657
|
+
* <Stack gap="base">
|
|
658
|
+
* <Heading level={2}>Profile</Heading>
|
|
659
|
+
* <Text tone="secondary">Public information</Text>
|
|
660
|
+
* </Stack>
|
|
661
|
+
* ```
|
|
662
|
+
*/
|
|
663
|
+
declare function Stack({ gap, align, as, className, ...rest }: StackProps): ReactElement;
|
|
664
|
+
|
|
665
|
+
type InlineGap = "hairline" | "tight" | "base" | "loose";
|
|
666
|
+
type InlineAlign = "start" | "center" | "end" | "baseline";
|
|
667
|
+
type InlineJustify = "start" | "center" | "end" | "between";
|
|
668
|
+
interface InlineProps extends HTMLAttributes<HTMLElement> {
|
|
669
|
+
/** Space between children, on the gap scale. Default "base". */
|
|
670
|
+
gap?: InlineGap;
|
|
671
|
+
/** Cross-axis alignment. Default "center". */
|
|
672
|
+
align?: InlineAlign;
|
|
673
|
+
/** Main-axis distribution. Default "start". */
|
|
674
|
+
justify?: InlineJustify;
|
|
675
|
+
/** Allow wrapping onto new lines. */
|
|
676
|
+
wrap?: boolean;
|
|
677
|
+
/** Element to render. Default div. */
|
|
678
|
+
as?: ElementType;
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Horizontal flow — Stack's row twin. Same token-bounded contract.
|
|
682
|
+
*
|
|
683
|
+
* ```tsx
|
|
684
|
+
* <Inline gap="tight" align="center" justify="between">
|
|
685
|
+
* <Text variant="label">Total</Text>
|
|
686
|
+
* <Text>42</Text>
|
|
687
|
+
* </Inline>
|
|
688
|
+
* ```
|
|
689
|
+
*/
|
|
690
|
+
declare function Inline({ gap, align, justify, wrap, as, className, ...rest }: InlineProps): ReactElement;
|
|
691
|
+
|
|
692
|
+
type ContainerWidth = "content" | "wide";
|
|
693
|
+
interface ContainerProps extends HTMLAttributes<HTMLElement> {
|
|
694
|
+
/** content = reading column, wide = desktop shell. Default "content". */
|
|
695
|
+
width?: ContainerWidth;
|
|
696
|
+
/** Element to render. Default div. */
|
|
697
|
+
as?: ElementType;
|
|
698
|
+
}
|
|
699
|
+
/**
|
|
700
|
+
* Centered max-width column with page-edge padding.
|
|
701
|
+
*
|
|
702
|
+
* ```tsx
|
|
703
|
+
* <Container>
|
|
704
|
+
* <Stack gap="section">…</Stack>
|
|
705
|
+
* </Container>
|
|
706
|
+
* ```
|
|
707
|
+
*/
|
|
708
|
+
declare function Container({ width, as, className, ...rest }: ContainerProps): ReactElement;
|
|
709
|
+
|
|
710
|
+
type CardVariant = "card" | "raised";
|
|
711
|
+
interface CardProps extends Omit<HTMLAttributes<HTMLElement>, "onClick"> {
|
|
712
|
+
children: ReactNode;
|
|
713
|
+
/** card = flat on border, raised = elevated. Default "card". */
|
|
714
|
+
variant?: CardVariant;
|
|
715
|
+
/** Makes the whole card a button. */
|
|
716
|
+
onClick?: () => void;
|
|
717
|
+
/** Makes the whole card a link. Wins over onClick. */
|
|
718
|
+
href?: string;
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* Surface container. Compose with CardHeader/CardBody/CardFooter — the card
|
|
722
|
+
* owns internal spacing, sections own their content.
|
|
723
|
+
*
|
|
724
|
+
* ```tsx
|
|
725
|
+
* <Card>
|
|
726
|
+
* <CardHeader><Heading level={3}>Next session</Heading></CardHeader>
|
|
727
|
+
* <CardBody><Text>Tomorrow, 19:00</Text></CardBody>
|
|
728
|
+
* <CardFooter><Button size="sm">Join</Button></CardFooter>
|
|
729
|
+
* </Card>
|
|
730
|
+
*
|
|
731
|
+
* <Card href="/items/42" variant="flat">…</Card>
|
|
732
|
+
* ```
|
|
733
|
+
*/
|
|
734
|
+
declare function Card({ children, variant, onClick, href, className, ...rest }: CardProps): ReactElement;
|
|
735
|
+
type CardSectionProps = HTMLAttributes<HTMLDivElement>;
|
|
736
|
+
/** Top slot — title row, media, tabs. */
|
|
737
|
+
declare function CardHeader({ className, ...rest }: CardSectionProps): ReactElement;
|
|
738
|
+
/** Main content slot. */
|
|
739
|
+
declare function CardBody({ className, ...rest }: CardSectionProps): ReactElement;
|
|
740
|
+
/** Bottom slot — actions, meta. */
|
|
741
|
+
declare function CardFooter({ className, ...rest }: CardSectionProps): ReactElement;
|
|
742
|
+
|
|
743
|
+
interface ModalProps {
|
|
744
|
+
open: boolean;
|
|
745
|
+
onClose: () => void;
|
|
746
|
+
/** Accessible name of the dialog. */
|
|
747
|
+
label: string;
|
|
748
|
+
/** Scrim click dismisses. Default true. */
|
|
749
|
+
closeOnScrimClick?: boolean;
|
|
750
|
+
children: ReactNode;
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
753
|
+
* Centered dialog. Escape, scrim click (`closeOnScrimClick`), and focus trap
|
|
754
|
+
* are handled. Compose the sections:
|
|
755
|
+
*
|
|
756
|
+
* ```tsx
|
|
757
|
+
* <Modal open={open} onClose={() => setOpen(false)} label="Edit session">
|
|
758
|
+
* <ModalHeader>Edit session</ModalHeader>
|
|
759
|
+
* <ModalBody>…</ModalBody>
|
|
760
|
+
* <ModalFooter><Button onClick={save}>Save</Button></ModalFooter>
|
|
761
|
+
* </Modal>
|
|
762
|
+
* ```
|
|
763
|
+
*/
|
|
764
|
+
declare function Modal({ open, onClose, label, closeOnScrimClick, children }: ModalProps): react.JSX.Element;
|
|
765
|
+
declare function ModalHeader({ children }: {
|
|
766
|
+
children: ReactNode;
|
|
767
|
+
}): react.JSX.Element;
|
|
768
|
+
declare function ModalBody({ children }: {
|
|
769
|
+
children: ReactNode;
|
|
770
|
+
}): react.JSX.Element;
|
|
771
|
+
declare function ModalFooter({ children }: {
|
|
772
|
+
children: ReactNode;
|
|
773
|
+
}): react.JSX.Element;
|
|
774
|
+
|
|
775
|
+
interface SheetProps {
|
|
776
|
+
open: boolean;
|
|
777
|
+
onClose: () => void;
|
|
778
|
+
/** Accessible name of the dialog. */
|
|
779
|
+
label: string;
|
|
780
|
+
/** Scrim click dismisses. Default true. */
|
|
781
|
+
closeOnScrimClick?: boolean;
|
|
782
|
+
children: ReactNode;
|
|
783
|
+
}
|
|
784
|
+
/**
|
|
785
|
+
* Bottom sheet. Same composition and dismissal model as Modal:
|
|
786
|
+
*
|
|
787
|
+
* ```tsx
|
|
788
|
+
* <Sheet open={open} onClose={() => setOpen(false)} label="Filters">
|
|
789
|
+
* <SheetHeader>Filters</SheetHeader>
|
|
790
|
+
* <SheetBody>…</SheetBody>
|
|
791
|
+
* <SheetFooter><Button onClick={apply}>Apply</Button></SheetFooter>
|
|
792
|
+
* </Sheet>
|
|
793
|
+
* ```
|
|
794
|
+
*/
|
|
795
|
+
declare function Sheet({ open, onClose, label, closeOnScrimClick, children }: SheetProps): react.JSX.Element;
|
|
796
|
+
declare function SheetHeader({ children }: {
|
|
797
|
+
children: ReactNode;
|
|
798
|
+
}): react.JSX.Element;
|
|
799
|
+
declare function SheetBody({ children }: {
|
|
800
|
+
children: ReactNode;
|
|
801
|
+
}): react.JSX.Element;
|
|
802
|
+
declare function SheetFooter({ children }: {
|
|
803
|
+
children: ReactNode;
|
|
804
|
+
}): react.JSX.Element;
|
|
805
|
+
|
|
806
|
+
interface ConfirmDialogProps {
|
|
807
|
+
open: boolean;
|
|
808
|
+
onClose: () => void;
|
|
809
|
+
onConfirm: () => void;
|
|
810
|
+
title: string;
|
|
811
|
+
description?: string | undefined;
|
|
812
|
+
confirmLabel: string;
|
|
813
|
+
cancelLabel?: string | undefined;
|
|
814
|
+
/** Style the confirm action as destructive. */
|
|
815
|
+
danger?: boolean | undefined;
|
|
816
|
+
}
|
|
817
|
+
/**
|
|
818
|
+
* Pre-composed Modal for the confirm/cancel pattern.
|
|
819
|
+
*
|
|
820
|
+
* ```tsx
|
|
821
|
+
* <ConfirmDialog
|
|
822
|
+
* open={open}
|
|
823
|
+
* onClose={() => setOpen(false)}
|
|
824
|
+
* onConfirm={deleteItem}
|
|
825
|
+
* title="Delete item?"
|
|
826
|
+
* description="This cannot be undone."
|
|
827
|
+
* confirmLabel="Delete"
|
|
828
|
+
* danger
|
|
829
|
+
* />
|
|
830
|
+
* ```
|
|
831
|
+
*/
|
|
832
|
+
declare function ConfirmDialog({ open, onClose, onConfirm, title, description, confirmLabel, cancelLabel, danger, }: ConfirmDialogProps): react.JSX.Element;
|
|
833
|
+
|
|
834
|
+
/**
|
|
835
|
+
* Page scaffold. Compose:
|
|
836
|
+
*
|
|
837
|
+
* ```tsx
|
|
838
|
+
* <Screen>
|
|
839
|
+
* <AppBar title="Sessions" />
|
|
840
|
+
* <ScreenContent>…</ScreenContent>
|
|
841
|
+
* <TabBar label="Primary">…</TabBar>
|
|
842
|
+
* </Screen>
|
|
843
|
+
* ```
|
|
844
|
+
*/
|
|
845
|
+
declare function Screen({ children }: {
|
|
846
|
+
children: ReactNode;
|
|
847
|
+
}): react.JSX.Element;
|
|
848
|
+
/** The scrollable main region of a Screen. */
|
|
849
|
+
declare function ScreenContent({ children }: {
|
|
850
|
+
children: ReactNode;
|
|
851
|
+
}): react.JSX.Element;
|
|
852
|
+
|
|
853
|
+
interface AppBarProps {
|
|
854
|
+
title?: string | undefined;
|
|
855
|
+
/** Left slot — typically a back icon-only Button. */
|
|
856
|
+
leading?: ReactNode;
|
|
857
|
+
/** Right slot — actions. */
|
|
858
|
+
trailing?: ReactNode;
|
|
859
|
+
}
|
|
860
|
+
/**
|
|
861
|
+
* Top app bar. Sticky, one per screen; the title is the page h1.
|
|
862
|
+
*
|
|
863
|
+
* ```tsx
|
|
864
|
+
* <AppBar
|
|
865
|
+
* title="Sessions"
|
|
866
|
+
* trailing={
|
|
867
|
+
* <Button iconOnly aria-label="Settings" variant="ghost" onClick={openSettings}>
|
|
868
|
+
* <Icon name="settings" />
|
|
869
|
+
* </Button>
|
|
870
|
+
* }
|
|
871
|
+
* />
|
|
872
|
+
* ```
|
|
873
|
+
*/
|
|
874
|
+
declare function AppBar({ title, leading, trailing }: AppBarProps): react.JSX.Element;
|
|
875
|
+
|
|
876
|
+
interface TabBarProps {
|
|
877
|
+
/** Accessible name of the navigation landmark. */
|
|
878
|
+
label: string;
|
|
879
|
+
children: ReactNode;
|
|
880
|
+
}
|
|
881
|
+
/**
|
|
882
|
+
* Bottom navigation. Items are links (or buttons for non-route actions);
|
|
883
|
+
* they stay in the natural tab order — roving focus is for composite
|
|
884
|
+
* widgets, not navigation landmarks.
|
|
885
|
+
*
|
|
886
|
+
* ```tsx
|
|
887
|
+
* <TabBar label="Primary">
|
|
888
|
+
* <TabBarItem label="Home" icon={<Icon name="home" />} href="/" active />
|
|
889
|
+
* <TabBarItem label="Search" icon={<Icon name="search" />} href="/search" />
|
|
890
|
+
* </TabBar>
|
|
891
|
+
* ```
|
|
892
|
+
*/
|
|
893
|
+
declare function TabBar({ label, children }: TabBarProps): react.JSX.Element;
|
|
894
|
+
interface TabBarItemProps {
|
|
895
|
+
label: string;
|
|
896
|
+
icon: ReactNode;
|
|
897
|
+
href?: string | undefined;
|
|
898
|
+
onClick?: MouseEventHandler | undefined;
|
|
899
|
+
active?: boolean | undefined;
|
|
900
|
+
}
|
|
901
|
+
declare function TabBarItem({ label, icon, href, onClick, active }: TabBarItemProps): react.JSX.Element;
|
|
902
|
+
|
|
903
|
+
interface UseOverlayOptions {
|
|
904
|
+
open: boolean;
|
|
905
|
+
onClose: () => void;
|
|
906
|
+
}
|
|
907
|
+
/**
|
|
908
|
+
* Shared modal-surface behaviour: focus capture and restore, Escape to
|
|
909
|
+
* close, Tab cycling inside the panel, body scroll lock. Attach the
|
|
910
|
+
* returned ref to the dialog element (it needs tabIndex={-1}).
|
|
911
|
+
*
|
|
912
|
+
* Anchor-positioned overlays (Tooltip/Popover) will extend this hook with
|
|
913
|
+
* a floating-ui middleware pass; the options object leaves room for that.
|
|
914
|
+
*/
|
|
915
|
+
declare function useOverlay<T extends HTMLElement>(options: UseOverlayOptions): RefObject<T | null>;
|
|
916
|
+
|
|
917
|
+
interface Presence {
|
|
918
|
+
/** Keep the element in the DOM (true during exit animation). */
|
|
919
|
+
mounted: boolean;
|
|
920
|
+
/** Drive the visual state — false during exit. */
|
|
921
|
+
visible: boolean;
|
|
922
|
+
}
|
|
923
|
+
/**
|
|
924
|
+
* Exit-animation helper. `open` flips instantly; `mounted` lags by
|
|
925
|
+
* `durationMs` on close so the exit transition can play.
|
|
926
|
+
*/
|
|
927
|
+
declare function usePresence(open: boolean, durationMs: number): Presence;
|
|
928
|
+
|
|
929
|
+
interface RovingGroupOptions {
|
|
930
|
+
/** Selector for the focusable items inside the container. */
|
|
931
|
+
selector: string;
|
|
932
|
+
/** Arrow axis. Default "horizontal". */
|
|
933
|
+
orientation?: "horizontal" | "vertical" | "both";
|
|
934
|
+
}
|
|
935
|
+
/**
|
|
936
|
+
* Arrow-key focus movement for composite widgets (toolbars, menus, tab bars).
|
|
937
|
+
* Wraps at the edges; Home/End jump. Returns a keydown handler for the
|
|
938
|
+
* container.
|
|
939
|
+
*/
|
|
940
|
+
declare function useRovingGroup(ref: RefObject<HTMLElement | null>, { selector, orientation }: RovingGroupOptions): (event: KeyboardEvent<HTMLElement>) => void;
|
|
941
|
+
|
|
942
|
+
export { AppBar, type AppBarProps, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, type AvatarSize, Badge, type BadgeProps, type BadgeTone, Button, type ButtonProps, type ButtonSize, type ButtonVariant, type CSSVars, Card, CardBody, CardFooter, CardHeader, type CardProps, type CardSectionProps, type CardVariant, Checkbox, type CheckboxProps, ConfirmDialog, type ConfirmDialogProps, Container, type ContainerProps, type ContainerWidth, Divider, type DividerProps, EmptyState, type EmptyStateProps, Field, type FieldContextValue, type FieldProps, Heading, type HeadingLevel, type HeadingProps, type HeadingTone, Icon, type IconProps, IconProvider, type IconProviderProps, type IconRender, type IconRenderProps, type IconSize, Inline, type InlineAlign, type InlineGap, type InlineJustify, type InlineProps, Input, type InputProps, type InputSize, Link, type LinkProps, type LinkVariant, ListGroup, type ListGroupProps, ListItem, type ListItemProps, Modal, ModalBody, ModalFooter, ModalHeader, type ModalProps, PasswordInput, type PasswordInputProps, type Presence, ProgressBar, type ProgressBarProps, Radio, type RadioProps, type RovingGroupOptions, Screen, ScreenContent, SearchField, type SearchFieldProps, type SegmentOption, SegmentedControl, type SegmentedControlProps, Select, type SelectProps, type SelectSize, Sheet, SheetBody, SheetFooter, SheetHeader, type SheetProps, Skeleton, type SkeletonProps, type SkeletonVariant, Spinner, type SpinnerProps, Stack, type StackAlign, type StackGap, type StackProps, Switch, type SwitchProps, Tab, TabBar, TabBarItem, type TabBarItemProps, type TabBarProps, TabList, type TabListProps, TabPanel, type TabPanelProps, type TabProps, Tabs, type TabsProps, Tag, type TagProps, type TagTone, Text, type TextProps, type TextTone, type TextVariant, Textarea, type TextareaProps, type ToastOptions, ToastProvider, type ToastProviderProps, type ToastTone, type UseOverlayOptions, cx, useFieldContext, useOverlay, usePresence, useRovingGroup, useToast };
|