shelving 1.264.0 → 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 (210) 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.d.ts +1 -1
  5. package/ui/block/Card.js +1 -1
  6. package/ui/block/Card.md +3 -7
  7. package/ui/block/Card.module.css +0 -3
  8. package/ui/block/Card.tsx +1 -1
  9. package/ui/block/Heading.md +0 -1
  10. package/ui/block/Heading.module.css +0 -3
  11. package/ui/block/Image.d.ts +3 -3
  12. package/ui/block/Image.js +4 -4
  13. package/ui/block/Image.module.css +4 -1
  14. package/ui/block/Image.tsx +14 -4
  15. package/ui/block/Label.module.css +0 -3
  16. package/ui/block/List.md +1 -2
  17. package/ui/block/List.module.css +0 -3
  18. package/ui/block/Panel.md +1 -2
  19. package/ui/block/Panel.module.css +0 -3
  20. package/ui/block/Paragraph.md +1 -2
  21. package/ui/block/Paragraph.module.css +0 -3
  22. package/ui/block/Preformatted.module.css +0 -3
  23. package/ui/block/Subheading.md +0 -1
  24. package/ui/block/Subheading.module.css +0 -3
  25. package/ui/block/Title.md +0 -1
  26. package/ui/block/Title.module.css +0 -3
  27. package/ui/block/Video.d.ts +3 -58
  28. package/ui/block/Video.js +2 -52
  29. package/ui/block/Video.module.css +1 -51
  30. package/ui/block/Video.tsx +3 -99
  31. package/ui/{form → button}/Button.d.ts +6 -2
  32. package/ui/{form → button}/Button.md +1 -2
  33. package/ui/{form → button}/Button.module.css +0 -3
  34. package/ui/{form → button}/Button.tsx +6 -1
  35. package/ui/button/FullscreenButton.d.ts +31 -0
  36. package/ui/button/FullscreenButton.js +37 -0
  37. package/ui/button/FullscreenButton.tsx +58 -0
  38. package/ui/button/RetryButton.d.ts +29 -0
  39. package/ui/button/RetryButton.js +27 -0
  40. package/ui/button/RetryButton.tsx +48 -0
  41. package/ui/{form → button}/SubmitButton.d.ts +12 -8
  42. package/ui/{form → button}/SubmitButton.js +4 -4
  43. package/ui/{form → button}/SubmitButton.tsx +22 -18
  44. package/ui/button/index.d.ts +5 -0
  45. package/ui/button/index.js +5 -0
  46. package/ui/button/index.ts +5 -0
  47. package/ui/dialog/Dialog.d.ts +1 -1
  48. package/ui/dialog/Dialog.tsx +1 -1
  49. package/ui/docs/DocumentationPage.test.tsx +2 -4
  50. package/ui/docs/DocumentationParams.js +1 -1
  51. package/ui/docs/DocumentationParams.tsx +1 -1
  52. package/ui/docs/DocumentationProperties.js +1 -1
  53. package/ui/docs/DocumentationProperties.tsx +1 -1
  54. package/ui/docs/DocumentationReferences.js +1 -1
  55. package/ui/docs/DocumentationReferences.tsx +1 -1
  56. package/ui/docs/DocumentationReturns.js +1 -1
  57. package/ui/docs/DocumentationReturns.tsx +1 -1
  58. package/ui/docs/DocumentationSearchPage.js +2 -2
  59. package/ui/docs/DocumentationSearchPage.tsx +2 -2
  60. package/ui/docs/DocumentationThrows.js +1 -1
  61. package/ui/docs/DocumentationThrows.tsx +1 -1
  62. package/ui/form/Field.test.tsx +1 -1
  63. package/ui/form/FormContext.d.ts +1 -1
  64. package/ui/form/FormContext.js +1 -1
  65. package/ui/form/FormContext.tsx +1 -1
  66. package/ui/form/FormFields.d.ts +1 -1
  67. package/ui/form/FormFields.js +1 -1
  68. package/ui/form/FormFields.tsx +2 -2
  69. package/ui/form/FormFooter.js +1 -1
  70. package/ui/form/FormFooter.tsx +1 -1
  71. package/ui/form/FormInput.d.ts +1 -1
  72. package/ui/form/FormInput.js +1 -1
  73. package/ui/form/FormInput.tsx +2 -2
  74. package/ui/form/Progress.d.ts +6 -24
  75. package/ui/form/Progress.js +9 -20
  76. package/ui/form/Progress.module.css +13 -32
  77. package/ui/form/Progress.tsx +18 -51
  78. package/ui/form/index.d.ts +0 -23
  79. package/ui/form/index.js +0 -23
  80. package/ui/form/index.ts +0 -23
  81. package/ui/index.d.ts +2 -0
  82. package/ui/index.js +2 -0
  83. package/ui/index.ts +2 -0
  84. package/ui/inline/Deleted.md +4 -5
  85. package/ui/inline/Deleted.module.css +1 -3
  86. package/ui/inline/Inserted.md +4 -5
  87. package/ui/inline/Inserted.module.css +1 -3
  88. package/ui/inline/Link.d.ts +1 -1
  89. package/ui/inline/Link.js +1 -1
  90. package/ui/inline/Link.md +2 -3
  91. package/ui/inline/Link.module.css +1 -3
  92. package/ui/inline/Link.tsx +1 -1
  93. package/ui/inline/Mark.js +1 -2
  94. package/ui/inline/Mark.md +5 -5
  95. package/ui/inline/Mark.module.css +2 -3
  96. package/ui/inline/Mark.tsx +0 -2
  97. package/ui/{form → input}/ArrayInput.js +1 -1
  98. package/ui/{form → input}/ArrayInput.tsx +1 -1
  99. package/ui/{form → input}/ButtonInput.d.ts +1 -1
  100. package/ui/{form → input}/ButtonInput.js +1 -1
  101. package/ui/{form → input}/ButtonInput.tsx +1 -1
  102. package/ui/{form → input}/ButtonPopover.d.ts +1 -1
  103. package/ui/{form → input}/ButtonPopover.js +1 -1
  104. package/ui/{form → input}/ButtonPopover.tsx +1 -1
  105. package/ui/{form → input}/DictionaryInput.js +1 -1
  106. package/ui/{form → input}/DictionaryInput.tsx +1 -1
  107. package/ui/{form → input}/SchemaInput.js +1 -1
  108. package/ui/{form → input}/SchemaInput.test.tsx +3 -3
  109. package/ui/{form → input}/SchemaInput.tsx +1 -1
  110. package/ui/{form → input}/TextInput.d.ts +1 -1
  111. package/ui/{form → input}/TextInput.js +1 -1
  112. package/ui/{form → input}/TextInput.tsx +1 -1
  113. package/ui/input/index.d.ts +20 -0
  114. package/ui/input/index.js +20 -0
  115. package/ui/input/index.ts +20 -0
  116. package/ui/layout/CenteredLayout.d.ts +5 -7
  117. package/ui/layout/CenteredLayout.js +8 -4
  118. package/ui/layout/CenteredLayout.md +9 -2
  119. package/ui/layout/CenteredLayout.module.css +16 -22
  120. package/ui/layout/CenteredLayout.tsx +18 -12
  121. package/ui/layout/Layout.d.ts +1 -1
  122. package/ui/layout/Layout.js +4 -0
  123. package/ui/layout/Layout.ts +6 -0
  124. package/ui/layout/SidebarLayout.js +13 -6
  125. package/ui/layout/SidebarLayout.md +4 -4
  126. package/ui/layout/SidebarLayout.module.css +6 -9
  127. package/ui/layout/SidebarLayout.tsx +21 -18
  128. package/ui/menu/Menu.d.ts +1 -1
  129. package/ui/menu/Menu.js +1 -1
  130. package/ui/menu/Menu.tsx +1 -1
  131. package/ui/misc/Catcher.d.ts +2 -19
  132. package/ui/misc/Catcher.js +3 -22
  133. package/ui/misc/Catcher.tsx +4 -40
  134. package/ui/misc/MetaContext.test.tsx +2 -3
  135. package/ui/misc/Tag.d.ts +1 -1
  136. package/ui/misc/Tag.js +1 -1
  137. package/ui/misc/Tag.md +1 -2
  138. package/ui/misc/Tag.module.css +0 -3
  139. package/ui/misc/Tag.tsx +1 -1
  140. package/ui/notice/Message.module.css +0 -3
  141. package/ui/notice/Notice.md +1 -2
  142. package/ui/notice/Notice.module.css +0 -3
  143. package/ui/router/Router.test.tsx +1 -4
  144. package/ui/style/TINT_CLASS.md +1 -1
  145. package/ui/style/Width.d.ts +2 -1
  146. package/ui/style/Width.module.css +47 -17
  147. package/ui/style/Width.tsx +22 -1
  148. package/ui/style/getWidthClass.md +5 -9
  149. package/ui/table/Table.md +1 -1
  150. package/ui/tree/TreeButton.d.ts +1 -1
  151. package/ui/tree/TreeButton.js +1 -1
  152. package/ui/tree/TreeButton.test.tsx +2 -5
  153. package/ui/tree/TreeButton.tsx +1 -1
  154. package/ui/tree/TreeContext.test.tsx +2 -3
  155. package/ui/tree/TreeMarkup.test.tsx +2 -5
  156. package/ui/tree/TreeRouter.test.tsx +2 -5
  157. package/ui/tree/TreeSidebar.js +1 -1
  158. package/ui/tree/TreeSidebar.tsx +1 -1
  159. /package/ui/{form → button}/Button.js +0 -0
  160. /package/ui/{form → button}/Clickable.d.ts +0 -0
  161. /package/ui/{form → button}/Clickable.js +0 -0
  162. /package/ui/{form → button}/Clickable.tsx +0 -0
  163. /package/ui/{form → input}/ArrayInput.d.ts +0 -0
  164. /package/ui/{form → input}/ArrayRadioInputs.d.ts +0 -0
  165. /package/ui/{form → input}/ArrayRadioInputs.js +0 -0
  166. /package/ui/{form → input}/ArrayRadioInputs.tsx +0 -0
  167. /package/ui/{form → input}/ButtonInputPopover.d.ts +0 -0
  168. /package/ui/{form → input}/ButtonInputPopover.js +0 -0
  169. /package/ui/{form → input}/ButtonInputPopover.tsx +0 -0
  170. /package/ui/{form → input}/CheckboxInput.d.ts +0 -0
  171. /package/ui/{form → input}/CheckboxInput.js +0 -0
  172. /package/ui/{form → input}/CheckboxInput.tsx +0 -0
  173. /package/ui/{form → input}/ChoiceRadioInputs.d.ts +0 -0
  174. /package/ui/{form → input}/ChoiceRadioInputs.js +0 -0
  175. /package/ui/{form → input}/ChoiceRadioInputs.tsx +0 -0
  176. /package/ui/{form → input}/DataInput.d.ts +0 -0
  177. /package/ui/{form → input}/DataInput.js +0 -0
  178. /package/ui/{form → input}/DataInput.tsx +0 -0
  179. /package/ui/{form → input}/DateInput.d.ts +0 -0
  180. /package/ui/{form → input}/DateInput.js +0 -0
  181. /package/ui/{form → input}/DateInput.tsx +0 -0
  182. /package/ui/{form → input}/DictionaryInput.d.ts +0 -0
  183. /package/ui/{form → input}/FileInput.d.ts +0 -0
  184. /package/ui/{form → input}/FileInput.js +0 -0
  185. /package/ui/{form → input}/FileInput.tsx +0 -0
  186. /package/ui/{form → input}/Input.d.ts +0 -0
  187. /package/ui/{form → input}/Input.js +0 -0
  188. /package/ui/{form → input}/Input.module.css +0 -0
  189. /package/ui/{form → input}/Input.tsx +0 -0
  190. /package/ui/{form → input}/NumberInput.d.ts +0 -0
  191. /package/ui/{form → input}/NumberInput.js +0 -0
  192. /package/ui/{form → input}/NumberInput.tsx +0 -0
  193. /package/ui/{form → input}/OutputInput.d.ts +0 -0
  194. /package/ui/{form → input}/OutputInput.js +0 -0
  195. /package/ui/{form → input}/OutputInput.tsx +0 -0
  196. /package/ui/{form → input}/Popover.d.ts +0 -0
  197. /package/ui/{form → input}/Popover.js +0 -0
  198. /package/ui/{form → input}/Popover.module.css +0 -0
  199. /package/ui/{form → input}/Popover.tsx +0 -0
  200. /package/ui/{form → input}/QueryInput.d.ts +0 -0
  201. /package/ui/{form → input}/QueryInput.js +0 -0
  202. /package/ui/{form → input}/QueryInput.tsx +0 -0
  203. /package/ui/{form → input}/RadioInput.d.ts +0 -0
  204. /package/ui/{form → input}/RadioInput.js +0 -0
  205. /package/ui/{form → input}/RadioInput.tsx +0 -0
  206. /package/ui/{form → input}/SchemaInput.d.ts +0 -0
  207. /package/ui/{form → input}/SchemaInput.md +0 -0
  208. /package/ui/{form → input}/SelectInput.d.ts +0 -0
  209. /package/ui/{form → input}/SelectInput.js +0 -0
  210. /package/ui/{form → input}/SelectInput.tsx +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shelving",
