@nimblebrain/synapse 0.14.1 → 0.16.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.
@@ -11,13 +11,25 @@ interface AvatarProps extends Omit<HTMLAttributes<HTMLSpanElement>, "children">
11
11
  }
12
12
  declare function Avatar({ name, src, size, style, ...rest }: AvatarProps): react_jsx_runtime.JSX.Element;
13
13
 
14
- type BadgeTone = "neutral" | "accent" | "success" | "warning" | "danger" | "processing" | "warm";
14
+ type BadgeTone = "neutral" | "accent" | "success" | "warning" | "danger" | "processing";
15
15
  interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {
16
16
  tone?: BadgeTone;
17
17
  children?: ReactNode;
18
18
  }
19
19
  declare function Badge({ tone, style, children, ...rest }: BadgeProps): react_jsx_runtime.JSX.Element;
20
20
 
21
+ interface Crumb {
22
+ label: string;
23
+ /** Omit on the current step. A crumb with no handler renders as plain text. */
24
+ onClick?: () => void;
25
+ }
26
+ interface BreadcrumbProps extends Omit<HTMLAttributes<HTMLElement>, "children"> {
27
+ crumbs: Crumb[];
28
+ /** The glyph between steps. */
29
+ separator?: string;
30
+ }
31
+ declare function Breadcrumb({ crumbs, separator, style, ...rest }: BreadcrumbProps): react_jsx_runtime.JSX.Element;
32
+
21
33
  type Variant = "primary" | "secondary" | "ghost";
22
34
  type Size = "sm" | "md";
23
35
  interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
@@ -102,6 +114,20 @@ interface ListRowProps extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
102
114
  }
103
115
  declare function ListRow({ title, meta, leading, trailing, interactive, style, className, ...rest }: ListRowProps): react_jsx_runtime.JSX.Element;
104
116
 
