shelving 1.236.2 → 1.237.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.
Files changed (219) hide show
  1. package/extract/IndexExtractor.js +9 -2
  2. package/extract/MergingExtractor.d.ts +3 -1
  3. package/extract/MergingExtractor.js +41 -3
  4. package/extract/TypescriptExtractor.d.ts +1 -0
  5. package/extract/TypescriptExtractor.js +12 -2
  6. package/package.json +1 -1
  7. package/ui/README.md +19 -274
  8. package/ui/app/App.d.ts +1 -0
  9. package/ui/app/App.js +1 -0
  10. package/ui/app/App.md +58 -0
  11. package/ui/app/App.tsx +1 -0
  12. package/ui/block/Card.d.ts +1 -0
  13. package/ui/block/Card.js +1 -0
  14. package/ui/block/Card.md +85 -0
  15. package/ui/block/Card.tsx +1 -0
  16. package/ui/block/Heading.d.ts +1 -0
  17. package/ui/block/Heading.js +1 -0
  18. package/ui/block/Heading.md +70 -0
  19. package/ui/block/Heading.tsx +1 -0
  20. package/ui/block/List.d.ts +1 -0
  21. package/ui/block/List.js +1 -0
  22. package/ui/block/List.md +51 -0
  23. package/ui/block/List.tsx +1 -0
  24. package/ui/block/Panel.d.ts +1 -0
  25. package/ui/block/Panel.js +1 -0
  26. package/ui/block/Panel.md +50 -0
  27. package/ui/block/Panel.tsx +1 -0
  28. package/ui/block/Paragraph.d.ts +1 -0
  29. package/ui/block/Paragraph.js +1 -0
  30. package/ui/block/Paragraph.md +48 -0
  31. package/ui/block/Paragraph.tsx +1 -0
  32. package/ui/block/Prose.d.ts +1 -0
  33. package/ui/block/Prose.js +1 -0
  34. package/ui/block/Prose.md +49 -0
  35. package/ui/block/Prose.tsx +1 -0
  36. package/ui/block/Section.d.ts +6 -0
  37. package/ui/block/Section.js +6 -0
  38. package/ui/block/Section.md +56 -0
  39. package/ui/block/Section.tsx +6 -0
  40. package/ui/block/Subheading.d.ts +1 -0
  41. package/ui/block/Subheading.js +1 -0
  42. package/ui/block/Subheading.md +58 -0
  43. package/ui/block/Subheading.tsx +1 -0
  44. package/ui/block/Table.d.ts +1 -0
  45. package/ui/block/Table.js +1 -0
  46. package/ui/block/Table.md +54 -0
  47. package/ui/block/Table.tsx +1 -0
  48. package/ui/block/Title.d.ts +1 -0
  49. package/ui/block/Title.js +1 -0
  50. package/ui/block/Title.md +57 -0
  51. package/ui/block/Title.tsx +1 -0
  52. package/ui/dialog/Dialog.d.ts +1 -0
  53. package/ui/dialog/Dialog.js +1 -0
  54. package/ui/dialog/Dialog.md +73 -0
  55. package/ui/dialog/Dialog.tsx +1 -0
  56. package/ui/dialog/Modal.d.ts +1 -0
  57. package/ui/dialog/Modal.js +1 -0
  58. package/ui/dialog/Modal.md +40 -0
  59. package/ui/dialog/Modal.tsx +1 -0
  60. package/ui/docs/DocumentationButtons.d.ts +2 -0
  61. package/ui/docs/DocumentationButtons.js +2 -0
  62. package/ui/docs/DocumentationButtons.md +38 -0
  63. package/ui/docs/DocumentationButtons.tsx +2 -0
  64. package/ui/docs/DocumentationCard.d.ts +1 -0
  65. package/ui/docs/DocumentationCard.js +1 -0
  66. package/ui/docs/DocumentationCard.md +35 -0
  67. package/ui/docs/DocumentationCard.tsx +1 -0
  68. package/ui/docs/DocumentationKind.d.ts +1 -1
  69. package/ui/docs/DocumentationKind.js +9 -4
  70. package/ui/docs/DocumentationKind.tsx +10 -5
  71. package/ui/docs/DocumentationPage.d.ts +1 -0
  72. package/ui/docs/DocumentationPage.js +2 -0
  73. package/ui/docs/DocumentationPage.md +46 -0
  74. package/ui/docs/DocumentationPage.tsx +2 -0
  75. package/ui/form/Button.d.ts +1 -0
  76. package/ui/form/Button.js +1 -0
  77. package/ui/form/Button.md +88 -0
  78. package/ui/form/Button.tsx +1 -0
  79. package/ui/form/Field.d.ts +6 -1
  80. package/ui/form/Field.js +6 -1
  81. package/ui/form/Field.md +59 -0
  82. package/ui/form/Field.tsx +6 -1
  83. package/ui/form/Form.d.ts +1 -0
  84. package/ui/form/Form.md +118 -0
  85. package/ui/form/Form.tsx +1 -0
  86. package/ui/form/FormStore.md +47 -0
  87. package/ui/form/SchemaInput.d.ts +1 -0
  88. package/ui/form/SchemaInput.md +64 -0
  89. package/ui/form/SchemaInput.tsx +1 -0
  90. package/ui/inline/Code.d.ts +1 -0
  91. package/ui/inline/Code.js +1 -0
  92. package/ui/inline/Code.md +58 -0
  93. package/ui/inline/Code.tsx +1 -0
  94. package/ui/inline/Link.d.ts +1 -0
  95. package/ui/inline/Link.js +1 -0
  96. package/ui/inline/Link.md +47 -0
  97. package/ui/inline/Link.tsx +1 -0
  98. package/ui/inline/Mark.d.ts +1 -0
  99. package/ui/inline/Mark.js +1 -0
  100. package/ui/inline/Mark.md +40 -0
  101. package/ui/inline/Mark.tsx +1 -0
  102. package/ui/inline/Strong.d.ts +1 -0
  103. package/ui/inline/Strong.js +1 -0
  104. package/ui/inline/Strong.md +34 -0
  105. package/ui/inline/Strong.tsx +1 -0
  106. package/ui/layout/CenteredLayout.d.ts +1 -0
  107. package/ui/layout/CenteredLayout.js +1 -0
  108. package/ui/layout/CenteredLayout.md +38 -0
  109. package/ui/layout/CenteredLayout.tsx +1 -0
  110. package/ui/layout/SidebarLayout.d.ts +1 -0
  111. package/ui/layout/SidebarLayout.js +1 -0
  112. package/ui/layout/SidebarLayout.md +65 -0
  113. package/ui/layout/SidebarLayout.tsx +1 -0
  114. package/ui/menu/Menu.d.ts +2 -0
  115. package/ui/menu/Menu.js +2 -0
  116. package/ui/menu/Menu.md +51 -0
  117. package/ui/menu/Menu.tsx +2 -0
  118. package/ui/menu/MenuItem.md +54 -0
  119. package/ui/misc/Catcher.d.ts +1 -0
  120. package/ui/misc/Catcher.js +1 -0
  121. package/ui/misc/Catcher.md +41 -0
  122. package/ui/misc/Catcher.tsx +1 -0
  123. package/ui/misc/Loading.d.ts +1 -0
  124. package/ui/misc/Loading.js +1 -0
  125. package/ui/misc/Loading.md +28 -0
  126. package/ui/misc/Loading.tsx +1 -0
  127. package/ui/misc/Mapper.md +40 -0
  128. package/ui/misc/Markup.d.ts +1 -0
  129. package/ui/misc/Markup.js +1 -0
  130. package/ui/misc/Markup.md +34 -0
  131. package/ui/misc/Markup.tsx +1 -0
  132. package/ui/misc/StatusIcon.d.ts +1 -0
  133. package/ui/misc/StatusIcon.js +1 -0
  134. package/ui/misc/StatusIcon.md +25 -0
  135. package/ui/misc/StatusIcon.tsx +1 -0
  136. package/ui/misc/Tag.d.ts +1 -0
  137. package/ui/misc/Tag.js +1 -0
  138. package/ui/misc/Tag.md +47 -0
  139. package/ui/misc/Tag.tsx +1 -0
  140. package/ui/notice/Notice.d.ts +1 -0
  141. package/ui/notice/Notice.js +1 -0
  142. package/ui/notice/Notice.md +53 -0
  143. package/ui/notice/Notice.tsx +1 -0
  144. package/ui/notice/Notices.d.ts +1 -0
  145. package/ui/notice/Notices.js +1 -0
  146. package/ui/notice/Notices.md +59 -0
  147. package/ui/notice/Notices.tsx +1 -0
  148. package/ui/page/HTML.d.ts +1 -0
  149. package/ui/page/HTML.js +1 -0
  150. package/ui/page/HTML.md +36 -0
  151. package/ui/page/HTML.tsx +1 -0
  152. package/ui/page/Head.d.ts +1 -0
  153. package/ui/page/Head.js +1 -0
  154. package/ui/page/Head.md +26 -0
  155. package/ui/page/Head.tsx +1 -0
  156. package/ui/page/Page.d.ts +1 -0
  157. package/ui/page/Page.js +1 -0
  158. package/ui/page/Page.md +42 -0
  159. package/ui/page/Page.tsx +1 -0
  160. package/ui/router/Navigation.d.ts +1 -0
  161. package/ui/router/Navigation.js +1 -0
  162. package/ui/router/Navigation.md +41 -0
  163. package/ui/router/Navigation.tsx +1 -0
  164. package/ui/router/NavigationStore.md +34 -0
  165. package/ui/router/Router.d.ts +1 -0
  166. package/ui/router/Router.js +1 -0
  167. package/ui/router/Router.md +143 -0
  168. package/ui/router/Router.tsx +1 -0
  169. package/ui/style/TINT_CLASS.md +55 -0
  170. package/ui/transition/CollapseTransition.d.ts +1 -0
  171. package/ui/transition/CollapseTransition.js +1 -0
  172. package/ui/transition/CollapseTransition.md +34 -0
  173. package/ui/transition/CollapseTransition.tsx +1 -0
  174. package/ui/transition/FadeTransition.d.ts +1 -0
  175. package/ui/transition/FadeTransition.js +1 -0
  176. package/ui/transition/FadeTransition.md +36 -0
  177. package/ui/transition/FadeTransition.tsx +1 -0
  178. package/ui/transition/HorizontalTransition.d.ts +1 -0
  179. package/ui/transition/HorizontalTransition.js +1 -0
  180. package/ui/transition/HorizontalTransition.md +44 -0
  181. package/ui/transition/HorizontalTransition.tsx +1 -0
  182. package/ui/transition/Transition.d.ts +1 -0
  183. package/ui/transition/Transition.js +1 -0
  184. package/ui/transition/Transition.md +70 -0
  185. package/ui/transition/Transition.tsx +1 -0
  186. package/ui/transition/VerticalTransition.d.ts +1 -0
  187. package/ui/transition/VerticalTransition.js +1 -0
  188. package/ui/transition/VerticalTransition.md +34 -0
  189. package/ui/transition/VerticalTransition.tsx +1 -0
  190. package/ui/tree/TreeApp.d.ts +1 -0
  191. package/ui/tree/TreeApp.js +1 -0
  192. package/ui/tree/TreeApp.md +59 -0
  193. package/ui/tree/TreeApp.tsx +1 -0
  194. package/ui/tree/TreeMenu.d.ts +1 -0
  195. package/ui/tree/TreeMenu.js +1 -0
  196. package/ui/tree/TreeMenu.md +35 -0
  197. package/ui/tree/TreeMenu.tsx +1 -0
  198. package/ui/tree/TreeSidebar.d.ts +1 -0
  199. package/ui/tree/TreeSidebar.js +1 -0
  200. package/ui/tree/TreeSidebar.md +24 -0
  201. package/ui/tree/TreeSidebar.tsx +1 -0
  202. package/ui/util/getClass.md +55 -0
  203. package/ui/util/notify.md +50 -0
  204. package/ui/util/requireContext.md +24 -0
  205. package/ui/app/README.md +0 -32
  206. package/ui/block/README.md +0 -144
  207. package/ui/dialog/README.md +0 -80
  208. package/ui/docs/README.md +0 -71
  209. package/ui/form/README.md +0 -165
  210. package/ui/inline/README.md +0 -86
  211. package/ui/layout/README.md +0 -71
  212. package/ui/menu/README.md +0 -33
  213. package/ui/misc/README.md +0 -121
  214. package/ui/notice/README.md +0 -94
  215. package/ui/page/README.md +0 -56
  216. package/ui/router/README.md +0 -186
  217. package/ui/transition/README.md +0 -80
  218. package/ui/tree/README.md +0 -78
  219. package/ui/util/README.md +0 -153