3
- "version": "1.264.0",
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));
@@ -1,5 +1,5 @@
1
1
  import type { ReactElement } from "react";
2
- import { type ClickableProps } from "../form/Clickable.js";
2
+ import { type ClickableProps } from "../button/Clickable.js";
3
3
  import { type BlockVariants } from "../style/Block.js";
4
4
  import { type StatusVariants } from "../style/Status.js";
5
5
  import type { BlockElement } from "./Block.js";
package/ui/block/Card.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Clickable } from "../form/Clickable.js";
2
+ import { Clickable } from "../button/Clickable.js";
3
3
  import { getBlockClass } from "../style/Block.js";
4
4
  import { getStatusClass } from "../style/Status.js";
5
5
  import { getClass, getModuleClass } from "../util/css.js";
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;
package/ui/block/Card.tsx CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { ReactElement } from "react";
2
- import { Clickable, type ClickableProps } from "../form/Clickable.js";
2
+ import { Clickable, type ClickableProps } from "../button/Clickable.js";
3
3
  import { type BlockVariants, getBlockClass } from "../style/Block.js";
4
4
  import { getStatusClass, type StatusVariants } from "../style/Status.js";
5
5
  import { getClass, getModuleClass } from "../util/css.js";
@@ -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));
@@ -1,6 +1,6 @@
1
1
  import type { ReactElement } from "react";
