shelving 1.264.1 → 1.264.2

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.
Files changed (70) hide show
  1. package/package.json +1 -1
  2. package/ui/README.md +2 -2
  3. package/ui/block/Blockquote.module.css +0 -3
  4. package/ui/block/Card.md +3 -7
  5. package/ui/block/Card.module.css +0 -3
  6. package/ui/block/Heading.md +0 -1
  7. package/ui/block/Heading.module.css +0 -3
  8. package/ui/block/Label.module.css +0 -3
  9. package/ui/block/List.md +1 -2
  10. package/ui/block/List.module.css +0 -3
  11. package/ui/block/Panel.md +1 -2
  12. package/ui/block/Panel.module.css +0 -3
  13. package/ui/block/Paragraph.md +1 -2
  14. package/ui/block/Paragraph.module.css +0 -3
  15. package/ui/block/Preformatted.module.css +0 -3
  16. package/ui/block/Subheading.md +0 -1
  17. package/ui/block/Subheading.module.css +0 -3
  18. package/ui/block/Title.md +0 -1
  19. package/ui/block/Title.module.css +0 -3
  20. package/ui/button/Button.md +1 -2
  21. package/ui/button/Button.module.css +0 -3
  22. package/ui/docs/DocumentationPage.test.tsx +2 -4
  23. package/ui/docs/DocumentationParams.js +1 -1
  24. package/ui/docs/DocumentationParams.tsx +1 -1
  25. package/ui/docs/DocumentationProperties.js +1 -1
  26. package/ui/docs/DocumentationProperties.tsx +1 -1
  27. package/ui/docs/DocumentationReferences.js +1 -1
  28. package/ui/docs/DocumentationReferences.tsx +1 -1
  29. package/ui/docs/DocumentationReturns.js +1 -1
  30. package/ui/docs/DocumentationReturns.tsx +1 -1
  31. package/ui/docs/DocumentationThrows.js +1 -1
  32. package/ui/docs/DocumentationThrows.tsx +1 -1
  33. package/ui/form/Field.test.tsx +1 -1
  34. package/ui/inline/Deleted.md +4 -5
  35. package/ui/inline/Deleted.module.css +1 -3
  36. package/ui/inline/Inserted.md +4 -5
  37. package/ui/inline/Inserted.module.css +1 -3
  38. package/ui/inline/Link.md +2 -3
  39. package/ui/inline/Link.module.css +1 -3
  40. package/ui/inline/Mark.js +1 -2
  41. package/ui/inline/Mark.md +5 -5
  42. package/ui/inline/Mark.module.css +2 -3
  43. package/ui/inline/Mark.tsx +0 -2
  44. package/ui/input/SchemaInput.test.tsx +3 -2
  45. package/ui/layout/CenteredLayout.d.ts +5 -7
  46. package/ui/layout/CenteredLayout.js +8 -4
  47. package/ui/layout/CenteredLayout.md +9 -2
  48. package/ui/layout/CenteredLayout.module.css +16 -22
  49. package/ui/layout/CenteredLayout.tsx +18 -12
  50. package/ui/layout/SidebarLayout.js +12 -5
  51. package/ui/layout/SidebarLayout.md +4 -4
  52. package/ui/layout/SidebarLayout.module.css +6 -9
  53. package/ui/layout/SidebarLayout.tsx +20 -17
  54. package/ui/misc/MetaContext.test.tsx +2 -3
  55. package/ui/misc/Tag.md +1 -2
  56. package/ui/misc/Tag.module.css +0 -3
  57. package/ui/notice/Message.module.css +0 -3
  58. package/ui/notice/Notice.md +1 -2
  59. package/ui/notice/Notice.module.css +0 -3
  60. package/ui/router/Router.test.tsx +1 -4
  61. package/ui/style/TINT_CLASS.md +1 -1
  62. package/ui/style/Width.d.ts +2 -1
  63. package/ui/style/Width.module.css +47 -17
  64. package/ui/style/Width.tsx +22 -1
  65. package/ui/style/getWidthClass.md +5 -9
  66. package/ui/table/Table.md +1 -1
  67. package/ui/tree/TreeButton.test.tsx +2 -5
  68. package/ui/tree/TreeContext.test.tsx +2 -3
  69. package/ui/tree/TreeMarkup.test.tsx +2 -5
  70. package/ui/tree/TreeRouter.test.tsx +2 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shelving",
3
- "version": "1.264.1",
3
+ "version": "1.264.2",
4
4
  "author": "Dave Houlbrooke <dave@shax.com>",