@@ -0,0 +1,64 @@
1
+ # SchemaInput
2
+
3
+ Schema-driven input dispatch. `SchemaInput` inspects a `Schema` instance and renders the right control automatically — the same mechanism [`Form`](/ui/Form) uses to turn a `DataSchema` into a complete set of inputs.
4
+
5
+ **Things to know:**
6
+
7
+ - `required` defaults to whether the schema is required (i.e. not wrapped in an `OptionalSchema` or `NullableSchema`); override it explicitly when needed.
8
+ - It throws an `UnexpectedError` if no input matches the schema type.
9
+ - `SchemaField` wraps the chosen input in a [`Field`](/ui/Field) with its label and message; pass `children` to override the input while keeping the field chrome.
10
+ - Every input it dispatches to is a standalone, controlled component extending `ValueInputProps<O>` — see the prop contract below.
11
+
12
+ The schema-to-input mapping:
13
+
14
+ | Schema type | Rendered as |
15
+ |---|---|
16
+ | `StringSchema` | [`TextInput`](/ui/TextInput) |
17
+ | `NumberSchema` | [`NumberInput`](/ui/NumberInput) (formatted on blur) |
18
+ | `DateSchema` | [`DateInput`](/ui/DateInput) |
19
+ | `BooleanSchema` | [`CheckboxInput`](/ui/CheckboxInput) |
20
+ | `ChoiceSchema` (≤ 8 options) | [`ChoiceRadioInputs`](/ui/ChoiceRadioInputs) |
21
+ | `ChoiceSchema` (> 8 options) | [`SelectInput`](/ui/SelectInput) |
22
+ | `ArraySchema` | [`ArrayInput`](/ui/ArrayInput) |
23
+ | `DictionarySchema` | [`DictionaryInput`](/ui/DictionaryInput) |
24
+ | `DataSchema` | [`DataInput`](/ui/DataInput) |
25
+
26
+ The shared value-input prop contract (`ValueInputProps<O>`):
27
+
28
+ | Prop | Contract |
29
+ |---|---|
30
+ | `name` | HTML field name |
31
+ | `value` | Current value |
32
+ | `onValue(v)` | Called on every change |
33
+ | `required` | Marks the field as required |
34
+ | `disabled` | Disables the control |
35
+ | `message` | Inline error string |
36
+
37
+ [`DataInput`](/ui/DataInput) renders a row of `SchemaInput` elements for each property of a nested data object, and propagates sub-field errors from a `"key: message\n…"` formatted `message` string. `ArrayInput` and `DictionaryInput` both accept an `items` schema to render a repeatable list of sub-inputs with add/remove buttons.
38
+
39
+ ## Usage
40
+
41
+ ### Dispatch on a single schema
42
+
43
+ ```tsx
44
+ import { SchemaInput } from "shelving/ui";
45
+ import { StringSchema, NumberSchema } from "shelving/schema";
46
+
47
+ <SchemaInput name="email" schema={new StringSchema({ title: "Email" })} /> // -> <TextInput>
48
+ <SchemaInput name="age" schema={new NumberSchema({ title: "Age" })} /> // -> <NumberInput>
49
+ ```
50
+
51
+ ### Wrapped in a field
52
+
53
+ ```tsx
54
+ import { SchemaField } from "shelving/ui";
55
+
56
+ <SchemaField name="email" schema={EMAIL_SCHEMA} /> // <Field> wrapping a <TextInput>
57
+ ```
58
+
59
+ ## See also
60
+
61
+ - [`Form`](/ui/Form) — drives `SchemaInput` for every property of its schema.
62
+ - [`Field`](/ui/Field) — the label + input + error wrapper `SchemaField` composes.
63
+ - [schema](/schema) — the `Schema` types `SchemaInput` dispatches on.
64
+ - [ui](/ui) — top-level UI module index.
@@ -61,6 +61,7 @@ export interface SchemaInputProps<T extends Schema, I = never> extends ValueInpu
61
61
  * @param props Props including the `schema` plus value input props.