2
- import { type SpaceVariants } from "../style/Space.js";
3
- import { type WidthVariants } from "../style/Width.js";
2
+ import type { SpaceVariants } from "../style/Space.js";
3
+ import type { WidthVariants } from "../style/Width.js";
4
4
  /**
5
5
  * Props for `Image` — an `src`, optional `alt` text, plus space and width variants.
6
6
  *
@@ -17,4 +17,4 @@ export interface ImageProps extends SpaceVariants, WidthVariants {
17
17
  * @example <Image src="/logo.png" alt="Logo" width="narrow" />
18
18
  * @see https://shelving.cc/ui/Image
19
19
  */
20
- export declare function Image({ src, alt, ...variants }: ImageProps): ReactElement;
20
+ export declare function Image({ src, alt, ...props }: ImageProps): ReactElement;
package/ui/block/Image.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { getSpaceClass } from "../style/Space.js";
3
- import { getWidthClass } from "../style/Width.js";
2
+ import { getBlockClass } from "../style/Block.js";
4
3
  import { getClass, getModuleClass } from "../util/css.js";
5
4
  import IMAGE_CSS from "./Image.module.css";
6
5
  const IMAGE_CLASS = getModuleClass(IMAGE_CSS, "image");
@@ -11,6 +10,7 @@ const IMAGE_CLASS = getModuleClass(IMAGE_CSS, "image");
11
10
  * @example <Image src="/logo.png" alt="Logo" width="narrow" />