117
+ interface PageHeaderProps extends Omit<HTMLAttributes<HTMLElement>, "title"> {
118
+ /** The trail. Omit on a top-level page, which has nothing above it to name. */
119
+ crumbs?: Crumb[];
120
+ title: ReactNode;
121
+ /** Sits beside the title — typically a `Badge`. */
122
+ status?: ReactNode;
123
+ /** Sits at the far end of the title's row. Buttons, a menu. */
124
+ actions?: ReactNode;
125
+ description?: ReactNode;
126
+ /** Lines the description is clamped to before ellipsis. `0` removes the clamp. */
127
+ descriptionLines?: number;
128
+ }
129
+ declare function PageHeader({ crumbs, title, status, actions, description, descriptionLines, style, ...rest }: PageHeaderProps): react_jsx_runtime.JSX.Element;
130
+
105
131
  interface PaginationProps extends Omit<HTMLAttributes<HTMLDivElement>, "onChange"> {
106
132
  /** Current page, 1-based. */
107
133
  page: number;
@@ -160,6 +186,12 @@ interface Column<T> {
160
186
  /** Cell content for a row. */
161
187
  render: (row: T, index: number) => ReactNode;
162
188
  align?: Align$1;
189
+ /**
190
+ * Column width (`"40%"`, `220`, `"12rem"`). Declaring one on any column switches
191
+ * the table to `table-layout: fixed`, and columns without a width then divide the
192
+ * remainder equally. Required on any column whose cell truncates — see the note on
193
+ * the module above.
194
+ */
163
195
  width?: number | string;
164
196
  }
165
197
  interface TableProps<T> extends Omit<HTMLAttributes<HTMLTableElement>, "children"> {
@@ -170,8 +202,39 @@ interface TableProps<T> extends Omit<HTMLAttributes<HTMLTableElement>, "children
170
202
  onRowClick?: (row: T, index: number) => void;
171
203
  /** Shown when `data` is empty. */
172
204
  empty?: ReactNode;
205
+ /**
206
+ * The narrowest this table stays readable, and the switch that turns scrolling on.
207
+ *
208
+ * A fixed-layout table has no lower bound of its own, so seven columns in a 400px pane
209
+ * become seven clipped headers and a badge overflowing its cell. Below this width the
210
+ * table scrolls inside its own container instead of crushing — and setting the floor is
211
+ * the only way to ask for that, because a scroller with no floor has no defined moment to
212
+ * engage: under fixed layout the table always fits its container, and under auto layout it
213
+ * engages at whatever width the content happens to reach.
214
+ *
215
+ * The cost is the sticky header. An `overflow-x` container captures the stickiness
216
+ * `position: sticky` resolves against the page's own scroller, and CSS gives no way to
217
+ * scroll one axis while leaving the other visible — so a table without a floor keeps its
218
+ * sticky header, and one with a floor trades it.
219
+ */
220
+ minWidth?: number | string;
221
+ }
222
+ declare function Table<T>({ data, columns, rowKey, onRowClick, empty, minWidth, style, className, ...rest }: TableProps<T>): react_jsx_runtime.JSX.Element;
223
+
224
+ interface Tab<T extends string> {
225
+ label: string;
226
+ value: T;
227
+ /** A small trailing count. Rendered muted, and omitted entirely when undefined. */
228
+ count?: number;
229
+ }
230
+ interface TabsProps<T extends string> extends Omit<HTMLAttributes<HTMLDivElement>, "onChange"> {
231
+ tabs: Tab<T>[];
232
+ value: T;
233
+ onChange: (value: T) => void;
234
+ /** Accessible name for the tab set — what these are facets OF. */
235
+ label?: string;
173
236
  }
174
- declare function Table<T>({ data, columns, rowKey, onRowClick, empty, style, className, ...rest }: TableProps<T>): react_jsx_runtime.JSX.Element;
237
+ declare function Tabs<T extends string>({ tabs, value, onChange, label, style, className, onKeyDown: callerKeyDown, ...rest }: TabsProps<T>): react_jsx_runtime.JSX.Element;
175
238
 
176
239
  type ContentWidth = "reading" | "full";
177
240
  interface AppFrameProps extends HTMLAttributes<HTMLDivElement> {
@@ -233,6 +296,38 @@ declare const ListDetailLayout: typeof ListDetailLayoutRoot & {
233
296
  Back: typeof Back;
234
297
  };
235
298
 
299
+ interface PageLayoutProps extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
300
+ /** The trail. Omit at the top level, which has nothing above it to name. */
301
+ crumbs?: Crumb[];
302
+ title: ReactNode;
303
+ /** Beside the title — typically a `Badge`. */
304
+ status?: ReactNode;
305
+ /** The far end of the title's row. */
306
+ actions?: ReactNode;
307
+ description?: ReactNode;
308
+ /** Lines the description is clamped to. `0` removes the clamp. */
309
+ descriptionLines?: number;
310
+ /**
311
+ * ONE tab bar, of the facets of whatever the title names. A `Tabs`.
312
+ *
313
+ * A slot rather than typed props because `Tabs` already has an API worth having, and
314
+ * wrapping it here would mean maintaining a second copy of it that drifts. What the layout
315
+ * owns is the bar's POSITION — under the header, above the content — which is the part
316
+ * apps get wrong.
317
+ */
318
+ tabs?: ReactNode;
319
+ /**
320
+ * Controls that narrow the content below: a search field, a status filter, a view toggle.
321
+ *
322
+ * Distinct from `tabs` on purpose. A tab changes which facet of one entity is shown; a
323
+ * toolbar reshapes a set within that facet. Rendering them as one row is how an app ends up
324
+ * with two identical-looking control strips whose difference nobody can see.
325
+ */
326
+ toolbar?: ReactNode;
327
+ children?: ReactNode;
328
+ }
329
+ declare function PageLayout({ crumbs, title, status, actions, description, descriptionLines, tabs, toolbar, children, style, ...rest }: PageLayoutProps): react_jsx_runtime.JSX.Element;
330
+
236
331
  type CollapseMode = "reflow" | "drawer";
237
332
  type Side = "left" | "right";
238
333
  interface SidebarState {
@@ -325,10 +420,13 @@ declare function Divider({ orientation, style, ...rest }: DividerProps): react_j
325
420
  * with no React re-render: the host swaps the `:root` vars and every `var()`
326
421
  * re-resolves.
327
422
  *
328
- * The fallbacks are deliberately **neutral** (system fonts, neutral grays, a
329
- * generic blue) — NOT NimbleBrain brand. Brand arrives by injection when the
330
- * app runs inside the NimbleBrain host; standalone/static renders get a sane
423
+ * The fallbacks are deliberately **unbranded** — system fonts, neutral grays, a
424
+ * generic blue, and generic semantic hues for the status channels. NOT
425
+ * NimbleBrain brand. Brand arrives by injection when the app runs inside the
426
+ * NimbleBrain host; standalone/static renders get a sane
331
427
  * unbranded default. This keeps the library host-agnostic.
428
+ * `__tests__/ui/tokens.test.ts` holds the line: every hex in these fallbacks
429
+ * must be in the sanctioned set, same as `theme-defaults.ts`.
332
430
  *
333
431
  * Components import the static `tokens` object and style with CSS `var()`, so
334
432
  * theming (incl. light/dark) resolves in CSS with no re-render.
@@ -350,14 +448,12 @@ declare const tokens: {
350
448
  readonly danger: "var(--nb-color-danger, #dc2626)";
351
449
  readonly success: "var(--nb-color-success, #059669)";
352
450
  readonly warning: "var(--nb-color-warning, #f59e0b)";
353
- readonly warm: "var(--nb-color-warm, #d4620a)";
354
- readonly warmLight: "var(--nb-color-warm-light, #fef5ee)";
355
451
  readonly processing: "var(--nb-color-processing, #7c3aed)";
356
452
  readonly processingLight: "var(--nb-color-processing-light, #f3eeff)";
357
453
  readonly infoLight: "var(--nb-color-info-light, #eef4ff)";
358
454
  readonly fontSans: "var(--font-sans, system-ui, -apple-system, BlinkMacSystemFont, sans-serif)";
359
455
  readonly fontMono: "var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace)";
360
- readonly fontHeading: "var(--nb-font-heading, Georgia, 'Times New Roman', serif)";
456
+ readonly fontHeading: "var(--nb-font-heading, system-ui, -apple-system, BlinkMacSystemFont, sans-serif)";
361
457
  readonly weightNormal: "var(--font-weight-normal, 400)";
362
458
  readonly weightMedium: "var(--font-weight-medium, 500)";
363
459
  readonly weightSemibold: "var(--font-weight-semibold, 600)";
@@ -404,7 +500,24 @@ interface TextProps extends Omit<HTMLAttributes<HTMLElement>, "color"> {
404
500
  weight?: Weight;
405
501
  tone?: Tone;
406
502
  mono?: boolean;
407
- /** Single-line ellipsis truncation. */
503
+ /**
504
+ * Single-line ellipsis truncation.
505
+ *
506
+ * Sets `display: block` alongside the ellipsis rules, and that is load-bearing rather
507
+ * than incidental: `overflow` and `text-overflow` do not apply to a non-replaced INLINE
508
+ * box, so on the default `<span>` the only declaration that survived was
509
+ * `white-space: nowrap` — and the prop did the exact opposite of its name, making text
510
+ * unwrappable instead of clipping it. Inside an auto-layout `<table>` that widened the
511
+ * column to the full string and pushed every later column off the pane.
512
+ *
513
+ * `min-width: 0` comes with it so the box can actually shrink as a flex item; without it
514
+ * a truncating `Text` inside `Inline`/`Stack` refuses to go below its content width and
515
+ * pushes its container instead, which is the same bug one layer out.
516
+ *
517
+ * A truncating cell in a `Table` also needs its column to declare a `width` — see
518
+ * `Column.width`. Auto table layout sizes to content, so the ellipsis has nothing to
519
+ * clip against until some column is pinned.
520
+ */
408
521
  truncate?: boolean;
409
522
  as?: ElementType;
410
523
  children?: ReactNode;
@@ -421,4 +534,4 @@ interface HeadingProps extends Omit<HTMLAttributes<HTMLHeadingElement>, "color">
421
534
  /** Display heading using the heading font slot. Defaults to md, semibold. */
422
535
  declare function Heading({ size, weight, tone, as: As, style, children, ...rest }: HeadingProps): react_jsx_runtime.JSX.Element;
423
536
 
424
- export { AppFrame, Avatar, Badge, type BadgeTone, Button, Card, type Column, Divider, Drawer, EmptyState, Heading, type HeadingSize, Inline, ListDetailLayout, ListRow, Pagination, Prose, SearchField, SegmentedControl, SidebarLayout, Spacer, Spinner, Stack, type Status, StatusDot, Table, Text, TextLink, type TextSize, type Tokens, headingStyle, textStyle, tokens, useBreakpoint, useListDetail, useSidebar };
537
+ export { AppFrame, Avatar, Badge, type BadgeTone, Breadcrumb, Button, Card, type Column, type Crumb, Divider, Drawer, EmptyState, Heading, type HeadingSize, Inline, ListDetailLayout, ListRow, PageHeader, PageLayout, Pagination, Prose, SearchField, SegmentedControl, SidebarLayout, Spacer, Spinner, Stack, type Status, StatusDot, Table, Tabs, Text, TextLink, type TextSize, type Tokens, headingStyle, textStyle, tokens, useBreakpoint, useListDetail, useSidebar };
@@ -11,13 +11,25 @@ interface AvatarProps extends Omit<HTMLAttributes<HTMLSpanElement>, "children">
11
11
  }
12
12
  declare function Avatar({ name, src, size, style, ...rest }: AvatarProps): react_jsx_runtime.JSX.Element;
13
13
 
14
- type BadgeTone = "neutral" | "accent" | "success" | "warning" | "danger" | "processing" | "warm";
14
+ type BadgeTone = "neutral" | "accent" | "success" | "warning" | "danger" | "processing";
15
15
  interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {
16
16
  tone?: BadgeTone;
17
17
  children?: ReactNode;
18
18
  }
19
19
  declare function Badge({ tone, style, children, ...rest }: BadgeProps): react_jsx_runtime.JSX.Element;
20
20
 
21
+ interface Crumb {
22
+ label: string;
23
+ /** Omit on the current step. A crumb with no handler renders as plain text. */
24
+ onClick?: () => void;
25
+ }
26
+ interface BreadcrumbProps extends Omit<HTMLAttributes<HTMLElement>, "children"> {
27
+ crumbs: Crumb[];
28
+ /** The glyph between steps. */
29
+ separator?: string;
30
+ }
31
+ declare function Breadcrumb({ crumbs, separator, style, ...rest }: BreadcrumbProps): react_jsx_runtime.JSX.Element;
32
+
21
33
  type Variant = "primary" | "secondary" | "ghost";
22
34
  type Size = "sm" | "md";
23
35
  interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
@@ -102,6 +114,20 @@ interface ListRowProps extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
102
114
  }
103
115
  declare function ListRow({ title, meta, leading, trailing, interactive, style, className, ...rest }: ListRowProps): react_jsx_runtime.JSX.Element;
104
116
 
117
+ interface PageHeaderProps extends Omit<HTMLAttributes<HTMLElement>, "title"> {
118
+ /** The trail. Omit on a top-level page, which has nothing above it to name. */
119
+ crumbs?: Crumb[];
120
+ title: ReactNode;
121
+ /** Sits beside the title — typically a `Badge`. */
122
+ status?: ReactNode;
123
+ /** Sits at the far end of the title's row. Buttons, a menu. */
124
+ actions?: ReactNode;
125
+ description?: ReactNode;
126
+ /** Lines the description is clamped to before ellipsis. `0` removes the clamp. */
127
+ descriptionLines?: number;
128
+ }
129
+ declare function PageHeader({ crumbs, title, status, actions, description, descriptionLines, style, ...rest }: PageHeaderProps): react_jsx_runtime.JSX.Element;
130
+
105
131
  interface PaginationProps extends Omit<HTMLAttributes<HTMLDivElement>, "onChange"> {
106
132
  /** Current page, 1-based. */
107
133
  page: number;
@@ -160,6 +186,12 @@ interface Column<T> {
160
186
  /** Cell content for a row. */
161
187
  render: (row: T, index: number) => ReactNode;
162
188
  align?: Align$1;
189
+ /**
190
+ * Column width (`"40%"`, `220`, `"12rem"`). Declaring one on any column switches
191
+ * the table to `table-layout: fixed`, and columns without a width then divide the
192
+ * remainder equally. Required on any column whose cell truncates — see the note on
193
+ * the module above.
194
+ */
163
195
  width?: number | string;
164
196
  }
165
197
  interface TableProps<T> extends Omit<HTMLAttributes<HTMLTableElement>, "children"> {
@@ -170,8 +202,39 @@ interface TableProps<T> extends Omit<HTMLAttributes<HTMLTableElement>, "children
170
202
  onRowClick?: (row: T, index: number) => void;
171
203
  /** Shown when `data` is empty. */
172
204
  empty?: ReactNode;
205
+ /**
206
+ * The narrowest this table stays readable, and the switch that turns scrolling on.
207
+ *
208
+ * A fixed-layout table has no lower bound of its own, so seven columns in a 400px pane
209
+ * become seven clipped headers and a badge overflowing its cell. Below this width the
210
+ * table scrolls inside its own container instead of crushing — and setting the floor is
211
+ * the only way to ask for that, because a scroller with no floor has no defined moment to
212
+ * engage: under fixed layout the table always fits its container, and under auto layout it
213
+ * engages at whatever width the content happens to reach.
214
+ *
215
+ * The cost is the sticky header. An `overflow-x` container captures the stickiness
216
+ * `position: sticky` resolves against the page's own scroller, and CSS gives no way to
217
+ * scroll one axis while leaving the other visible — so a table without a floor keeps its
218
+ * sticky header, and one with a floor trades it.
219
+ */
220
+ minWidth?: number | string;
221
+ }
222
+ declare function Table<T>({ data, columns, rowKey, onRowClick, empty, minWidth, style, className, ...rest }: TableProps<T>): react_jsx_runtime.JSX.Element;
223
+
224
+ interface Tab<T extends string> {
225
+ label: string;
226
+ value: T;
227
+ /** A small trailing count. Rendered muted, and omitted entirely when undefined. */
228
+ count?: number;
229
+ }
230
+ interface TabsProps<T extends string> extends Omit<HTMLAttributes<HTMLDivElement>, "onChange"> {
231
+ tabs: Tab<T>[];
232
+ value: T;
233
+ onChange: (value: T) => void;
234
+ /** Accessible name for the tab set — what these are facets OF. */
235
+ label?: string;
173
236
  }
174
- declare function Table<T>({ data, columns, rowKey, onRowClick, empty, style, className, ...rest }: TableProps<T>): react_jsx_runtime.JSX.Element;
237
+ declare function Tabs<T extends string>({ tabs, value, onChange, label, style, className, onKeyDown: callerKeyDown, ...rest }: TabsProps<T>): react_jsx_runtime.JSX.Element;
175
238
 
176
239
  type ContentWidth = "reading" | "full";
177
240
  interface AppFrameProps extends HTMLAttributes<HTMLDivElement> {
@@ -233,6 +296,38 @@ declare const ListDetailLayout: typeof ListDetailLayoutRoot & {
233
296
  Back: typeof Back;
234
297
  };
235
298
 
299
+ interface PageLayoutProps extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
300
+ /** The trail. Omit at the top level, which has nothing above it to name. */
301
+ crumbs?: Crumb[];
302
+ title: ReactNode;
303
+ /** Beside the title — typically a `Badge`. */
304
+ status?: ReactNode;
305
+ /** The far end of the title's row. */
306
+ actions?: ReactNode;
307
+ description?: ReactNode;
308
+ /** Lines the description is clamped to. `0` removes the clamp. */
309
+ descriptionLines?: number;
310
+ /**
311
+ * ONE tab bar, of the facets of whatever the title names. A `Tabs`.
312
+ *
313
+ * A slot rather than typed props because `Tabs` already has an API worth having, and
314
+ * wrapping it here would mean maintaining a second copy of it that drifts. What the layout
315
+ * owns is the bar's POSITION — under the header, above the content — which is the part
316
+ * apps get wrong.
317
+ */
318
+ tabs?: ReactNode;
319
+ /**
320
+ * Controls that narrow the content below: a search field, a status filter, a view toggle.
321
+ *
322
+ * Distinct from `tabs` on purpose. A tab changes which facet of one entity is shown; a
323
+ * toolbar reshapes a set within that facet. Rendering them as one row is how an app ends up
324
+ * with two identical-looking control strips whose difference nobody can see.
325
+ */
326
+ toolbar?: ReactNode;
327
+ children?: ReactNode;
328
+ }
329
+ declare function PageLayout({ crumbs, title, status, actions, description, descriptionLines, tabs, toolbar, children, style, ...rest }: PageLayoutProps): react_jsx_runtime.JSX.Element;
330
+
236
331
  type CollapseMode = "reflow" | "drawer";
237
332
  type Side = "left" | "right";
238
333
  interface SidebarState {
@@ -325,10 +420,13 @@ declare function Divider({ orientation, style, ...rest }: DividerProps): react_j
325
420
  * with no React re-render: the host swaps the `:root` vars and every `var()`
326
421
  * re-resolves.
327
422
  *
328
- * The fallbacks are deliberately **neutral** (system fonts, neutral grays, a
329
- * generic blue) — NOT NimbleBrain brand. Brand arrives by injection when the
330
- * app runs inside the NimbleBrain host; standalone/static renders get a sane
423
+ * The fallbacks are deliberately **unbranded** — system fonts, neutral grays, a
424
+ * generic blue, and generic semantic hues for the status channels. NOT
425
+ * NimbleBrain brand. Brand arrives by injection when the app runs inside the
426
+ * NimbleBrain host; standalone/static renders get a sane
331
427
  * unbranded default. This keeps the library host-agnostic.
428
+ * `__tests__/ui/tokens.test.ts` holds the line: every hex in these fallbacks
429
+ * must be in the sanctioned set, same as `theme-defaults.ts`.
332
430
  *
333
431
  * Components import the static `tokens` object and style with CSS `var()`, so
334
432
  * theming (incl. light/dark) resolves in CSS with no re-render.
@@ -350,14 +448,12 @@ declare const tokens: {
350
448
  readonly danger: "var(--nb-color-danger, #dc2626)";
351
449
  readonly success: "var(--nb-color-success, #059669)";
352
450
  readonly warning: "var(--nb-color-warning, #f59e0b)";
353
- readonly warm: "var(--nb-color-warm, #d4620a)";
354
- readonly warmLight: "var(--nb-color-warm-light, #fef5ee)";
355
451
  readonly processing: "var(--nb-color-processing, #7c3aed)";
356
452
  readonly processingLight: "var(--nb-color-processing-light, #f3eeff)";
357
453
  readonly infoLight: "var(--nb-color-info-light, #eef4ff)";
358
454
  readonly fontSans: "var(--font-sans, system-ui, -apple-system, BlinkMacSystemFont, sans-serif)";
359
455
  readonly fontMono: "var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace)";
360
- readonly fontHeading: "var(--nb-font-heading, Georgia, 'Times New Roman', serif)";
456
+ readonly fontHeading: "var(--nb-font-heading, system-ui, -apple-system, BlinkMacSystemFont, sans-serif)";
361
457
  readonly weightNormal: "var(--font-weight-normal, 400)";
362
458
  readonly weightMedium: "var(--font-weight-medium, 500)";
363
459
  readonly weightSemibold: "var(--font-weight-semibold, 600)";
@@ -404,7 +500,24 @@ interface TextProps extends Omit<HTMLAttributes<HTMLElement>, "color"> {
404
500
  weight?: Weight;
405
501
  tone?: Tone;
406
502
  mono?: boolean;
407
- /** Single-line ellipsis truncation. */
503
+ /**
504
+ * Single-line ellipsis truncation.
505
+ *
506
+ * Sets `display: block` alongside the ellipsis rules, and that is load-bearing rather
507
+ * than incidental: `overflow` and `text-overflow` do not apply to a non-replaced INLINE
508
+ * box, so on the default `<span>` the only declaration that survived was
509
+ * `white-space: nowrap` — and the prop did the exact opposite of its name, making text
510
+ * unwrappable instead of clipping it. Inside an auto-layout `<table>` that widened the
511
+ * column to the full string and pushed every later column off the pane.
512
+ *
513
+ * `min-width: 0` comes with it so the box can actually shrink as a flex item; without it
514
+ * a truncating `Text` inside `Inline`/`Stack` refuses to go below its content width and
515
+ * pushes its container instead, which is the same bug one layer out.
516
+ *
517
+ * A truncating cell in a `Table` also needs its column to declare a `width` — see
518
+ * `Column.width`. Auto table layout sizes to content, so the ellipsis has nothing to
519
+ * clip against until some column is pinned.
520
+ */
408
521
  truncate?: boolean;
409
522
  as?: ElementType;
410
523
  children?: ReactNode;
@@ -421,4 +534,4 @@ interface HeadingProps extends Omit<HTMLAttributes<HTMLHeadingElement>, "color">
421
534
  /** Display heading using the heading font slot. Defaults to md, semibold. */
422
535
  declare function Heading({ size, weight, tone, as: As, style, children, ...rest }: HeadingProps): react_jsx_runtime.JSX.Element;
423
536
 
424
- export { AppFrame, Avatar, Badge, type BadgeTone, Button, Card, type Column, Divider, Drawer, EmptyState, Heading, type HeadingSize, Inline, ListDetailLayout, ListRow, Pagination, Prose, SearchField, SegmentedControl, SidebarLayout, Spacer, Spinner, Stack, type Status, StatusDot, Table, Text, TextLink, type TextSize, type Tokens, headingStyle, textStyle, tokens, useBreakpoint, useListDetail, useSidebar };
537
+ export { AppFrame, Avatar, Badge, type BadgeTone, Breadcrumb, Button, Card, type Column, type Crumb, Divider, Drawer, EmptyState, Heading, type HeadingSize, Inline, ListDetailLayout, ListRow, PageHeader, PageLayout, Pagination, Prose, SearchField, SegmentedControl, SidebarLayout, Spacer, Spinner, Stack, type Status, StatusDot, Table, Tabs, Text, TextLink, type TextSize, type Tokens, headingStyle, textStyle, tokens, useBreakpoint, useListDetail, useSidebar };