62
62
  * @returns The matching input element for the schema.
63
63
  * @throws `UnexpectedError` if no input matches the schema type.
64
+ * @kind component
64
65
  * @example <SchemaInput name="email" schema={EMAIL} /> // Outputs a `<TextInput>` for the "email" property.
65
66
  * @example <SchemaInput name="age" schema={AGE} /> // Outputs a `<NumberInput>` for the "age" property.
66
67
  * @see https://dhoulb.github.io/shelving/ui/form/SchemaInput/SchemaInput
@@ -32,6 +32,7 @@ export interface CodeProps extends ColorVariants, TypographyVariants, OptionalCh
32
32
  * Inline code span — renders a `<code>` element.
33
33
  * - Pass `plain` to drop the default background and padding.
34
34
  *
35
+ * @kind component
35
36
  * @param props Colour and typography variants, `children`, plus an optional `plain` toggle.
36
37
  * @returns Rendered `<code>` element.
37
38
  * @example <Code>npm install</Code>
package/ui/inline/Code.js CHANGED
@@ -24,6 +24,7 @@ export const CODE_PROSE_CLASS = getModuleClass(CODE_CSS, "prose");
24
24
  * Inline code span — renders a `<code>` element.
25
25
  * - Pass `plain` to drop the default background and padding.
26
26
  *
27
+ * @kind component
27
28
  * @param props Colour and typography variants, `children`, plus an optional `plain` toggle.