12
11
  * @see https://shelving.cc/ui/Image
13
12
  */
14
- export function Image({ src, alt, ...variants }) {
15
- return _jsx("img", { src: src, alt: alt, className: getClass(IMAGE_CLASS, getSpaceClass(variants), getWidthClass(variants)) });
13
+ export function Image({ src, alt, ...props }) {
14
+ return (_jsx("img", { src: src, alt: alt, className: getClass(IMAGE_CLASS, //
15
+ getBlockClass(props)) }));
16
16
  }
@@ -4,9 +4,12 @@
4
4
  @layer components {
5
5
  .image,
6
6
  .prose img {
7
- inline-size: var(--image-width, 100%);
7
+ /* Box */
8
+ border: var(--image-border, none);
9
+ border-radius: var(--image-radius, var(--radius-normal));
8
10
  margin-block: var(--image-space, var(--space-paragraph));
9
11
 
12
+ /* Contents */
10
13
  object-position: center center;
11
14
  object-fit: cover; /* Don't distort when resized. */
12
15
  }
@@ -1,6 +1,7 @@
1
1
  import type { ReactElement } from "react";
2
- import { getSpaceClass, type SpaceVariants } from "../style/Space.js";
3
- import { getWidthClass, type WidthVariants } from "../style/Width.js";
2
+ import { getBlockClass } from "../style/Block.js";
3
+ import type { SpaceVariants } from "../style/Space.js";
4
+ import type { WidthVariants } from "../style/Width.js";
4
5
  import { getClass, getModuleClass } from "../util/css.js";
5
6
  import IMAGE_CSS from "./Image.module.css";
6
7
 
@@ -23,6 +24,15 @@ export interface ImageProps extends SpaceVariants, WidthVariants {
23
24
  * @example <Image src="/logo.png" alt="Logo" width="narrow" />
24
25
  * @see https://shelving.cc/ui/Image
25
26
  */
26
- export function Image({ src, alt, ...variants }: ImageProps): ReactElement {
27
- return <img src={src} alt={alt} className={getClass(IMAGE_CLASS, getSpaceClass(variants), getWidthClass(variants))} />;
27
+ export function Image({ src, alt, ...props }: ImageProps): ReactElement {
28
+ return (
29
+ <img
30
+ src={src}
31
+ alt={alt}
32
+ className={getClass(
33
+ IMAGE_CLASS, //
34
+ getBlockClass(props),
35
+ )}
36
+ />
37
+ );
28
38
  }
@@ -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));
@@ -1,7 +1,7 @@
1
- import { type MouseEvent, type ReactElement } from "react";
1
+ import { type ReactElement } from "react";
2
2
  import type { SpaceVariants } from "../style/Space.js";
3
3
  import type { WidthVariants } from "../style/Width.js";
4
- import type { ChildProps, OptionalChildProps } from "../util/props.js";
4
+ import type { OptionalChildProps } from "../util/props.js";
5
5
  /**
6
6
  * Props for `Video` — space and width variants plus optional `children`.
7
7
  *
@@ -9,68 +9,13 @@ import type { ChildProps, OptionalChildProps } from "../util/props.js";
9
9
  */
10
10
  export interface VideoProps extends SpaceVariants, WidthVariants, OptionalChildProps {
11
11
  }
12
- /**
13
- * Props for `VideoButtons` — `children` plus an optional `left` alignment flag.
14
- *
15
- * @see https://shelving.cc/ui/VideoButtonsProps
16
- */
17
- export interface VideoButtonsProps extends ChildProps {
18
- left?: boolean;
19
- }
20
- /**
21
- * Props for `VideoButton` — `children` plus optional `title`, `onClick`, `danger`, and `disabled`.
22
- *
23
- * @see https://shelving.cc/ui/VideoButtonProps
24
- */
25
- export interface VideoButtonProps extends ChildProps {
26
- title?: string | undefined;
27
- onClick?: (event: MouseEvent<HTMLButtonElement>) => void;
28
- danger?: boolean;
29
- disabled?: boolean;
30
- }
31
12
  /**
32
13
  * Video container element.
33
14
  * - Has a black background and a 16:9 aspect ratio.
34
- * - Shows its contents (i.e. a `<video>` element or a `<TwilioRoom>`.
15
+ * - Shows its contents (i.e. a `<video>` element or a `<TwilioRoom>`).
35
16
  *
36
17
  * @kind component
37
18
  * @example <Video><video src="/clip.mp4" /></Video>
38
19
  * @see https://shelving.cc/ui/Video
39
20
  */
40
21
  export declare function Video({ children, ...props }: VideoProps): ReactElement;
41
- /**
42
- * Set of video buttons floating over a video.
43
- *
44
- * @example <VideoButtons><FullscreenVideoButton /></VideoButtons>
45
- * @see https://shelving.cc/ui/VideoButtons
46
- */
47
- export declare function VideoButtons({ children, ...variants }: VideoButtonsProps): import("react").JSX.Element;
48
- /**
49
- * Individual video button over a video — renders a `<button>`.
50
- *
51
- * @kind component
52
- * @example <VideoButton title="Play" onClick={play}><PlayIcon /></VideoButton>
53
- * @see https://shelving.cc/ui/VideoButton
54
- */
55
- export declare function VideoButton({ children, title, onClick, disabled, ...variants }: VideoButtonProps): ReactElement;
56
- declare const _fullscreenVideoButtonProps: unique symbol;
57
- /**
58
- * Props for `FullscreenVideoButton` — an empty marker interface (the component takes no props).
59
- *
60
- * @see https://shelving.cc/ui/FullscreenVideoButtonProps
61
- */
62
- export interface FullscreenVideoButtonProps {
63
- readonly [_fullscreenVideoButtonProps]?: never;
64
- }
65
- /**
66
- * Button to toggle the surrounding video element in and out of fullscreen.
67
- * - Renders `null` when the browser does not support the Fullscreen API.
68
- * - Tracks fullscreen state so the icon and title flip between enter/exit.
69
- *
70
- * @returns Rendered fullscreen toggle button, or `null` when fullscreen is unavailable.
71
- * @kind component
72
- * @example <Video><video src="/clip.mp4" /><VideoButtons><FullscreenVideoButton /></VideoButtons></Video>
73
- * @see https://shelving.cc/ui/FullscreenVideoButton
74
- */
75
- export declare function FullscreenVideoButton(): ReactElement | null;
76
- export {};
package/ui/block/Video.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { ArrowsPointingInIcon, ArrowsPointingOutIcon } from "@heroicons/react/24/solid";
3
- import { useEffect, useRef, useState } from "react";
2
+ import { useRef } from "react";
4
3
  import { getBlockClass } from "../style/Block.js";
5
4
  import { getClass, getModuleClass } from "../util/css.js";
6
5
  import VIDEO_CSS from "./Video.module.css";
@@ -8,7 +7,7 @@ const VIDEO_CLASS = getModuleClass(VIDEO_CSS, "video");
8
7
  /**
9
8
  * Video container element.
10
9
  * - Has a black background and a 16:9 aspect ratio.
11
- * - Shows its contents (i.e. a `<video>` element or a `<TwilioRoom>`.
10
+ * - Shows its contents (i.e. a `<video>` element or a `<TwilioRoom>`).
12
11
  *
13
12
  * @kind component
14
13
  * @example <Video><video src="/clip.mp4" /></Video>
@@ -19,52 +18,3 @@ export function Video({ children, ...props }) {
19
18
  return (_jsx("figure", { ref: ref, className: getClass(VIDEO_CLASS, //
20
19
  getBlockClass(props)), children: children }));
21
20
  }
22
- /**
23
- * Set of video buttons floating over a video.
24
- *
25
- * @example <VideoButtons><FullscreenVideoButton /></VideoButtons>
26
- * @see https://shelving.cc/ui/VideoButtons
27
- */
28
- export function VideoButtons({ children, ...variants }) {
29
- return _jsx("div", { className: getModuleClass(VIDEO_CSS, "buttons", variants), children: children });
30
- }
31
- /**
32
- * Individual video button over a video — renders a `<button>`.
33
- *
34
- * @kind component
35
- * @example <VideoButton title="Play" onClick={play}><PlayIcon /></VideoButton>
36
- * @see https://shelving.cc/ui/VideoButton
37
- */
38
- export function VideoButton({ children, title, onClick, disabled, ...variants }) {
39
- return (_jsx("button", { type: "button", onClick: onClick, className: getModuleClass(VIDEO_CSS, "button", variants), title: title, disabled: disabled, children: children }));
40
- }
41
- /**
42
- * Button to toggle the surrounding video element in and out of fullscreen.
43
- * - Renders `null` when the browser does not support the Fullscreen API.
44
- * - Tracks fullscreen state so the icon and title flip between enter/exit.
45
- *
46
- * @returns Rendered fullscreen toggle button, or `null` when fullscreen is unavailable.
47
- * @kind component
48
- * @example <Video><video src="/clip.mp4" /><VideoButtons><FullscreenVideoButton /></VideoButtons></Video>
49
- * @see https://shelving.cc/ui/FullscreenVideoButton
50
- */
51
- export function FullscreenVideoButton() {
52
- const [isFull, setFull] = useState(() => typeof document !== "undefined" && !!document.fullscreenElement);
53
- useEffect(() => {
54
- const onChange = () => setFull(!!document.fullscreenElement);
55
- document.addEventListener("fullscreenchange", onChange);
56
- return () => document.removeEventListener("fullscreenchange", onChange);
57
- });
58
- if (!document.fullscreenEnabled)
59
- return null;
60
- return (_jsx(VideoButton, { title: isFull ? "Exit full screen mode" : "Enter full screen mode", onClick: ({ currentTarget }) => {
61
- if (document.fullscreenElement) {
62
- document.exitFullscreen();
63
- }
64
- else {
65
- const parent = currentTarget.closest("figure, video");
66
- if (parent)
67
- parent.requestFullscreen();
68
- }
69
- }, children: isFull ? _jsx(ArrowsPointingInIcon, {}) : _jsx(ArrowsPointingOutIcon, {}) }));
70
- }
@@ -12,7 +12,7 @@
12
12
  /* Box */
13
13
  aspect-ratio: 16 / 9;
14
14
  margin-block: var(--video-space, var(--space-paragraph));
15
- border: var(--video-border, var(--stroke-normal) solid black);
15
+ border: var(--video-border, none);
16
16
  border-radius: var(--video-radius, var(--radius-normal));
17
17
  padding: var(--video-padding, var(--space-normal));
18
18
 
@@ -35,54 +35,4 @@
35
35
  border-radius: 0;
36
36
  }
37
37
  }