5
5
  "repository": {
6
6
  "type": "git",
package/ui/README.md CHANGED
@@ -27,7 +27,7 @@ The styling system lives in `style/` and has four moving parts: design tokens, t
27
27
 
28
28
  **Styling props.** The cross-cutting visual options are props, each backed by a helper in `style/` that maps the prop to a class. Colour and status move the tint anchor — `getColorClass()` and `getStatusClass()`; font size, weight, family, and case, plus text alignment, tint, and wrapping, all come from `getTypographyClass()`, which extends `ColorVariants` and composes `getColorClass()` so every typographic element also accepts `color` (use `getColorClass()` directly only for colour-without-typography, e.g. `<Icon>`); spacing, block-padding, inline-padding ("indent"), and gap from `getSpaceClass()`, `getPaddingClass()`, `getIndentClass()`, and `getGapClass()`; width constraints from `getWidthClass()`; flex layout from `getFlexClass()`; and opt-in scrolling from `getScrollClass()`. Each helper's page lists its exact prop values and what they set. A component opts into the props it wants by extending the matching `*Props` interfaces and composing the `getXxxClass(props)` calls.
29
29
 
30
- Each painting component also exposes its own theme hooks — a single tint hook (`--card-tint`) to recolour the whole component, plus per-property hooks (`--card-background`, `--card-radius`, …) for surgical overrides. Those are documented in each component's own **Styling** section (see `<Card>` for the precedent).
30
+ Each painting component also exposes per-property theme hooks (`--card-background`, `--card-radius`, …) for surgical overrides. To recolour a component or a whole region, apply `color=` / `status=` — on it or an ancestor scope — rather than a per-component tint hook; components no longer set the tint anchor themselves. Those hooks are documented in each component's own **Styling** section (see `<Card>` for the precedent).
31
31
 
32
32
  ## Theming
33
33
 
@@ -50,7 +50,7 @@ Each base token lives in a themed module that documents the variables it defines
50
50
  - `space` · `width` — layout spacing and widths (`--space-*`, `--width-*`).
51
51
  - `radius` · `stroke` · `shadow` · `duration` — surface tokens (`--radius-*`, `--stroke-*`, `--shadow-*`, `--duration-*`).
52
52
 
53
- The **tint ladder** is the one exception that doesn't follow the override-a-variable pattern: its 21 steps are *recomputed* from a single anchor inside every tinted scope, so you move the anchor rather than overriding individual steps. See `TINT_CLASS` for the full theming guide, and each component's **Styling** section for its per-component hooks.
53
+ The **tint ladder** is the one exception that doesn't follow the override-a-variable pattern: its 21 steps are *recomputed* from a single anchor inside every tinted scope, so you move the anchor (via `color=` / `status=`) rather than overriding individual steps. See `TINT_CLASS` for the full theming guide, and each component's **Styling** section for its per-property hooks.
54
54
 
55
55
  ## Finding your way around
56
56
 
@@ -7,9 +7,6 @@
7
7
  @layer components {
8
8
  .blockquote,
9
9
  .prose blockquote {
10
- /* Theme */
11
- --tint-50: var(--blockquote-tint, inherit);
12
-
13
10
  /* Box */
14
11
  margin-block: var(--blockquote-space, var(--space-paragraph));
15
12
  border-inline-start: var(--blockquote-border, var(--blockquote-stroke, var(--stroke-normal)) solid var(--tint-80));
package/ui/block/Card.md CHANGED
@@ -45,11 +45,10 @@ import { Card, Subheading } from "shelving/ui";
45
45
 
46
46
  ## Styling
47
47
 
48
- `Card` paints from the [tint ladder](/ui/TINT_CLASS); override these hooks at `:root` (or any ancestor scope) to retheme. Move `--card-tint` to recolour everything at once; reach for a per-property hook for a single surgical change.
48
+ `Card` paints from the [tint ladder](/ui/TINT_CLASS); override these hooks at `:root` (or any ancestor scope) to retheme. Apply `color=` / `status=` (on the card or an ancestor scope) to recolour everything at once — surface, border, text, and hover shade re-derive together; reach for a per-property hook for a single surgical change.
49
49
 
50
50
  | Variable | Styles | Default |
51
51
  |---|---|---|
52
- | `--card-tint` | Tint anchor for the card scope — recolours surface, border, text and hover together | `inherit` (flows from `color=` / `status=` / parent) |
53
52
  | `--card-background` | Surface fill | `var(--tint-90)` |
54
53
  | `--card-hover-background` | Surface fill when a navigable card is hovered | `var(--tint-95)` |
55
54
  | `--card-color` | Text colour | `var(--tint-00)` |
@@ -71,9 +70,6 @@ import { Card, Subheading } from "shelving/ui";
71
70
  --card-shadow: var(--shadow-small);
72
71
  --card-radius: var(--radius-small);
73
72
  }
74
-
75
- /* Retint every card purple — surface, border, text and hover all follow. */
76
- :root {
77
- --card-tint: var(--color-purple);
78
- }
79
73
  ```
74
+
75
+ To recolour cards, apply `color=` / `status=` to the card (or a tinted ancestor scope) — e.g. `<Card color="purple">` — rather than a per-component tint hook.
@@ -19,9 +19,6 @@
19
19
 
20
20
  @layer components {
21
21
  .card {
22
- /* Theme */
23
- --tint-50: var(--card-tint, inherit);
24
-
25
22
  /* Box */
26
23
  position: relative;
27
24
  margin-inline: 0;
@@ -44,7 +44,6 @@ import { Heading } from "shelving/ui";
44
44
 
45
45
  | Variable | Styles | Default |
46
46
  |---|---|---|
47
- | `--heading-tint` | Tint anchor for the heading scope | `inherit` (flows from `color=` / parent) |
48
47
  | `--heading-color` | Text colour | `inherit` |
49
48
  | `--heading-space-before` | Top margin | `var(--space-section)` (2rem) |
50
49
  | `--heading-space` | Bottom margin | `var(--space-paragraph)` (16px) |
@@ -6,9 +6,6 @@
6
6
  @layer components {
7
7
  .heading,
8
8
  .prose h2 {
9
- /* Theme */
10
- --tint-50: var(--heading-tint, inherit);
11
-
12
9
  /* Box */
13
10
  margin-block-start: var(--heading-space-before, var(--space-section));
14
11
  margin-block-end: var(--heading-space, var(--space-paragraph));
@@ -5,9 +5,6 @@
5
5
 
6
6
  @layer components {
7
7
  .label {
8
- /* Theme */
9
- --tint-50: var(--label-tint, inherit);
10
-
11
8
  /* Box */
12
9
  margin-block: var(--label-space, var(--space-paragraph));
13
10
 
package/ui/block/List.md CHANGED
@@ -31,11 +31,10 @@ import { List } from "shelving/ui";
31
31
 
32
32
  ## Styling
33
33
 
34
- `List` paints from the [tint ladder](/ui/TINT_CLASS) for its markers only; rebind `--list-tint` to recolour the scope, or reach for a per-property hook for a single change.
34
+ `List` paints from the [tint ladder](/ui/TINT_CLASS) for its markers only; apply `color=` (on the list or an ancestor scope) to recolour the markers, or reach for a per-property hook for a single change.
35
35
 
36
36
  | Variable | Styles | Default |
37
37
  |---|---|---|
38
- | `--list-tint` | Tint anchor for the list scope | `inherit` (flows from `color=` / parent) |
39
38
  | `--list-space` | Outer block margin (top + bottom) | `var(--space-paragraph)` (16px) |
40
39
  | `--list-gap` | Space between items | `var(--space-xsmall)` |
41
40
  | `--list-indent` | Inline start padding (marker gutter) | `1.125em` unordered / `1.8em` ordered |
@@ -9,9 +9,6 @@
9
9
  .ordered,
10
10
  .prose ul,
11
11
  .prose ol {
12
- /* Theme */
13
- --tint-50: var(--list-tint, inherit);
14
-
15
12
  /* Box */
16
13
  margin-block: var(--list-space, var(--space-paragraph));
17
14
 
package/ui/block/Panel.md CHANGED
@@ -31,11 +31,10 @@ import { Panel, Block, Title, Paragraph } from "shelving/ui";
31
31
 
32
32
  ## Styling
33
33
 
34
- `Panel` paints from the [tint ladder](/ui/TINT_CLASS); rebind `--panel-tint` to recolour the whole scope at once, or reach for a per-property hook for a single change.
34
+ `Panel` paints from the [tint ladder](/ui/TINT_CLASS); apply `color=` / `status=` (on the panel or an ancestor scope) to recolour the whole scope at once — surface, border, and text re-derive together — or reach for a per-property hook for a single change.
35
35
 
36
36
  | Variable | Styles | Default |
37
37
  |---|---|---|
38
- | `--panel-tint` | Tint anchor for the panel scope — recolours surface, border, and text together | `inherit` (flows from `color=` / `status=` / parent) |
39
38
  | `--panel-background` | Surface fill | `var(--tint-90)` |
40
39
  | `--panel-color` | Text colour | `var(--tint-00)` |
41
40
  | `--panel-border` | Top/bottom border shorthand | `var(--panel-stroke) solid var(--tint-80)` |
@@ -14,9 +14,6 @@
14
14
  */
15
15
  @layer components {
16
16
  .panel {
17
- /* Theme */
18
- --tint-50: var(--panel-tint, inherit);
19
-
20
17
  /* Box */
21
18
  position: relative;
22
19
  padding-block: var(--panel-padding, var(--space-section));
@@ -31,11 +31,10 @@ import { Paragraph, Strong, Link } from "shelving/ui";
31
31
 
32
32
  ## Styling
33
33
 
34
- `Paragraph` exposes a single hook for its own block margin and rebinds the tint anchor for its scope; it paints no colour of its own, so it inherits the surrounding text colour.
34
+ `Paragraph` exposes a single hook for its own block margin; it paints no colour of its own, so it inherits the surrounding text colour. Apply `color=` / `status=` to set the tint scope for any ladder-reading inline content inside it.
35
35
 
36
36
  | Variable | Styles | Default |
37
37
  |---|---|---|
38
- | `--paragraph-tint` | Tint anchor for the paragraph scope | `inherit` (flows from `color=` / parent) |
39
38
  | `--paragraph-space` | Outer block margin (top + bottom) | `var(--space-paragraph)` (16px) |
40
39
 
41
40
  **Global tokens it reads:** `--space-paragraph`.
@@ -4,9 +4,6 @@
4
4
  @layer components {
5
5
  .prose p,
6
6
  .paragraph {
7
- /* Theme */
8
- --tint-50: var(--paragraph-tint, inherit);
9
-
10
7
  /* Box */
11
8
  margin-block: var(--paragraph-space, var(--space-paragraph));
12
9
  }
@@ -10,9 +10,6 @@
10
10
  @layer components {
11
11
  .preformatted,
12
12
  .prose pre {
13
- /* Theme */
14
- --tint-50: var(--preformatted-tint, inherit);
15
-
16
13
  /* Box */
17
14
  position: relative;
18
15
  margin-inline: 0;
@@ -39,7 +39,6 @@ import { Title, Heading, Subheading } from "shelving/ui";
39
39
 
40
40
  | Variable | Styles | Default |
41
41
  |---|---|---|
42
- | `--subheading-tint` | Tint anchor for the subheading scope | `inherit` (flows from `color=` / parent) |
43
42
  | `--subheading-color` | Text colour | `inherit` |
44
43
  | `--subheading-space-before` | Top margin | `var(--space-section)` (2rem) |
45
44
  | `--subheading-space` | Bottom margin | `var(--space-paragraph)` (16px) |
@@ -6,9 +6,6 @@
6
6
  @layer components {
7
7
  .subheading,
8
8
  .prose :is(h3, h4, h5, h6) {
9
- /* Theme */
10
- --tint-50: var(--subheading-tint, inherit);
11
-
12
9
  /* Box */
13
10
  margin-block-start: var(--subheading-space-before, var(--space-section));
14
11
  margin-block-end: var(--subheading-space, var(--space-paragraph));
package/ui/block/Title.md CHANGED
@@ -38,7 +38,6 @@ import { Panel, Block, Title } from "shelving/ui";
38
38
 
39
39
  | Variable | Styles | Default |
40
40
  |---|---|---|
41
- | `--title-tint` | Tint anchor for the title scope | `inherit` (flows from `color=` / parent) |
42
41
  | `--title-color` | Text colour | `inherit` |
43
42
  | `--title-space-before` | Top margin | `var(--space-section)` (2rem) |
44
43
  | `--title-space` | Bottom margin | `var(--space-paragraph)` (16px) |
@@ -6,9 +6,6 @@
6
6
  @layer components {
7
7
  .title,
8
8
  .prose h1 {
9
- /* Theme */
10
- --tint-50: var(--title-tint, inherit);
11
-
12
9
  /* Box */
13
10
  margin-block-start: var(--title-space-before, var(--space-section));
14
11
  margin-block-end: var(--title-space, var(--space-paragraph));
@@ -46,11 +46,10 @@ import { getButtonClass } from "shelving/ui";
46
46
 
47
47
  ## Styling
48
48
 
49
- `Button` paints from the [tint ladder](/ui/TINT_CLASS). Override these hooks at `:root` or any ancestor scope; move `--button-tint` to recolour the whole button, or use a per-property hook for one change.
49
+ `Button` paints from the [tint ladder](/ui/TINT_CLASS). Override these hooks at `:root` or any ancestor scope; apply `color=` / `status=` (on the button or an ancestor scope) to recolour the whole button, or use a per-property hook for one change.
50
50
 
51
51
  | Variable | Styles | Default |
52
52
  |---|---|---|
53
- | `--button-tint` | Tint anchor for the button scope | `inherit` (flows from `color=` / `status=` / parent) |
54
53
  | `--button-background` | Surface fill | `var(--tint-90)` |
55
54
  | `--button-hover-background` | Surface fill on hover / focus | `var(--tint-95)` |
56
55
  | `--button-hover-border` | Border on hover / focus | `var(--button-stroke) solid var(--tint-90)` |
@@ -9,9 +9,6 @@
9
9
 
10
10
  @layer components {
11
11
  .button {
12
- /* Theme */
13
- --tint-50: var(--button-tint, inherit);
14
-
15
12
  /* Box */
16
13
  display: block;
17
14
  box-sizing: border-box;
@@ -1,10 +1,8 @@
1
1
  import { describe, expect, test } from "bun:test";
2
2
  import type { ReactNode } from "react";
3
3
  import { renderToStaticMarkup } from "react-dom/server";
4
- import type { DocumentationElement } from "../../util/tree.js";
5
- import { MetaContext } from "../misc/MetaContext.js";
6
- import { createMeta } from "../util/meta.js";
7
- import { DocumentationPage } from "./DocumentationPage.js";
4
+ import { createMeta, DocumentationPage, MetaContext } from "shelving/ui";
5
+ import type { DocumentationElement } from "shelving/util/tree";
8
6
 
9
7
  /** Make a minimal `tree-documentation` child element of a given kind. */
10
8
  function doc(name: string, kind: string): DocumentationElement {
@@ -29,7 +29,7 @@ export function DocumentationParams({ params }) {
29
29
  const map = useTreeMap();
30
30
  if (!params?.length)
31
31
  return null;
32
- return (_jsx(Section, { children: _jsx(Scroll, { horizontal: true, children: _jsxs(Table, { children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx(Cell, { header: true, width: "fit", children: "Param" }), _jsx(Cell, { header: true, width: "fit", children: "Type" }), _jsx(Cell, { header: true, width: "xxnarrow", grow: true })] }) }), _jsx("tbody", { children: params.map(({ name, type = DEFAULT_TYPE, description, default: def, optional }) => {
32
+ return (_jsx(Section, { children: _jsx(Scroll, { horizontal: true, children: _jsxs(Table, { children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx(Cell, { header: true, width: "fit", children: "Param" }), _jsx(Cell, { header: true, width: "fit", children: "Type" }), _jsx(Cell, { header: true, width: "16x", grow: true })] }) }), _jsx("tbody", { children: params.map(({ name, type = DEFAULT_TYPE, description, default: def, optional }) => {
33
33
  const { members, optional: typeOptional } = splitType(type);
34
34
  // An options-bag param whose (single, concrete) type resolves to a documented interface/object type is flattened into its individual fields as indented child rows.
35
35
  const single = members.length === 1 ? members[0] : undefined;
@@ -55,7 +55,7 @@ export function DocumentationParams({ params }: DocumentationParamsProps): React
55
55
  <Cell header width="fit">
56
56
  Type
57
57
  </Cell>
58
- <Cell header width="xxnarrow" grow />
58
+ <Cell header width="16x" grow />
59
59
  </tr>
60
60
  </thead>
61
61
  <tbody>
@@ -24,7 +24,7 @@ export function DocumentationProperties({ properties }) {
24
24
  const map = useTreeMap();
25
25
  if (!properties?.length)
26
26
  return null;
27
- return (_jsx(Section, { children: _jsx(Scroll, { horizontal: true, children: _jsxs(Table, { children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx(Cell, { header: true, width: "fit", children: "Property" }), _jsx(Cell, { header: true, width: "fit", children: "Type" }), _jsx(Cell, { header: true, width: "xxnarrow", grow: true })] }) }), _jsx("tbody", { children: properties.map(({ name, type = DEFAULT_TYPE, description, default: def, optional, readonly }) => {
27
+ return (_jsx(Section, { children: _jsx(Scroll, { horizontal: true, children: _jsxs(Table, { children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx(Cell, { header: true, width: "fit", children: "Property" }), _jsx(Cell, { header: true, width: "fit", children: "Type" }), _jsx(Cell, { header: true, width: "16x", grow: true })] }) }), _jsx("tbody", { children: properties.map(({ name, type = DEFAULT_TYPE, description, default: def, optional, readonly }) => {
28
28
  const { members, optional: typeOptional } = splitType(type);
29
29
  return (_jsxs("tr", { children: [_jsx(Cell, { nowrap: true, children: _jsx(Code, { nowrap: true, children: `.${name}` }) }), _jsx("td", { children: _jsx(DocumentationType, { members: members }) }), _jsx("td", { children: _jsx(DocumentationDescription, { description: description || getTreeElement(map, members[0] ?? DEFAULT_TYPE)?.props.description, default: def, optional: !!optional || typeOptional, readonly: readonly }) })] }, `${name}-${type}`));
30
30
  }) })] }) }) }));
@@ -49,7 +49,7 @@ export function DocumentationProperties({ properties }: DocumentationPropertiesP
49
49
  <Cell header width="fit">
50
50
  Type
51
51
  </Cell>
52
- <Cell header width="xxnarrow" grow />
52
+ <Cell header width="16x" grow />
53
53
  </tr>
54
54
  </thead>
55
55
  <tbody>
@@ -19,5 +19,5 @@ export function DocumentationReferences({ types }) {
19
19
  const map = useTreeMap();
20
20
  if (!types?.length)
21
21
  return null;
22
- return (_jsx(Section, { children: _jsx(Scroll, { horizontal: true, children: _jsxs(Table, { children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx(Cell, { header: true, width: "fit", children: "Type" }), _jsx(Cell, { header: true, width: "xxnarrow", grow: true })] }) }), _jsx("tbody", { children: types.map(type => (_jsxs("tr", { children: [_jsx("td", { children: _jsx(TreeLink, { name: type }) }), _jsx("td", { children: _jsx(DocumentationDescription, { description: getTreeElement(map, type)?.props.description }) })] }, type))) })] }) }) }));
22
+ return (_jsx(Section, { children: _jsx(Scroll, { horizontal: true, children: _jsxs(Table, { children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx(Cell, { header: true, width: "fit", children: "Type" }), _jsx(Cell, { header: true, width: "16x", grow: true })] }) }), _jsx("tbody", { children: types.map(type => (_jsxs("tr", { children: [_jsx("td", { children: _jsx(TreeLink, { name: type }) }), _jsx("td", { children: _jsx(DocumentationDescription, { description: getTreeElement(map, type)?.props.description }) })] }, type))) })] }) }) }));
23
23
  }
@@ -39,7 +39,7 @@ export function DocumentationReferences({ types }: DocumentationReferencesProps)
39
39
  <Cell header width="fit">
40
40
  Type
41
41
  </Cell>
42
- <Cell header width="xxnarrow" grow />
42
+ <Cell header width="16x" grow />
43
43
  </tr>
44
44
  </thead>
45
45
  <tbody>
@@ -21,5 +21,5 @@ export function DocumentationReturns({ returns }) {
21
21
  const map = useTreeMap();
22
22
  if (!returns?.length)
23
23
  return null;
24
- return (_jsx(Section, { children: _jsx(Scroll, { horizontal: true, children: _jsxs(Table, { children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx(Cell, { header: true, width: "fit", children: "Return" }), _jsx(Cell, { header: true, width: "xxnarrow", grow: true })] }) }), _jsx("tbody", { children: returns.map(({ type = DEFAULT_TYPE, description }) => (_jsxs("tr", { children: [_jsx("td", { children: _jsx(TreeLink, { name: type, nowrap: true }) }), _jsx("td", { children: _jsx(DocumentationDescription, { description: description || getTreeElement(map, type)?.props.description }) })] }, `${type}-${description}`))) })] }) }) }));
24
+ return (_jsx(Section, { children: _jsx(Scroll, { horizontal: true, children: _jsxs(Table, { children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx(Cell, { header: true, width: "fit", children: "Return" }), _jsx(Cell, { header: true, width: "16x", grow: true })] }) }), _jsx("tbody", { children: returns.map(({ type = DEFAULT_TYPE, description }) => (_jsxs("tr", { children: [_jsx("td", { children: _jsx(TreeLink, { name: type, nowrap: true }) }), _jsx("td", { children: _jsx(DocumentationDescription, { description: description || getTreeElement(map, type)?.props.description }) })] }, `${type}-${description}`))) })] }) }) }));
25
25
  }
@@ -43,7 +43,7 @@ export function DocumentationReturns({ returns }: DocumentationReturnsProps): Re
43
43
  <Cell header width="fit">
44
44
  Return
45
45
  </Cell>
46
- <Cell header width="xxnarrow" grow />
46
+ <Cell header width="16x" grow />
47
47
  </tr>
48
48
  </thead>
49
49
  <tbody>
@@ -21,5 +21,5 @@ export function DocumentationThrows({ throws }) {
21
21
  const map = useTreeMap();
22
22
  if (!throws?.length)
23
23
  return null;
24
- return (_jsx(Section, { children: _jsx(Scroll, { horizontal: true, children: _jsxs(Table, { children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx(Cell, { header: true, width: "fit", children: "Throws" }), _jsx(Cell, { header: true, width: "xxnarrow", grow: true })] }) }), _jsx("tbody", { children: throws.map(({ type = DEFAULT_TYPE, description }) => (_jsxs("tr", { children: [_jsx("td", { children: _jsx(TreeLink, { name: type, nowrap: true }) }), _jsx("td", { children: _jsx(DocumentationDescription, { description: description || getTreeElement(map, type)?.props.description }) })] }, `${type}-${description}`))) })] }) }) }));
24
+ return (_jsx(Section, { children: _jsx(Scroll, { horizontal: true, children: _jsxs(Table, { children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx(Cell, { header: true, width: "fit", children: "Throws" }), _jsx(Cell, { header: true, width: "16x", grow: true })] }) }), _jsx("tbody", { children: throws.map(({ type = DEFAULT_TYPE, description }) => (_jsxs("tr", { children: [_jsx("td", { children: _jsx(TreeLink, { name: type, nowrap: true }) }), _jsx("td", { children: _jsx(DocumentationDescription, { description: description || getTreeElement(map, type)?.props.description }) })] }, `${type}-${description}`))) })] }) }) }));
25
25
  }
@@ -43,7 +43,7 @@ export function DocumentationThrows({ throws }: DocumentationThrowsProps): React
43
43
  <Cell header width="fit">
44
44
  Throws
45
45
  </Cell>
46
- <Cell header width="xxnarrow" grow />
46
+ <Cell header width="16x" grow />
47
47
  </tr>
48
48
  </thead>
49
49
  <tbody>
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, test } from "bun:test";
2
2
  import { renderToStaticMarkup } from "react-dom/server";
3
- import { Field } from "./Field.js";
3
+ import { Field } from "shelving/ui";
4
4
 
5
5
  describe("Field", () => {
6
6
  test("does not render a message container when there is no message", () => {
@@ -5,7 +5,7 @@ Deleted text — renders a `<del>` element to mark content that has been removed
5
5
  **Things to know:**
6
6
 
7
7
  - Use `Deleted` for content genuinely removed from a document (edits, diffs, retired prices), and `<Inserted>` for content added — they pair up.
8
- - It drives its colour through the [tint ladder](/ui/TINT_CLASS), so the `color` variant (`color="purple"`, `color="orange"`, …) recolours the strike-through. The base tint defaults to `--color-red`.
8
+ - It colours itself directly from `--color-red` rather than the tint ladder, so a deletion stays a consistent red even inside a tinted region; change it with `--deleted-color`.
9
9
  - Inside `<Prose>` a raw `<del>` picks up the same styling, so Markdown-rendered deletions match component ones.
10
10
 
11
11
  ## Usage
@@ -22,13 +22,12 @@ import { Paragraph, Deleted, Inserted } from "shelving/ui";
22
22
 
23
23
  ## Styling
24
24
 
25
- `Deleted` paints from the [tint ladder](/ui/TINT_CLASS): the `50` tint sets the text colour, defaulting to `--color-red`. Override `--deleted-tint` to recolour from the base, or set each property directly.
25
+ `Deleted` colours its text directly from `--color-red` (not the tint ladder), so deletions stay a consistent red regardless of the surrounding tint. Override `--deleted-color` to recolour.
26
26
 
27
27
  | Variable | Styles | Default |
28
28
  |---|---|---|
29
- | `--deleted-tint` | Base tint (`--tint-50`) the colour derives from | `var(--color-red)` |
30
- | `--deleted-color` | Text colour | `var(--tint-50)` |
29
+ | `--deleted-color` | Text colour | `var(--color-red)` |
31
30
  | `--deleted-decoration` | Text decoration | `line-through var(--stroke-normal)` |
32
31
  | `--deleted-weight` | Font weight | `var(--weight-strong)` |
33
32
 
34
- **Global tokens it reads:** `--color-red`, `--stroke-normal`, `--weight-strong`, and the tint-ladder step `--tint-50`.
33
+ **Global tokens it reads:** `--color-red`, `--stroke-normal`, and `--weight-strong`.
@@ -6,10 +6,8 @@
6
6
  @layer components {
7
7
  .deleted,
8
8
  .prose del {
9
- --tint-50: var(--deleted-tint, var(--color-red));
10
-
11
9
  /* Style */
12
- color: var(--deleted-color, var(--tint-50));
10
+ color: var(--deleted-color, var(--color-red));
13
11
  text-decoration: var(--deleted-decoration, line-through var(--stroke-normal));
14
12
 
15
13
  /* Text */
@@ -5,7 +5,7 @@ Inserted text — renders an `<ins>` element to mark content that has been added
5
5
  **Things to know:**
6
6
 
7
7
  - Use `Inserted` for content genuinely added to a document (edits, diffs, new prices), and `<Deleted>` for content removed — they pair up.
8
- - It drives its colour through the [tint ladder](/ui/TINT_CLASS), so the `color` variant (`color="purple"`, `color="blue"`, …) recolours the underline. The base tint defaults to `--color-green`.
8
+ - It colours itself directly from `--color-green` rather than the tint ladder, so an insertion stays a consistent green even inside a tinted region; change it with `--inserted-color`.
9
9
  - Inside `<Prose>` a raw `<ins>` picks up the same styling, so Markdown-rendered insertions match component ones.
10
10
 
11
11
  ## Usage
@@ -22,13 +22,12 @@ import { Paragraph, Deleted, Inserted } from "shelving/ui";
22
22
 
23
23
  ## Styling
24
24
 
25
- `Inserted` paints from the [tint ladder](/ui/TINT_CLASS): the `50` tint sets the text colour, defaulting to `--color-green`. Override `--inserted-tint` to recolour from the base, or set each property directly.
25
+ `Inserted` colours its text directly from `--color-green` (not the tint ladder), so insertions stay a consistent green regardless of the surrounding tint. Override `--inserted-color` to recolour.
26
26
 
27
27
  | Variable | Styles | Default |
28
28
  |---|---|---|
29
- | `--inserted-tint` | Base tint (`--tint-50`) the colour derives from | `var(--color-green)` |
30
- | `--inserted-color` | Text colour | `var(--tint-50)` |
29
+ | `--inserted-color` | Text colour | `var(--color-green)` |
31
30
  | `--inserted-decoration` | Text decoration | `underline var(--stroke-normal)` |
32
31
  | `--inserted-weight` | Font weight | `var(--weight-strong)` |
33
32
 
34
- **Global tokens it reads:** `--color-green`, `--stroke-normal`, `--weight-strong`, and the tint-ladder step `--tint-50`.
33
+ **Global tokens it reads:** `--color-green`, `--stroke-normal`, and `--weight-strong`.
@@ -6,10 +6,8 @@
6
6
  @layer components {
7
7
  .inserted,
8
8
  .prose ins {
9
- --tint-50: var(--inserted-tint, var(--color-green));
10
-
11
9
  /* Style */
12
- color: var(--inserted-color, var(--tint-50));
10
+ color: var(--inserted-color, var(--color-green));
13
11
  text-decoration: var(--inserted-decoration, underline var(--stroke-normal));
14
12
 
15
13
  /* Text */
package/ui/inline/Link.md CHANGED
@@ -31,12 +31,11 @@ import { Link } from "shelving/ui";
31
31
 
32
32
  ## Styling
33
33
 
34
- `Link` drives its colour through the tint ladder, so the `color` variant (`color="purple"`, `color="red"`, …) recolours the link. By default the `50` tint resolves to the global `--color-link` token.
34
+ `Link` colours itself from the global `--color-link` token by default. Inside a tinted scope (`color=` / `status=` on an ancestor) `--color-link` resolves to `inherit`, so links adopt the surrounding tinted text colour. Override `--link-color` to set it directly.
35
35
 
36
36
  | Variable | Styles | Default |
37
37
  |---|---|---|
38
- | `--link-tint` | Base tint (`--tint-50`) the link colour derives from | `var(--color-link)` |
39
- | `--link-color` | Text colour | `var(--tint-50)` |
38
+ | `--link-color` | Text colour | `var(--color-link)` |
40
39
  | `--link-weight` | Font weight | `var(--weight-strong)` |
41
40
 
42
41
  **Global tokens it reads:** `--color-link`, `--weight-strong`, and `--stroke-normal` (the underline thickness).
@@ -6,10 +6,8 @@
6
6
  @layer components {
7
7
  .link,
8
8
  .prose a {
9
- --tint-50: var(--link-tint, var(--color-link));
10
-
11
9
  /* Style */
12
- color: var(--link-color, var(--tint-50));
10
+ color: var(--link-color, var(--color-link));
13
11
  text-decoration: none;
14
12
  cursor: inherit;
15
13
 
package/ui/inline/Mark.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { TINT_CLASS } from "../style/Tint.js";
3
2
  import { getTypographyClass } from "../style/Typography.js";
4
3
  import { getClass, getModuleClass } from "../util/css.js";
5
4
  import MARK_CSS from "./Mark.module.css";
@@ -12,5 +11,5 @@ const MARK_CLASS = getModuleClass(MARK_CSS, "mark");
12
11
  */
13
12
  export function Mark({ children, ...props }) {
14
13
  return (_jsx("mark", { className: getClass(MARK_CLASS, //
15
- TINT_CLASS, getTypographyClass(props)), children: children }));
14
+ getTypographyClass(props)), children: children }));
16
15
  }
package/ui/inline/Mark.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Mark
2
2
 
3
- Highlighted text — renders a `<mark>` element to call attention to a run of text, such as a matched search term. Painted as a small inline pill with a yellow background by default.
3
+ Highlighted text — renders a `<mark>` element to call attention to a run of text, such as a matched search term. Painted as a small inline pill with a translucent yellow background by default.
4
4
 
5
5
  **Things to know:**
6
6
 
@@ -20,15 +20,15 @@ import { Mark } from "shelving/ui";
20
20
 
21
21
  ## Styling
22
22
 
23
- `Mark` paints from the [tint ladder](/ui/TINT_CLASS): the `50` tint sets the background and the `00` tint the text. By default the base tint resolves to `--color-yellow`; override `--mark-tint` to recolour the whole pill, or `--mark-background` / `--mark-color` to set the two faces independently.
23
+ `Mark` highlights with a translucent wash of `--color-yellow` `color-mix(…, transparent)`, so the text underneath stays legible with the text painted from `--tint-00`. Override `--mark-tint` to change the highlight hue, `--mark-background` to replace the fill outright, or `--mark-color` for the text.
24
24
 
25
25
  | Variable | Styles | Default |
26
26
  |---|---|---|
27
- | `--mark-tint` | Base tint (`--tint-50`) the pill derives from | `var(--color-yellow)` |
28
- | `--mark-background` | Background fill | `var(--tint-50)` |
27
+ | `--mark-tint` | Highlight hue, mixed 50% with `transparent` for the background | `var(--color-yellow)` |
28
+ | `--mark-background` | Background fill | `color-mix(in oklch, var(--mark-tint, var(--color-yellow)), transparent)` |
29
29
  | `--mark-color` | Text colour | `var(--tint-00)` |
30
30
  | `--mark-padding` | Inline padding | `var(--space-xxsmall)` |
31
31
  | `--mark-radius` | Corner radius | `var(--radius-xxsmall)` |
32
32
  | `--mark-weight` | Font weight | `var(--weight-strong)` |
33
33
 
34
- **Global tokens it reads:** `--color-yellow`, `--space-xxsmall`, `--radius-xxsmall`, `--weight-strong`, and the tint-ladder steps `--tint-50` / `--tint-00`.
34
+ **Global tokens it reads:** `--color-yellow`, `--space-xxsmall`, `--radius-xxsmall`, `--weight-strong`, and the tint-ladder step `--tint-00`.
@@ -1,4 +1,5 @@
1
1
  @import "../style/layers.css";
2
+ @import "../style/Color.module.css";
2
3
  @import "../style/Radius.module.css";
3
4
  @import "../style/Typography.module.css";
4
5
  @import "../style/Tint.module.css";
@@ -6,8 +7,6 @@
6
7
  @layer components {
7
8
  .mark,
8
9
  .prose mark {
9
- --tint-50: var(--mark-tint, var(--color-yellow));
10
-
11
10
  /* Box */
12
11
  display: inline-block;
13
12
  padding-inline: var(--mark-padding, var(--space-xxsmall));
@@ -15,7 +14,7 @@
15
14
  vertical-align: baseline;
16
15
 
17
16
  /* Style */
18
- background: var(--mark-background, var(--tint-80));
17
+ background-color: var(--mark-background, color-mix(in oklch, var(--mark-tint, var(--color-yellow)), transparent));
19
18
  color: var(--mark-color, var(--tint-00));
20
19
 
21
20
  /* Text */
@@ -1,5 +1,4 @@
1
1
  import type { ReactElement } from "react";
2
- import { TINT_CLASS } from "../style/Tint.js";
3
2
  import { getTypographyClass, type TypographyVariants } from "../style/Typography.js";
4
3
  import { getClass, getModuleClass } from "../util/css.js";
5
4
  import type { OptionalChildProps } from "../util/props.js";
@@ -25,7 +24,6 @@ export function Mark({ children, ...props }: MarkProps): ReactElement {
25
24
  <mark
26
25
  className={getClass(
27
26
  MARK_CLASS, //
28
- TINT_CLASS,
29
27
  getTypographyClass(props),
30
28
  )}
31
29
  >
@@ -1,7 +1,8 @@
1
1
  import { describe, expect, test } from "bun:test";
2
2
  import { renderToStaticMarkup } from "react-dom/server";
3
- import { PASSTHROUGH, StringSchema } from "../../index.js";
4
- import { StringSchemaInput } from "../index.js";
3
+ import { StringSchema } from "shelving/schema";
4
+ import { StringSchemaInput } from "shelving/ui";
5
+ import { PASSTHROUGH } from "shelving/util/function";
5
6
 
6
7
  describe("StringSchemaInput", () => {
7
8
  test("formats the initial value to its clean sanitized value", () => {