28
29
  * @returns Rendered `<code>` element.
29
30
  * @example <Code>npm install</Code>
@@ -0,0 +1,58 @@
1
+ # Code
2
+
3
+ An inline code span — renders a `<code>` element with monospace type and a subtle tinted background. `Code.tsx` exports four siblings that share the same monospace styling but carry different HTML semantics:
4
+
5
+ | Component | HTML element | Use for |
6
+ | ---------- | ------------ | ------------------------------- |
7
+ | `Code` | `<code>` | Inline code fragments |
8
+ | `Keyboard` | `<kbd>` | Keyboard input, e.g. `Ctrl+S` |
9
+ | `Sample` | `<samp>` | Program output |
10
+ | `Variable` | `<var>` | Variable names in documentation |
11
+
12
+ **Things to know:**
13
+
14
+ - Pick the sibling whose semantics match — they all look the same but mean different things to assistive tech and search.
15
+ - Pass `plain` to drop the default background and inline padding (useful when the code already sits inside a tinted container).
16
+ - Painted from the [tint ladder](/ui/TINT_CLASS): the background is `--tint-90` and the text `--tint-00`, so it re-tints with its surrounding scope.
17
+ - Inside [`Prose`](/ui/Prose) raw `<code>` / `<kbd>` / `<samp>` / `<var>` pick up the same styling, and code inside a `<pre>` drops the inline box automatically.
18
+
19
+ ## Usage
20
+
21
+ ### Inline code and keyboard input
22
+
23
+ ```tsx
24
+ import { Code, Keyboard, Sample } from "shelving/ui";
25
+
26
+ <p>Run <Code>npm install</Code>, then press <Keyboard>Enter</Keyboard>.</p>
27
+ <p>It prints <Sample>Done.</Sample></p>
28
+ ```
29
+
30
+ ### Plain (no background)
31
+
32
+ ```tsx
33
+ import { Code } from "shelving/ui";
34
+
35
+ <Code plain>const x = 1;</Code>
36
+ ```
37
+
38
+ ## Styling
39
+
40
+ `Code` paints from the [tint ladder](/ui/TINT_CLASS); the box (`background` / `color`) reads ladder steps directly, while type, padding, and radius have per-property hooks.
41
+
42
+ | Variable | Styles | Default |
43
+ |---|---|---|
44
+ | `--code-font` | Font family | `var(--font-code)` |
45
+ | `--code-weight` | Font weight | `var(--weight-code)` |
46
+ | `--code-size` | Font size | `var(--size-smaller)` |
47
+ | `--code-leading` | Line height | `var(--leading)` |
48
+ | `--code-padding` | Inline padding (non-`plain`) | `var(--space-xxsmall)` |
49
+ | `--code-radius` | Corner radius (non-`plain`) | `var(--radius-xxsmall)` |
50
+
51
+ **Global tokens it reads:** `--font-code`, `--weight-code`, `--size-smaller`, `--leading`, `--space-xxsmall`, `--radius-xxsmall`, and the tint-ladder steps `--tint-00` / `--tint-90` for the box fill and text.
52
+
53
+ ## See also
54
+
55
+ - [`Preformatted`](/ui/Preformatted) — block-level `<pre>` for multi-line code.
56
+ - [`Mark`](/ui/Mark) — highlight a run of text rather than mark it as code.
57
+ - [`Prose`](/ui/Prose) — styles raw `<code>` and friends inside longform content.
58
+ - [`ui`](/ui) — the styling system: tint ladder and theming.
@@ -39,6 +39,7 @@ export interface CodeProps extends ColorVariants, TypographyVariants, OptionalCh
39
39
  * Inline code span — renders a `<code>` element.
40
40
  * - Pass `plain` to drop the default background and padding.
41
41
  *
42
+ * @kind component
42
43
  * @param props Colour and typography variants, `children`, plus an optional `plain` toggle.
43
44
  * @returns Rendered `<code>` element.
44
45
  * @example <Code>npm install</Code>