38
-
39
- .buttons {
40
- position: absolute;
41
- top: var(--video-buttons-offset-y, var(--space-normal));
42
- right: var(--video-buttons-offset-x, var(--space-normal));
43
- display: flex;
44
- gap: var(--video-buttons-gap, var(--space-small));
45
-
46
- &.left {
47
- right: auto;
48
- left: var(--video-buttons-offset-x, var(--space-normal));
49
- }
50
- }
51
-
52
- .button {
53
- /* Box */
54
- display: block;
55
- border: var(--video-button-border, var(--stroke-normal) solid black);
56
- border-radius: var(--video-button-radius, 100rem);
57
- padding-inline: var(--video-button-padding-x, var(--space-xsmall));
58
-
59
- /* Style */
60
- color: var(--video-button-text, white);
61
- background: var(--video-button-bg, black);
62
- transition: var(--video-button-transition, all var(--duration-fast));
63
- outline: var(--video-button-focus-border, var(--stroke-focus) solid var(--color-focus));
64
- outline-offset: calc(0px - var(--stroke-normal));
65
- box-shadow: var(--video-button-shadow, var(--shadow-normal));
66
- cursor: pointer;
67
-
68
- /* Pseudo-classes */
69
- &:disabled,
70
- &:where(a:not(:any-link)) {
71
- opacity: var(--video-button-disabled-opacity, 0.5);
72
- cursor: default;
73
- }
74
- &:enabled:hover,
75
- &:any-link:hover,
76
- &:focus:not(:focus-visible) {
77
- background: color-mix(in oklch, white 85%, transparent);
78
- }
79
- }
80
- }
81
-
82
- @layer overrides {
83
- .button {
84
- &:not(:focus-visible) {
85
- outline-color: transparent;
86
- }
87
- }
88
38
  }