@@ -22,6 +22,7 @@ export interface LinkProps extends ClickableProps {
22
22
  /**
23
23
  * Inline link — delegates to `Clickable`, rendering an `<a>` (when `href` is set) or `<button>` (when `onClick` is set).
24
24
  *
25
+ * @kind component
25
26
  * @param props Clickable props such as `href`, `onClick`, `title`, and `children`.
26
27
  * @returns Rendered inline `<a>` or `<button>` element.
27
28
  * @example <Link href="/about">About us</Link>
package/ui/inline/Link.js CHANGED
@@ -17,6 +17,7 @@ export const LINK_PROSE_CLASS = getModuleClass(LINK_CSS, "prose");
17
17
  /**
18
18
  * Inline link — delegates to `Clickable`, rendering an `<a>` (when `href` is set) or `<button>` (when `onClick` is set).
19
19
  *
20
+ * @kind component
20
21
  * @param props Clickable props such as `href`, `onClick`, `title`, and `children`.
21
22
  * @returns Rendered inline `<a>` or `<button>` element.
22
23
  * @example <Link href="/about">About us</Link>
@@ -0,0 +1,47 @@
1
+ # Link
2
+
3
+ An inline link or action. Delegates to [`Clickable`](/ui/Clickable), rendering an `<a>` when `href` is provided or a `<button>` when `onClick` is provided — so the same component covers both navigation and in-page actions. Prefer it over a raw `<a>` inside React components.
4
+
5
+ **Things to know:**
6
+
7
+ - It handles busy state, URL resolution, and active-page highlighting automatically via the shared `Clickable` helper.
8
+ - An `<a>` (any actual link) shows an underline that disappears on hover; a `<button>` variant carries no underline.
9
+ - Reach for `Link` for inline text links; for standalone calls to action use a button-styled component instead.
10
+ - Inside [`Prose`](/ui/Prose) a raw `<a>` picks up the same styling, so Markdown-rendered links match component ones.
11
+
12
+ ## Usage
13
+
14
+ ### Link inside body copy
15
+
16
+ ```tsx
17
+ import { Paragraph, Link } from "shelving/ui";
18
+
19
+ <Paragraph>
20
+ Read our <Link href="/privacy">privacy policy</Link> for details.
21
+ </Paragraph>
22
+ ```
23
+
24
+ ### Action button
25
+
26
+ ```tsx
27
+ import { Link } from "shelving/ui";
28
+
29
+ <Link onClick={() => save()}>Save now</Link>
30
+ ```
31
+
32
+ ## Styling
33
+
34
+ `Link` exposes a couple of inline hooks; the link colour comes from the global `--color-link` token.
35
+
36
+ | Variable | Styles | Default |
37
+ |---|---|---|
38
+ | `--link-weight` | Text colour and font weight | `var(--color-link)` colour / `var(--weight-strong)` weight |
39
+
40
+ **Global tokens it reads:** `--color-link`, `--weight-strong`, and `--stroke-normal` (the underline thickness).
41
+
42
+ ## See also
43
+
44
+ - [`Clickable`](/ui/Clickable) — the underlying primitive that renders `<a>` vs `<button>`.
45
+ - [`Strong`](/ui/Strong) — emphasis for runs of text that are not links.
46
+ - [`Prose`](/ui/Prose) — styles raw `<a>` inside longform content.
47
+ - [`ui`](/ui) — the styling system and theming tokens.
@@ -27,6 +27,7 @@ export interface LinkProps extends ClickableProps {}
27
27
  /**
28
28
  * Inline link — delegates to `Clickable`, rendering an `<a>` (when `href` is set) or `<button>` (when `onClick` is set).
29
29
  *
30
+ * @kind component
30
31
  * @param props Clickable props such as `href`, `onClick`, `title`, and `children`.
31
32
  * @returns Rendered inline `<a>` or `<button>` element.
32
33
  * @example <Link href="/about">About us</Link>
@@ -22,6 +22,7 @@ export interface MarkProps extends OptionalChildProps {
22
22
  /**
23
23
  * Highlighted text — renders a `<mark>` element to call attention to a run of text.
24
24
  *
25
+ * @kind component
25
26
  * @param props The `children` to highlight.
26
27
  * @returns Rendered `<mark>` element.
27
28
  * @example <Mark>search term</Mark>
package/ui/inline/Mark.js CHANGED
@@ -16,6 +16,7 @@ export const MARK_PROSE_CLASS = getModuleClass(MARK_CSS, "prose");
16
16
  /**
17
17
  * Highlighted text — renders a `<mark>` element to call attention to a run of text.
18
18
  *
19
+ * @kind component
19
20
  * @param props The `children` to highlight.
20
21
  * @returns Rendered `<mark>` element.
21
22
  * @example <Mark>search term</Mark>
@@ -0,0 +1,40 @@
1
+ # Mark
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.
4
+
5
+ **Things to know:**
6
+
7
+ - Use it for relevance highlighting (search hits, the current match), not for general emphasis — reach for [`Strong`](/ui/Strong) or [`Emphasis`](/ui/Emphasis) for that.
8
+ - It is a self-contained inline pill: it adds its own inline padding and rounded corners.
9
+ - Inside [`Prose`](/ui/Prose) a raw `<mark>` picks up the same styling, so Markdown-rendered highlights match component ones.
10
+
11
+ ## Usage
12
+
13
+ ### Highlighted search term
14
+
15
+ ```tsx
16
+ import { Mark } from "shelving/ui";
17
+
18
+ <p>Files are stored in <Mark>UTF-8</Mark> encoding.</p>
19
+ ```
20
+
21
+ ## Styling
22
+
23
+ `Mark` is a fixed-palette highlight: it paints from dedicated colour hooks rather than the tint ladder.
24
+
25
+ | Variable | Styles | Default |
26
+ |---|---|---|
27
+ | `--mark-color-bg` | Background fill | `var(--light-yellow)` |
28
+ | `--mark-color-text` | Text colour | `var(--dark-yellow)` |
29
+ | `--mark-padding` | Inline padding | `0.375em` |
30
+ | `--mark-radius` | Corner radius | `var(--radius-xxsmall)` |
31
+ | `--mark-weight` | Font weight | `var(--weight-strong)` |
32
+
33
+ **Global tokens it reads:** `--light-yellow`, `--dark-yellow`, `--radius-xxsmall`, and `--weight-strong`.
34
+
35
+ ## See also
36
+
37
+ - [`Strong`](/ui/Strong) — strong importance rather than relevance highlighting.
38
+ - [`Emphasis`](/ui/Emphasis) — stress emphasis (italic) for a run of text.
39
+ - [`Code`](/ui/Code) — inline code rather than a highlight.
40
+ - [`ui`](/ui) — the styling system and theming tokens.
@@ -27,6 +27,7 @@ export interface MarkProps extends OptionalChildProps {}
27
27
  /**
28
28
  * Highlighted text — renders a `<mark>` element to call attention to a run of text.
29
29
  *
30
+ * @kind component
30
31
  * @param props The `children` to highlight.
31
32
  * @returns Rendered `<mark>` element.
32
33
  * @example <Mark>search term</Mark>
@@ -22,6 +22,7 @@ export interface StrongProps extends OptionalChildProps {
22
22
  /**
23
23
  * Strong importance — renders a `<strong>` element for text of strong importance (typically bold).
24
24
  *
25
+ * @kind component
25
26
  * @param props The `children` to render with strong importance.
26
27
  * @returns Rendered `<strong>` element.
27
28
  * @example <Strong>Warning</Strong>
@@ -16,6 +16,7 @@ export const STRONG_PROSE_CLASS = getModuleClass(STRONG_CSS, "prose");
16
16
  /**
17
17
  * Strong importance — renders a `<strong>` element for text of strong importance (typically bold).
18
18
  *
19
+ * @kind component
19
20
  * @param props The `children` to render with strong importance.
20
21
  * @returns Rendered `<strong>` element.
21
22
  * @example <Strong>Warning</Strong>
@@ -0,0 +1,34 @@
1
+ # Strong
2
+
3
+ Strong importance — renders a `<strong>` element for text that carries strong importance, seriousness, or urgency (typically shown bold). Prefer it over a raw `<strong>` or `<b>` inside React components so the semantics and class names stay consistent.
4
+
5
+ **Things to know:**
6
+
7
+ - Use `Strong` for importance, [`Emphasis`](/ui/Emphasis) for stress emphasis (italic), and [`Mark`](/ui/Mark) for relevance highlighting — they are not interchangeable.
8
+ - It only sets the font weight; it inherits colour and size from the surrounding text.
9
+ - Inside [`Prose`](/ui/Prose) raw `<strong>` / `<b>` pick up the same styling, so Markdown-rendered bold text matches component ones.
10
+
11
+ ## Usage
12
+
13
+ ### Strong importance in body copy
14
+
15
+ ```tsx
16
+ import { Paragraph, Strong } from "shelving/ui";
17
+
18
+ <Paragraph>
19
+ Press save before leaving. <Strong>Unsaved changes will be lost.</Strong>
20
+ </Paragraph>
21
+ ```
22
+
23
+ ## Styling
24
+
25
+ `Strong` has no own theming hooks — it sets `font-weight: var(--weight-strong)` and inherits everything else from its surroundings.
26
+
27
+ **Global tokens it reads:** `--weight-strong`.
28
+
29
+ ## See also
30
+
31
+ - [`Emphasis`](/ui/Emphasis) — stress emphasis (italic `<em>`) rather than importance.
32
+ - [`Mark`](/ui/Mark) — highlight a run of text by relevance.
33
+ - [`Small`](/ui/Small) — de-emphasised fine print.
34
+ - [`ui`](/ui) — the styling system and theming tokens.
@@ -27,6 +27,7 @@ export interface StrongProps extends OptionalChildProps {}
27
27
  /**
28
28
  * Strong importance — renders a `<strong>` element for text of strong importance (typically bold).
29
29
  *
30
+ * @kind component
30
31
  * @param props The `children` to render with strong importance.
31
32
  * @returns Rendered `<strong>` element.
32
33
  * @example <Strong>Warning</Strong>
@@ -12,6 +12,7 @@ export interface CenteredLayoutProps extends OptionalChildProps {
12
12
  * Layout that centres its content with no header/footer and a narrow max-width.
13
13
  * - Used for e.g. login/register/error/form pages where the content is the only focus.
14
14
  *
15
+ * @kind component
15
16
  * @param children The content to centre.
16
17
  * @param fullWidth Drop the narrow max-width and let content fill the width (defaults to `false`).
17
18
  * @returns The centred layout element.
@@ -7,6 +7,7 @@ import { LAYOUT_CLASS } from "./Layout.js";
7
7
  * Layout that centres its content with no header/footer and a narrow max-width.
8
8
  * - Used for e.g. login/register/error/form pages where the content is the only focus.
9
9
  *
10
+ * @kind component
10
11
  * @param children The content to centre.
11
12
  * @param fullWidth Drop the narrow max-width and let content fill the width (defaults to `false`).
12
13
  * @returns The centred layout element.
@@ -0,0 +1,38 @@
1
+ # CenteredLayout
2
+
3
+ A full-viewport layout that centres its content horizontally inside a narrow max-width column. Good for login, registration, error, and other focused single-purpose pages where the content is the only thing on screen.
4
+
5
+ **Things to know:**
6
+
7
+ - Pass `fullWidth` to drop the max-width constraint while keeping the centred positioning — use it when the content itself needs to fill the width.
8
+ - Like the other full-viewport layouts it owns scroll, padding, and safe-area insets so individual pages don't have to.
9
+
10
+ ## Usage
11
+
12
+ ```tsx
13
+ import { CenteredLayout, Section } from "shelving/ui";
14
+
15
+ function LoginPage() {
16
+ return (
17
+ <CenteredLayout>
18
+ <Section narrow>
19
+ <LoginForm/>
20
+ </Section>
21
+ </CenteredLayout>
22
+ );
23
+ }
24
+ ```
25
+
26
+ Layouts compose naturally as [`Router`](/ui/Router) route values — wrap a group of routes in a shared layout, then route further inside it.
27
+
28
+ ## Styling
29
+
30
+ This layout exposes no own `--centered-layout-*` hooks. The inner column is capped at the global `--width-wide` token (dropped when `fullWidth` is set), and the outer element composes the shared `.layout` behaviour, so it reads the layout hooks `--layout-space`, `--layout-padding`, and `--layout-inset-top` / `-bottom` / `-left` / `-right`.
31
+
32
+ **Global tokens it reads** — `--width-wide`.
33
+
34
+ ## See also
35
+
36
+ - [`SidebarLayout`](/ui/SidebarLayout) — the other full-viewport layout, with a fixed side column
37
+ - [`Page`](/ui/Page) — sits above layouts in the tree
38
+ - [`Router`](/ui/Router) — wrap route groups in a shared layout
@@ -18,6 +18,7 @@ export interface CenteredLayoutProps extends OptionalChildProps {
18
18
  * Layout that centres its content with no header/footer and a narrow max-width.
19
19
  * - Used for e.g. login/register/error/form pages where the content is the only focus.
20
20
  *
21
+ * @kind component
21
22
  * @param children The content to centre.
22
23
  * @param fullWidth Drop the narrow max-width and let content fill the width (defaults to `false`).
23
24
  * @returns The centred layout element.
@@ -19,6 +19,7 @@ export interface SidebarLayoutProps extends OptionalChildProps {
19
19
  * - Inside a `<Navigation>` the drawer closes itself whenever the route changes (e.g. tapping a sidebar link).
20
20
  * - Use the `--sidebar-layout-width`, `--sidebar-layout-bg`, `--sidebar-layout-border`, and `--sidebar-layout-color-border` custom properties to override defaults.
21
21
  *
22
+ * @kind component
22
23
  * @param sidebar The side-column content, rendered inside a `<nav>`.
23
24
  * @param children The main scrollable content.
24
25
  * @param right Render the sidebar on the right rather than the left (defaults to `false`).
@@ -14,6 +14,7 @@ import SIDEBAR_LAYOUT_CSS from "./SidebarLayout.module.css";
14
14
  * - Inside a `<Navigation>` the drawer closes itself whenever the route changes (e.g. tapping a sidebar link).
15
15
  * - Use the `--sidebar-layout-width`, `--sidebar-layout-bg`, `--sidebar-layout-border`, and `--sidebar-layout-color-border` custom properties to override defaults.
16
16
  *
17
+ * @kind component
17
18
  * @param sidebar The side-column content, rendered inside a `<nav>`.
18
19
  * @param children The main scrollable content.
19
20
  * @param right Render the sidebar on the right rather than the left (defaults to `false`).
@@ -0,0 +1,65 @@
1
+ # SidebarLayout
2
+
3
+ A full-viewport layout with a fixed-width side column next to a scrollable main content column. The sidebar renders as a `<nav>` landmark — it almost always holds the primary navigation. On narrow viewports it collapses to an off-canvas drawer toggled by a single burger/close button.
4
+
5
+ **Things to know:**
6
+
7
+ - Pass `right` to place the sidebar on the right rather than the left.
8
+ - The sidebar renders as `<nav>`, so it is a navigation landmark without extra markup — drop a [`Menu`](/ui/Menu) inside it.
9
+ - While the drawer is open an overlay dims the page; clicking the overlay closes it.
10
+ - Inside a [`Navigation`](/ui/Navigation) context the drawer closes itself whenever the route changes (e.g. tapping a sidebar link).
11
+ - The layout owns scroll, padding, and safe-area insets so individual pages don't have to.
12
+
13
+ ## Usage
14
+
15
+ ```tsx
16
+ import { SidebarLayout, Menu, MenuItem, Router } from "shelving/ui";
17
+
18
+ function AppShell() {
19
+ const nav = (
20
+ <Menu>
21
+ <MenuItem href="/dashboard">Dashboard</MenuItem>
22
+ <MenuItem href="/users">Users</MenuItem>
23
+ <MenuItem href="/settings">Settings</MenuItem>
24
+ </Menu>
25
+ );
26
+ return (
27
+ <SidebarLayout sidebar={nav}>
28
+ <Router routes={ROUTES}/>
29
+ </SidebarLayout>
30
+ );
31
+ }
32
+ ```
33
+
34
+ Layouts compose naturally as [`Router`](/ui/Router) route values — wrap a group of routes in a shared layout, then route further inside it.
35
+
36
+ ### Keyboard-aware safe area
37
+
38
+ `useSafeKeyboardArea()` (exported alongside the layouts) tracks the dynamic viewport and writes a `--layout-inset-bottom` custom property reflecting the space hidden behind the on-screen keyboard. This is an iOS Safari workaround until `interactive-widget` viewport support lands.
39
+
40
+ ```tsx
41
+ import { useSafeKeyboardArea } from "shelving/ui";
42
+
43
+ useEffect(useSafeKeyboardArea, []);
44
+ ```
45
+
46
+ ## Styling
47
+
48
+ | Variable | Styles | Default |
49
+ |---|---|---|
50
+ | `--sidebar-layout-width` | Width of the side column (and drawer) | `17.5rem` |
51
+ | `--sidebar-layout-background` | Page background while the layout is mounted | `var(--tint-100)` |
52
+ | `--sidebar-layout-sidebar-background` | Sidebar column fill | `var(--tint-90)` |
53
+ | `--sidebar-layout-content-background` | Main content column fill | `var(--tint-100)` |
54
+ | `--sidebar-layout-border` | Divider between sidebar and content | `var(--stroke-normal) solid var(--tint-80)` |
55
+
56
+ The content column composes the shared `.layout` behaviour, so it also reads the layout hooks `--layout-space`, `--layout-padding`, `--layout-inset-top` / `-bottom` / `-left` / `-right`, and `--layout-body-bg`.
57
+
58
+ **Global tokens it reads** — the tint ladder `--tint-80` / `--tint-90` / `--tint-100`, plus `--space-normal`, `--stroke-normal`, `--duration-normal`, and `--color-shadow`.
59
+
60
+ ## See also
61
+
62
+ - [`CenteredLayout`](/ui/CenteredLayout) — the other full-viewport layout, for focused single-column pages
63
+ - [`Menu`](/ui/Menu) / [`MenuItem`](/ui/MenuItem) — navigation links for the sidebar
64
+ - [`Router`](/ui/Router) — wrap route groups in a shared layout
65
+ - [`Page`](/ui/Page) — sits above layouts in the tree
@@ -27,6 +27,7 @@ export interface SidebarLayoutProps extends OptionalChildProps {
27
27
  * - Inside a `<Navigation>` the drawer closes itself whenever the route changes (e.g. tapping a sidebar link).
28
28
  * - Use the `--sidebar-layout-width`, `--sidebar-layout-bg`, `--sidebar-layout-border`, and `--sidebar-layout-color-border` custom properties to override defaults.
29
29
  *
30
+ * @kind component
30
31
  * @param sidebar The side-column content, rendered inside a `<nav>`.
31
32
  * @param children The main scrollable content.
32
33
  * @param right Render the sidebar on the right rather than the left (defaults to `false`).
package/ui/menu/Menu.d.ts CHANGED
@@ -13,6 +13,7 @@ export interface MenuProps extends OptionalChildProps {
13
13
  * - Renders as a bare `<menu>` element — semantically equivalent to `<ul>` per HTML spec but more meaningful for menu contexts. Place inside a `<nav>` (or use the sidebar-style nav at the layout level) if a navigation landmark is needed.
14
14
  * - Nested `<Menu>` instances (typically inside a `<MenuItem>`) get indented via the `.menu .menu` CSS rule.
15
15
  *
16
+ * @kind component
16
17
  * @param children The `<MenuItem>` entries to list.
17
18
  * @returns The menu element.
18
19
  * @example <Menu><MenuItem href="/home">Home</MenuItem></Menu>
@@ -36,6 +37,7 @@ export interface MenuItemProps extends ClickableProps {
36
37
  * - Reads the current page URL from `<Meta>` and computes `active` / `proud` against its own `href`.
37
38
  * - Splits `children` into `[label, ...after]`: label goes inside the `<a>`; `after` is rendered as siblings below it, only when proud.
38
39
  *
40
+ * @kind component
39
41
  * @param href The link target, used to compute `active`/`proud` against the current URL.
40
42
  * @param children The label (first node) and optional submenu (remaining nodes).
41
43
  * @param props Additional `<Clickable>` props.
package/ui/menu/Menu.js CHANGED
@@ -15,6 +15,7 @@ const MENU_ACTIVE_CLASS = getModuleClass(MENU_CSS, "active");
15
15
  * - Renders as a bare `<menu>` element — semantically equivalent to `<ul>` per HTML spec but more meaningful for menu contexts. Place inside a `<nav>` (or use the sidebar-style nav at the layout level) if a navigation landmark is needed.
16
16
  * - Nested `<Menu>` instances (typically inside a `<MenuItem>`) get indented via the `.menu .menu` CSS rule.
17
17
  *
18
+ * @kind component
18
19
  * @param children The `<MenuItem>` entries to list.
19
20
  * @returns The menu element.
20
21
  * @example <Menu><MenuItem href="/home">Home</MenuItem></Menu>
@@ -28,6 +29,7 @@ export function Menu({ children }) {
28
29
  * - Reads the current page URL from `<Meta>` and computes `active` / `proud` against its own `href`.
29
30
  * - Splits `children` into `[label, ...after]`: label goes inside the `<a>`; `after` is rendered as siblings below it, only when proud.
30
31
  *
32
+ * @kind component
31
33
  * @param href The link target, used to compute `active`/`proud` against the current URL.
32
34
  * @param children The label (first node) and optional submenu (remaining nodes).
33
35
  * @param props Additional `<Clickable>` props.
@@ -0,0 +1,51 @@
1
+ # Menu
2
+
3
+ A `<menu>` list of [`MenuItem`](/ui/MenuItem) children — the container for URL-aware navigation in sidebars, dropdowns, and any other list of links.
4
+
5
+ **Things to know:**
6
+
7
+ - Renders as a bare `<menu>` element (semantically equivalent to `<ul>` but more meaningful for menus). Place it inside a `<nav>` — or a [`SidebarLayout`](/ui/SidebarLayout) sidebar, which is already a `<nav>` landmark — if a navigation landmark is needed.
8
+ - Nesting a `<Menu>` inside a [`MenuItem`](/ui/MenuItem) gets indented automatically via the `.menu .menu` descendant rule.
9
+
10
+ ## Usage
11
+
12
+ ```tsx
13
+ import { Menu, MenuItem } from "shelving/ui";
14
+
15
+ <Menu>
16
+ <MenuItem href="/dashboard">Dashboard</MenuItem>
17
+ <MenuItem href="/users">
18
+ Users
19
+ <Menu>
20
+ <MenuItem href="/users/active">Active</MenuItem>
21
+ <MenuItem href="/users/archived">Archived</MenuItem>
22
+ </Menu>
23
+ </MenuItem>
24
+ <MenuItem href="/settings">Settings</MenuItem>
25
+ </Menu>
26
+ ```
27
+
28
+ ## Styling
29
+
30
+ | Variable | Styles | Default |
31
+ |---|---|---|
32
+ | `--menu-gap` | Vertical gap between items | `var(--space-xxsmall)` |
33
+ | `--menu-font` | Font family | `var(--font-body)` |
34
+ | `--menu-size` | Font size | `var(--size-normal)` |
35
+ | `--menu-leading` | Line height | `var(--leading)` |
36
+ | `--menu-color` | Text colour | `var(--tint-00)` |
37
+ | `--menu-nested-space` | Block margin around a nested submenu | `var(--space-xxsmall)` |
38
+ | `--menu-padding` | Item link padding (also insets the nested border) | `var(--space-xxsmall)` |
39
+ | `--menu-nested-border` | Nested submenu left-border width | `var(--stroke-focus)` |
40
+ | `--menu-nested-color-border` | Nested submenu left-border colour | `var(--tint-50)` |
41
+ | `--menu-nested-indent` | Nested submenu left padding | `var(--space-xsmall)` |
42
+
43
+ Item-state hooks (`--menu-hover-*`, `--menu-proud-*`, `--menu-active-*`, `--menu-radius`, `--menu-focus-border`) are documented on [`MenuItem`](/ui/MenuItem).
44
+
45
+ **Global tokens it reads** — the tint ladder `--tint-00` / `--tint-50`, plus `--space-xxsmall` / `--space-xsmall`, `--font-body`, `--size-normal`, `--leading`, and `--stroke-focus`.
46
+
47
+ ## See also
48
+
49
+ - [`MenuItem`](/ui/MenuItem) — the individual link entries
50
+ - [`SidebarLayout`](/ui/SidebarLayout) — renders a `<nav>` that typically contains a `<Menu>`
51
+ - [`Router`](/ui/Router) — provides the URL context items read
package/ui/menu/Menu.tsx CHANGED
@@ -25,6 +25,7 @@ export interface MenuProps extends OptionalChildProps {}
25
25
  * - Renders as a bare `<menu>` element — semantically equivalent to `<ul>` per HTML spec but more meaningful for menu contexts. Place inside a `<nav>` (or use the sidebar-style nav at the layout level) if a navigation landmark is needed.
26
26
  * - Nested `<Menu>` instances (typically inside a `<MenuItem>`) get indented via the `.menu .menu` CSS rule.
27
27
  *
28
+ * @kind component
28
29
  * @param children The `<MenuItem>` entries to list.
29
30
  * @returns The menu element.
30
31
  * @example <Menu><MenuItem href="/home">Home</MenuItem></Menu>
@@ -52,6 +53,7 @@ export interface MenuItemProps extends ClickableProps {
52
53
  * - Reads the current page URL from `<Meta>` and computes `active` / `proud` against its own `href`.
53
54
  * - Splits `children` into `[label, ...after]`: label goes inside the `<a>`; `after` is rendered as siblings below it, only when proud.
54
55
  *
56
+ * @kind component
55
57
  * @param href The link target, used to compute `active`/`proud` against the current URL.
56
58
  * @param children The label (first node) and optional submenu (remaining nodes).
57
59
  * @param props Additional `<Clickable>` props.