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.
- package/package.json +1 -1
- package/ui/README.md +2 -2
- package/ui/block/Blockquote.module.css +0 -3
- package/ui/block/Card.d.ts +1 -1
- package/ui/block/Card.js +1 -1
- package/ui/block/Card.md +3 -7
- package/ui/block/Card.module.css +0 -3
- package/ui/block/Card.tsx +1 -1
- package/ui/block/Heading.md +0 -1
- package/ui/block/Heading.module.css +0 -3
- package/ui/block/Image.d.ts +3 -3
- package/ui/block/Image.js +4 -4
- package/ui/block/Image.module.css +4 -1
- package/ui/block/Image.tsx +14 -4
- package/ui/block/Label.module.css +0 -3
- package/ui/block/List.md +1 -2
- package/ui/block/List.module.css +0 -3
- package/ui/block/Panel.md +1 -2
- package/ui/block/Panel.module.css +0 -3
- package/ui/block/Paragraph.md +1 -2
- package/ui/block/Paragraph.module.css +0 -3
- package/ui/block/Preformatted.module.css +0 -3
- package/ui/block/Subheading.md +0 -1
- package/ui/block/Subheading.module.css +0 -3
- package/ui/block/Title.md +0 -1
- package/ui/block/Title.module.css +0 -3
- package/ui/block/Video.d.ts +3 -58
- package/ui/block/Video.js +2 -52
- package/ui/block/Video.module.css +1 -51
- package/ui/block/Video.tsx +3 -99
- package/ui/{form → button}/Button.d.ts +6 -2
- package/ui/{form → button}/Button.md +1 -2
- package/ui/{form → button}/Button.module.css +0 -3
- package/ui/{form → button}/Button.tsx +6 -1
- package/ui/button/FullscreenButton.d.ts +31 -0
- package/ui/button/FullscreenButton.js +37 -0
- package/ui/button/FullscreenButton.tsx +58 -0
- package/ui/button/RetryButton.d.ts +29 -0
- package/ui/button/RetryButton.js +27 -0
- package/ui/button/RetryButton.tsx +48 -0
- package/ui/{form → button}/SubmitButton.d.ts +12 -8
- package/ui/{form → button}/SubmitButton.js +4 -4
- package/ui/{form → button}/SubmitButton.tsx +22 -18
- package/ui/button/index.d.ts +5 -0
- package/ui/button/index.js +5 -0
- package/ui/button/index.ts +5 -0
- package/ui/dialog/Dialog.d.ts +1 -1
- package/ui/dialog/Dialog.tsx +1 -1
- package/ui/docs/DocumentationPage.test.tsx +2 -4
- package/ui/docs/DocumentationParams.js +1 -1
- package/ui/docs/DocumentationParams.tsx +1 -1
- package/ui/docs/DocumentationProperties.js +1 -1
- package/ui/docs/DocumentationProperties.tsx +1 -1
- package/ui/docs/DocumentationReferences.js +1 -1
- package/ui/docs/DocumentationReferences.tsx +1 -1
- package/ui/docs/DocumentationReturns.js +1 -1
- package/ui/docs/DocumentationReturns.tsx +1 -1
- package/ui/docs/DocumentationSearchPage.js +2 -2
- package/ui/docs/DocumentationSearchPage.tsx +2 -2
- package/ui/docs/DocumentationThrows.js +1 -1
- package/ui/docs/DocumentationThrows.tsx +1 -1
- package/ui/form/Field.test.tsx +1 -1
- package/ui/form/FormContext.d.ts +1 -1
- package/ui/form/FormContext.js +1 -1
- package/ui/form/FormContext.tsx +1 -1
- package/ui/form/FormFields.d.ts +1 -1
- package/ui/form/FormFields.js +1 -1
- package/ui/form/FormFields.tsx +2 -2
- package/ui/form/FormFooter.js +1 -1
- package/ui/form/FormFooter.tsx +1 -1
- package/ui/form/FormInput.d.ts +1 -1
- package/ui/form/FormInput.js +1 -1
- package/ui/form/FormInput.tsx +2 -2
- package/ui/form/Progress.d.ts +6 -24
- package/ui/form/Progress.js +9 -20
- package/ui/form/Progress.module.css +13 -32
- package/ui/form/Progress.tsx +18 -51
- package/ui/form/index.d.ts +0 -23
- package/ui/form/index.js +0 -23
- package/ui/form/index.ts +0 -23
- package/ui/index.d.ts +2 -0
- package/ui/index.js +2 -0
- package/ui/index.ts +2 -0
- package/ui/inline/Deleted.md +4 -5
- package/ui/inline/Deleted.module.css +1 -3
- package/ui/inline/Inserted.md +4 -5
- package/ui/inline/Inserted.module.css +1 -3
- package/ui/inline/Link.d.ts +1 -1
- package/ui/inline/Link.js +1 -1
- package/ui/inline/Link.md +2 -3
- package/ui/inline/Link.module.css +1 -3
- package/ui/inline/Link.tsx +1 -1
- package/ui/inline/Mark.js +1 -2
- package/ui/inline/Mark.md +5 -5
- package/ui/inline/Mark.module.css +2 -3
- package/ui/inline/Mark.tsx +0 -2
- package/ui/{form → input}/ArrayInput.js +1 -1
- package/ui/{form → input}/ArrayInput.tsx +1 -1
- package/ui/{form → input}/ButtonInput.d.ts +1 -1
- package/ui/{form → input}/ButtonInput.js +1 -1
- package/ui/{form → input}/ButtonInput.tsx +1 -1
- package/ui/{form → input}/ButtonPopover.d.ts +1 -1
- package/ui/{form → input}/ButtonPopover.js +1 -1
- package/ui/{form → input}/ButtonPopover.tsx +1 -1
- package/ui/{form → input}/DictionaryInput.js +1 -1
- package/ui/{form → input}/DictionaryInput.tsx +1 -1
- package/ui/{form → input}/SchemaInput.js +1 -1
- package/ui/{form → input}/SchemaInput.test.tsx +3 -3
- package/ui/{form → input}/SchemaInput.tsx +1 -1
- package/ui/{form → input}/TextInput.d.ts +1 -1
- package/ui/{form → input}/TextInput.js +1 -1
- package/ui/{form → input}/TextInput.tsx +1 -1
- package/ui/input/index.d.ts +20 -0
- package/ui/input/index.js +20 -0
- package/ui/input/index.ts +20 -0
- package/ui/layout/CenteredLayout.d.ts +5 -7
- package/ui/layout/CenteredLayout.js +8 -4
- package/ui/layout/CenteredLayout.md +9 -2
- package/ui/layout/CenteredLayout.module.css +16 -22
- package/ui/layout/CenteredLayout.tsx +18 -12
- package/ui/layout/Layout.d.ts +1 -1
- package/ui/layout/Layout.js +4 -0
- package/ui/layout/Layout.ts +6 -0
- package/ui/layout/SidebarLayout.js +13 -6
- package/ui/layout/SidebarLayout.md +4 -4
- package/ui/layout/SidebarLayout.module.css +6 -9
- package/ui/layout/SidebarLayout.tsx +21 -18
- package/ui/menu/Menu.d.ts +1 -1
- package/ui/menu/Menu.js +1 -1
- package/ui/menu/Menu.tsx +1 -1
- package/ui/misc/Catcher.d.ts +2 -19
- package/ui/misc/Catcher.js +3 -22
- package/ui/misc/Catcher.tsx +4 -40
- package/ui/misc/MetaContext.test.tsx +2 -3
- package/ui/misc/Tag.d.ts +1 -1
- package/ui/misc/Tag.js +1 -1
- package/ui/misc/Tag.md +1 -2
- package/ui/misc/Tag.module.css +0 -3
- package/ui/misc/Tag.tsx +1 -1
- package/ui/notice/Message.module.css +0 -3
- package/ui/notice/Notice.md +1 -2
- package/ui/notice/Notice.module.css +0 -3
- package/ui/router/Router.test.tsx +1 -4
- package/ui/style/TINT_CLASS.md +1 -1
- package/ui/style/Width.d.ts +2 -1
- package/ui/style/Width.module.css +47 -17
- package/ui/style/Width.tsx +22 -1
- package/ui/style/getWidthClass.md +5 -9
- package/ui/table/Table.md +1 -1
- package/ui/tree/TreeButton.d.ts +1 -1
- package/ui/tree/TreeButton.js +1 -1
- package/ui/tree/TreeButton.test.tsx +2 -5
- package/ui/tree/TreeButton.tsx +1 -1
- package/ui/tree/TreeContext.test.tsx +2 -3
- package/ui/tree/TreeMarkup.test.tsx +2 -5
- package/ui/tree/TreeRouter.test.tsx +2 -5
- package/ui/tree/TreeSidebar.js +1 -1
- package/ui/tree/TreeSidebar.tsx +1 -1
- /package/ui/{form → button}/Button.js +0 -0
- /package/ui/{form → button}/Clickable.d.ts +0 -0
- /package/ui/{form → button}/Clickable.js +0 -0
- /package/ui/{form → button}/Clickable.tsx +0 -0
- /package/ui/{form → input}/ArrayInput.d.ts +0 -0
- /package/ui/{form → input}/ArrayRadioInputs.d.ts +0 -0
- /package/ui/{form → input}/ArrayRadioInputs.js +0 -0
- /package/ui/{form → input}/ArrayRadioInputs.tsx +0 -0
- /package/ui/{form → input}/ButtonInputPopover.d.ts +0 -0
- /package/ui/{form → input}/ButtonInputPopover.js +0 -0
- /package/ui/{form → input}/ButtonInputPopover.tsx +0 -0
- /package/ui/{form → input}/CheckboxInput.d.ts +0 -0
- /package/ui/{form → input}/CheckboxInput.js +0 -0
- /package/ui/{form → input}/CheckboxInput.tsx +0 -0
- /package/ui/{form → input}/ChoiceRadioInputs.d.ts +0 -0
- /package/ui/{form → input}/ChoiceRadioInputs.js +0 -0
- /package/ui/{form → input}/ChoiceRadioInputs.tsx +0 -0
- /package/ui/{form → input}/DataInput.d.ts +0 -0
- /package/ui/{form → input}/DataInput.js +0 -0
- /package/ui/{form → input}/DataInput.tsx +0 -0
- /package/ui/{form → input}/DateInput.d.ts +0 -0
- /package/ui/{form → input}/DateInput.js +0 -0
- /package/ui/{form → input}/DateInput.tsx +0 -0
- /package/ui/{form → input}/DictionaryInput.d.ts +0 -0
- /package/ui/{form → input}/FileInput.d.ts +0 -0
- /package/ui/{form → input}/FileInput.js +0 -0
- /package/ui/{form → input}/FileInput.tsx +0 -0
- /package/ui/{form → input}/Input.d.ts +0 -0
- /package/ui/{form → input}/Input.js +0 -0
- /package/ui/{form → input}/Input.module.css +0 -0
- /package/ui/{form → input}/Input.tsx +0 -0
- /package/ui/{form → input}/NumberInput.d.ts +0 -0
- /package/ui/{form → input}/NumberInput.js +0 -0
- /package/ui/{form → input}/NumberInput.tsx +0 -0
- /package/ui/{form → input}/OutputInput.d.ts +0 -0
- /package/ui/{form → input}/OutputInput.js +0 -0
- /package/ui/{form → input}/OutputInput.tsx +0 -0
- /package/ui/{form → input}/Popover.d.ts +0 -0
- /package/ui/{form → input}/Popover.js +0 -0
- /package/ui/{form → input}/Popover.module.css +0 -0
- /package/ui/{form → input}/Popover.tsx +0 -0
- /package/ui/{form → input}/QueryInput.d.ts +0 -0
- /package/ui/{form → input}/QueryInput.js +0 -0
- /package/ui/{form → input}/QueryInput.tsx +0 -0
- /package/ui/{form → input}/RadioInput.d.ts +0 -0
- /package/ui/{form → input}/RadioInput.js +0 -0
- /package/ui/{form → input}/RadioInput.tsx +0 -0
- /package/ui/{form → input}/SchemaInput.d.ts +0 -0
- /package/ui/{form → input}/SchemaInput.md +0 -0
- /package/ui/{form → input}/SelectInput.d.ts +0 -0
- /package/ui/{form → input}/SelectInput.js +0 -0
- /package/ui/{form → input}/SelectInput.tsx +0 -0
package/ui/layout/Layout.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useEffect } from "react";
|
|
1
2
|
/**
|
|
2
3
|
* Track the dynamic viewport height so layout safe-area insets follow the on-screen keyboard.
|
|
3
4
|
*
|
|
@@ -8,6 +9,9 @@
|
|
|
8
9
|
* @see https://shelving.cc/ui/useSafeKeyboardArea
|
|
9
10
|
*/
|
|
10
11
|
export function useSafeKeyboardArea() {
|
|
12
|
+
useEffect(_safeKeyboardArea, []);
|
|
13
|
+
}
|
|
14
|
+
function _safeKeyboardArea() {
|
|
11
15
|
const vv = window.visualViewport;
|
|
12
16
|
if (!vv)
|
|
13
17
|
return;
|
package/ui/layout/Layout.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { useEffect } from "react";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Track the dynamic viewport height so layout safe-area insets follow the on-screen keyboard.
|
|
3
5
|
*
|
|
@@ -8,6 +10,10 @@
|
|
|
8
10
|
* @see https://shelving.cc/ui/useSafeKeyboardArea
|
|
9
11
|
*/
|
|
10
12
|
export function useSafeKeyboardArea() {
|
|
13
|
+
useEffect(_safeKeyboardArea, []);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function _safeKeyboardArea() {
|
|
11
17
|
const vv = window.visualViewport;
|
|
12
18
|
if (!vv) return;
|
|
13
19
|
const onResize = () => {
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Bars3Icon, XMarkIcon } from "@heroicons/react/24/solid";
|
|
3
3
|
import { useEffect, useState } from "react";
|
|
4
|
-
import { Button } from "../
|
|
4
|
+
import { Button } from "../button/Button.js";
|
|
5
5
|
import { requireMetaURL } from "../misc/MetaContext.js";
|
|
6
6
|
import { RouteCache } from "../router/RouteCache.js";
|
|
7
7
|
import { getClass, getModuleClass } from "../util/css.js";
|
|
8
|
-
import
|
|
8
|
+
import LAYOUT_CSS from "./SidebarLayout.module.css";
|
|
9
|
+
const LAYOUT_SIDEBAR_CLASS = getModuleClass(LAYOUT_CSS, "sidebar");
|
|
10
|
+
const LAYOUT_CONTENT_CLASS = getModuleClass(LAYOUT_CSS, "content");
|
|
11
|
+
const LAYOUT_TOGGLE_CLASS = getModuleClass(LAYOUT_CSS, "toggle");
|
|
12
|
+
const LAYOUT_OVERLAY_CLASS = getModuleClass(LAYOUT_CSS, "overlay");
|
|
13
|
+
const LAYOUT_MAIN_CLASS = getModuleClass(LAYOUT_CSS, "main");
|
|
14
|
+
const LAYOUT_OPEN_CLASS = getModuleClass(LAYOUT_CSS, "open");
|
|
9
15
|
/**
|
|
10
16
|
* Layout with a fixed-width side column (typically navigation) next to a scrollable main content column.
|
|
11
17
|
* - The sidebar is rendered as `<nav>` — it almost always contains the page's primary navigation.
|
|
@@ -25,12 +31,13 @@ export function SidebarLayout({ sidebar, children, right = false }) {
|
|
|
25
31
|
if (path)
|
|
26
32
|
setOpen(false);
|
|
27
33
|
}, [path]);
|
|
28
|
-
const sidebarEl = (_jsx("nav", { className: getClass(
|
|
34
|
+
const sidebarEl = (_jsx("nav", { className: getClass(LAYOUT_SIDEBAR_CLASS, //
|
|
35
|
+
open && LAYOUT_OPEN_CLASS), children: sidebar }, "sidebar"));
|
|
29
36
|
// Wrap the scrolling content column in `<RouteCache>` so recently-visited pages stay mounted but hidden
|
|
30
37
|
// — keeping the scroll position of this `.content` container (and all page state) intact across
|
|
31
38
|
// back/forward navigation. The sidebar and drawer state stay outside the cache, so they are neither
|
|
32
39
|
// duplicated nor remounted as the URL changes.
|
|
33
|
-
const contentEl = (_jsx(RouteCache, { children: _jsxs("div", { className:
|
|
34
|
-
const overlayEl = open && (_jsx("button", { type: "button", className:
|
|
35
|
-
return
|
|
40
|
+
const contentEl = (_jsx(RouteCache, { children: _jsxs("div", { className: LAYOUT_CONTENT_CLASS, children: [_jsx("div", { className: LAYOUT_TOGGLE_CLASS, children: _jsx(Button, { title: open ? "Close menu" : "Show menu", onClick: () => setOpen(o => !o), children: open ? _jsx(XMarkIcon, {}) : _jsx(Bars3Icon, {}) }) }), children] }) }, "content"));
|
|
41
|
+
const overlayEl = open && (_jsx("button", { type: "button", className: LAYOUT_OVERLAY_CLASS, "aria-label": "Close menu", onClick: () => setOpen(false) }, "overlay"));
|
|
42
|
+
return _jsx("main", { className: LAYOUT_MAIN_CLASS, children: right ? [contentEl, sidebarEl, overlayEl] : [sidebarEl, contentEl, overlayEl] });
|
|
36
43
|
}
|
|
@@ -48,11 +48,11 @@ useEffect(useSafeKeyboardArea, []);
|
|
|
48
48
|
| Variable | Styles | Default |
|
|
49
49
|
|---|---|---|
|
|
50
50
|
| `--sidebar-layout-width` | Width of the side column (and drawer) | `17.5rem` |
|
|
51
|
-
| `--sidebar-layout-background` | Page background while the layout is mounted | `
|
|
52
|
-
| `--sidebar-layout-sidebar-background` | Sidebar column fill |
|
|
53
|
-
| `--sidebar-layout-content-background` | Main content column fill |
|
|
51
|
+
| `--sidebar-layout-background` | Page background while the layout is mounted | Unset — the `body` default from `Typography.module.css` shows |
|
|
52
|
+
| `--sidebar-layout-sidebar-background` | Sidebar column fill | Unset — the page background shows |
|
|
53
|
+
| `--sidebar-layout-content-background` | Main content column fill | Unset — the page background shows |
|
|
54
54
|
| `--sidebar-layout-border` | Divider between sidebar and content | `var(--stroke-normal) solid var(--tint-80)` |
|
|
55
55
|
|
|
56
56
|
The sidebar and content columns own their own scroll behaviour directly (this layout no longer composes a shared `.layout` class). `useSafeKeyboardArea()` still writes `--layout-inset-bottom` for layouts that pad to the safe area.
|
|
57
57
|
|
|
58
|
-
**Global tokens it reads** —
|
|
58
|
+
**Global tokens it reads** — `--tint-80`, plus `--space-normal`, `--stroke-normal`, `--duration-normal`, and `--color-shadow`.
|
|
@@ -50,7 +50,8 @@
|
|
|
50
50
|
inset: 0;
|
|
51
51
|
|
|
52
52
|
/* Style */
|
|
53
|
-
|
|
53
|
+
/* Deliberately no fallback: when the hook is unset this declaration fails and the body default from Typography.module.css shows. */
|
|
54
|
+
background: var(--sidebar-layout-background);
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
.main {
|
|
@@ -74,7 +75,8 @@
|
|
|
74
75
|
padding: var(--space-normal);
|
|
75
76
|
|
|
76
77
|
/* Style */
|
|
77
|
-
|
|
78
|
+
/* Deliberately no fallback: when the hook is unset this declaration fails and the page background shows. */
|
|
79
|
+
background: var(--sidebar-layout-sidebar-background);
|
|
78
80
|
}
|
|
79
81
|
|
|
80
82
|
.content {
|
|
@@ -91,13 +93,8 @@
|
|
|
91
93
|
scroll-behavior: smooth;
|
|
92
94
|
|
|
93
95
|
/* Style */
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
.contentInner {
|
|
98
|
-
width: 100%;
|
|
99
|
-
padding: 0;
|
|
100
|
-
margin: 0 auto;
|
|
96
|
+
/* Deliberately no fallback: when the hook is unset this declaration fails and the page background shows. */
|
|
97
|
+
background: var(--sidebar-layout-content-background);
|
|
101
98
|
}
|
|
102
99
|
|
|
103
100
|
/* Wrapper for the menu toggle button — hidden on wide viewports, shown on narrow ones (see media query). */
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { Bars3Icon, XMarkIcon } from "@heroicons/react/24/solid";
|
|
2
2
|
import { type ReactElement, type ReactNode, useEffect, useState } from "react";
|
|
3
|
-
import { Button } from "../
|
|
3
|
+
import { Button } from "../button/Button.js";
|
|
4
4
|
import { requireMetaURL } from "../misc/MetaContext.js";
|
|
5
5
|
import { RouteCache } from "../router/RouteCache.js";
|
|
6
6
|
import { getClass, getModuleClass } from "../util/css.js";
|
|
7
7
|
import type { OptionalChildProps } from "../util/props.js";
|
|
8
|
-
import
|
|
8
|
+
import LAYOUT_CSS from "./SidebarLayout.module.css";
|
|
9
|
+
|
|
10
|
+
const LAYOUT_SIDEBAR_CLASS = getModuleClass(LAYOUT_CSS, "sidebar");
|
|
11
|
+
const LAYOUT_CONTENT_CLASS = getModuleClass(LAYOUT_CSS, "content");
|
|
12
|
+
const LAYOUT_TOGGLE_CLASS = getModuleClass(LAYOUT_CSS, "toggle");
|
|
13
|
+
const LAYOUT_OVERLAY_CLASS = getModuleClass(LAYOUT_CSS, "overlay");
|
|
14
|
+
const LAYOUT_MAIN_CLASS = getModuleClass(LAYOUT_CSS, "main");
|
|
15
|
+
const LAYOUT_OPEN_CLASS = getModuleClass(LAYOUT_CSS, "open");
|
|
9
16
|
|
|
10
17
|
/**
|
|
11
18
|
* Props for `<SidebarLayout>` — the `sidebar` column content, main `children`, and a `right` placement flag.
|
|
@@ -42,39 +49,35 @@ export function SidebarLayout({ sidebar, children, right = false }: SidebarLayou
|
|
|
42
49
|
const sidebarEl = (
|
|
43
50
|
<nav
|
|
44
51
|
key="sidebar"
|
|
45
|
-
className={getClass(
|
|
52
|
+
className={getClass(
|
|
53
|
+
LAYOUT_SIDEBAR_CLASS, //
|
|
54
|
+
open && LAYOUT_OPEN_CLASS,
|
|
55
|
+
)}
|
|
46
56
|
>
|
|
47
57
|
{sidebar}
|
|
48
58
|
</nav>
|
|
49
59
|
);
|
|
60
|
+
|
|
50
61
|
// Wrap the scrolling content column in `<RouteCache>` so recently-visited pages stay mounted but hidden
|
|
51
62
|
// — keeping the scroll position of this `.content` container (and all page state) intact across
|
|
52
63
|
// back/forward navigation. The sidebar and drawer state stay outside the cache, so they are neither
|
|
53
64
|
// duplicated nor remounted as the URL changes.
|
|
54
65
|
const contentEl = (
|
|
55
66
|
<RouteCache key="content">
|
|
56
|
-
<div className={
|
|
57
|
-
<div className={
|
|
67
|
+
<div className={LAYOUT_CONTENT_CLASS}>
|
|
68
|
+
<div className={LAYOUT_TOGGLE_CLASS}>
|
|
58
69
|
<Button title={open ? "Close menu" : "Show menu"} onClick={() => setOpen(o => !o)}>
|
|
59
70
|
{open ? <XMarkIcon /> : <Bars3Icon />}
|
|
60
71
|
</Button>
|
|
61
72
|
</div>
|
|
62
|
-
|
|
73
|
+
{children}
|
|
63
74
|
</div>
|
|
64
75
|
</RouteCache>
|
|
65
76
|
);
|
|
77
|
+
|
|
66
78
|
const overlayEl = open && (
|
|
67
|
-
<button
|
|
68
|
-
key="overlay"
|
|
69
|
-
type="button"
|
|
70
|
-
className={getModuleClass(SIDEBAR_LAYOUT_CSS, "overlay")}
|
|
71
|
-
aria-label="Close menu"
|
|
72
|
-
onClick={() => setOpen(false)}
|
|
73
|
-
/>
|
|
74
|
-
);
|
|
75
|
-
return (
|
|
76
|
-
<main className={getModuleClass(SIDEBAR_LAYOUT_CSS, "main")}>
|
|
77
|
-
{right ? [contentEl, sidebarEl, overlayEl] : [sidebarEl, contentEl, overlayEl]}
|
|
78
|
-
</main>
|
|
79
|
+
<button key="overlay" type="button" className={LAYOUT_OVERLAY_CLASS} aria-label="Close menu" onClick={() => setOpen(false)} />
|
|
79
80
|
);
|
|
81
|
+
|
|
82
|
+
return <main className={LAYOUT_MAIN_CLASS}>{right ? [contentEl, sidebarEl, overlayEl] : [sidebarEl, contentEl, overlayEl]}</main>;
|
|
80
83
|
}
|
package/ui/menu/Menu.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
|
-
import { type ClickableProps } from "../
|
|
2
|
+
import { type ClickableProps } from "../button/Clickable.js";
|
|
3
3
|
import { type BlockVariants } from "../style/Block.js";
|
|
4
4
|
import type { OptionalChildProps } from "../util/props.js";
|
|
5
5
|
/**
|
package/ui/menu/Menu.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { isArray } from "../../util/array.js";
|
|
3
3
|
import { getLink, isURLActive, isURLProud } from "../../util/index.js";
|
|
4
|
-
import { Clickable } from "../
|
|
4
|
+
import { Clickable } from "../button/Clickable.js";
|
|
5
5
|
import { requireMeta } from "../misc/MetaContext.js";
|
|
6
6
|
import { getBlockClass } from "../style/Block.js";
|
|
7
7
|
import { getClass, getModuleClass } from "../util/css.js";
|
package/ui/menu/Menu.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
2
|
import { isArray } from "../../util/array.js";
|
|
3
3
|
import { getLink, isURLActive, isURLProud } from "../../util/index.js";
|
|
4
|
-
import { Clickable, type ClickableProps } from "../
|
|
4
|
+
import { Clickable, type ClickableProps } from "../button/Clickable.js";
|
|
5
5
|
import { requireMeta } from "../misc/MetaContext.js";
|
|
6
6
|
import { type BlockVariants, getBlockClass } from "../style/Block.js";
|
|
7
7
|
import { getClass, getModuleClass } from "../util/css.js";
|
package/ui/misc/Catcher.d.ts
CHANGED
|
@@ -1,25 +1,8 @@
|
|
|
1
1
|
import { Component, type ReactElement, type ReactNode } from "react";
|
|
2
2
|
import type { Callback } from "../../util/function.js";
|
|
3
|
-
import {
|
|
4
|
-
import type { ChildProps, OptionalChildProps } from "../util/props.js";
|
|
5
|
-
/**
|
|
6
|
-
* Props for `<RetryButton>` — `<Button>` variants plus optional `children` to override the default "Retry" label.
|
|
7
|
-
*
|
|
8
|
-
* @see https://shelving.cc/ui/RetryButtonProps
|
|
9
|
-
*/
|
|
10
|
-
export interface RetryButtonProps extends ButtonVariants, OptionalChildProps {
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Button that retries the nearest `<Catcher>` error boundary when clicked.
|
|
14
|
-
*
|
|
15
|
-
* - Reads the retry callback from `<Catcher>`'s private context, so it renders `null` when there is no boundary above it to retry.
|
|
16
|
-
* - Defaults to an "Retry" label with a refresh icon; pass `children` to override.
|
|
17
|
-
*
|
|
18
|
-
* @kind component
|
|
19
|
-
* @see https://shelving.cc/ui/RetryButton
|
|
20
|
-
*/
|
|
21
|
-
export declare function RetryButton({ children, ...props }: RetryButtonProps): ReactElement | null;
|
|
3
|
+
import type { ChildProps } from "../util/props.js";
|
|
22
4
|
/**
|
|
5
|
+
import { RetryButton, RetryContext } from "../button/RetryButton.js";
|
|
23
6
|
* Props for a component that renders a caught error `reason`.
|
|
24
7
|
*
|
|
25
8
|
* @see https://shelving.cc/ui/ErrorProps
|
package/ui/misc/Catcher.js
CHANGED
|
@@ -1,30 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { Component, createContext, use } from "react";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Component } from "react";
|
|
4
3
|
import { getMessage } from "../../util/error.js";
|
|
5
4
|
import { Paragraph } from "../block/Paragraph.js";
|
|
6
|
-
import {
|
|
5
|
+
import { RetryButton, RetryContext } from "../button/RetryButton.js";
|
|
7
6
|
import { CenteredLayout } from "../layout/CenteredLayout.js";
|
|
8
7
|
import { Notice } from "../notice/Notice.js";
|
|
9
8
|
import { Page } from "../page/Page.js";
|
|
10
|
-
const RetryContext = createContext(undefined);
|
|
11
|
-
RetryContext.displayName = "RetryContext";
|
|
12
|
-
const RETRY_CHILDREN = (_jsxs(_Fragment, { children: [_jsx(ArrowPathIcon, {}), "Retry"] }));
|
|
13
|
-
/**
|
|
14
|
-
* Button that retries the nearest `<Catcher>` error boundary when clicked.
|
|
15
|
-
*
|
|
16
|
-
* - Reads the retry callback from `<Catcher>`'s private context, so it renders `null` when there is no boundary above it to retry.
|
|
17
|
-
* - Defaults to an "Retry" label with a refresh icon; pass `children` to override.
|
|
18
|
-
*
|
|
19
|
-
* @kind component
|
|
20
|
-
* @see https://shelving.cc/ui/RetryButton
|
|
21
|
-
*/
|
|
22
|
-
export function RetryButton({ children = RETRY_CHILDREN, ...props }) {
|
|
23
|
-
const retry = use(RetryContext);
|
|
24
|
-
if (!retry)
|
|
25
|
-
return null;
|
|
26
|
-
return (_jsx(Button, { onClick: retry, ...props, children: children }));
|
|
27
|
-
}
|
|
28
9
|
/**
|
|
29
10
|
* React error boundary that renders a fallback component when any descendant throws.
|
|
30
11
|
*
|
package/ui/misc/Catcher.tsx
CHANGED
|
@@ -1,51 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Component, createContext, type ReactElement, type ReactNode, use } from "react";
|
|
1
|
+
import { Component, type ReactElement, type ReactNode } from "react";
|
|
3
2
|
import { getMessage } from "../../util/error.js";
|
|
4
3
|
import type { Callback } from "../../util/function.js";
|
|
5
4
|
import { Paragraph } from "../block/Paragraph.js";
|
|
6
|
-
import {
|
|
5
|
+
import { RetryButton, RetryContext } from "../button/RetryButton.js";
|
|
7
6
|
import { CenteredLayout } from "../layout/CenteredLayout.js";
|
|
8
7
|
import { Notice } from "../notice/Notice.js";
|
|
9
8
|
import { Page } from "../page/Page.js";
|
|
10
|
-
import type { ChildProps
|
|
11
|
-
|
|
12
|
-
const RetryContext = createContext<Callback | undefined>(undefined);
|
|
13
|
-
RetryContext.displayName = "RetryContext";
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Props for `<RetryButton>` — `<Button>` variants plus optional `children` to override the default "Retry" label.
|
|
17
|
-
*
|
|
18
|
-
* @see https://shelving.cc/ui/RetryButtonProps
|
|
19
|
-
*/
|
|
20
|
-
export interface RetryButtonProps extends ButtonVariants, OptionalChildProps {}
|
|
21
|
-
|
|
22
|
-
const RETRY_CHILDREN = (
|
|
23
|
-
<>
|
|
24
|
-
<ArrowPathIcon />
|
|
25
|
-
Retry
|
|
26
|
-
</>
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Button that retries the nearest `<Catcher>` error boundary when clicked.
|
|
31
|
-
*
|
|
32
|
-
* - Reads the retry callback from `<Catcher>`'s private context, so it renders `null` when there is no boundary above it to retry.
|
|
33
|
-
* - Defaults to an "Retry" label with a refresh icon; pass `children` to override.
|
|
34
|
-
*
|
|
35
|
-
* @kind component
|
|
36
|
-
* @see https://shelving.cc/ui/RetryButton
|
|
37
|
-
*/
|
|
38
|
-
export function RetryButton({ children = RETRY_CHILDREN, ...props }: RetryButtonProps): ReactElement | null {
|
|
39
|
-
const retry = use(RetryContext);
|
|
40
|
-
if (!retry) return null;
|
|
41
|
-
return (
|
|
42
|
-
<Button onClick={retry} {...props}>
|
|
43
|
-
{children}
|
|
44
|
-
</Button>
|
|
45
|
-
);
|
|
46
|
-
}
|
|
9
|
+
import type { ChildProps } from "../util/props.js";
|
|
47
10
|
|
|
48
11
|
/**
|
|
12
|
+
import { RetryButton, RetryContext } from "../button/RetryButton.js";
|
|
49
13
|
* Props for a component that renders a caught error `reason`.
|
|
50
14
|
*
|
|
51
15
|
* @see https://shelving.cc/ui/ErrorProps
|
|
@@ -1,9 +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 { RequiredError } from "
|
|
5
|
-
import { createMeta } from "
|
|
6
|
-
import { MetaContext, requireMetaURL } from "./MetaContext.js";
|
|
4
|
+
import { RequiredError } from "shelving/error";
|
|
5
|
+
import { createMeta, MetaContext, requireMetaURL } from "shelving/ui";
|
|
7
6
|
|
|
8
7
|
/** Render `requireMetaURL().path` from inside a component so its `use(MetaContext)` call is valid. */
|
|
9
8
|
function Probe(): ReactNode {
|
package/ui/misc/Tag.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ReactElement } from "react";
|
|
2
|
-
import { type ClickableProps } from "../
|
|
2
|
+
import { type ClickableProps } from "../button/Clickable.js";
|
|
3
3
|
import { type StatusVariants } from "../style/Status.js";
|
|
4
4
|
import { type TypographyVariants } from "../style/Typography.js";
|
|
5
5
|
/**
|
package/ui/misc/Tag.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { Clickable } from "../
|
|
2
|
+
import { Clickable } from "../button/Clickable.js";
|
|
3
3
|
import { getStatusClass } from "../style/Status.js";
|
|
4
4
|
import { getTypographyClass } from "../style/Typography.js";
|
|
5
5
|
import { getClass, getModuleClass } from "../util/css.js";
|
package/ui/misc/Tag.md
CHANGED
|
@@ -20,11 +20,10 @@ import { Tag } from "shelving/ui";
|
|
|
20
20
|
|
|
21
21
|
## Styling
|
|
22
22
|
|
|
23
|
-
`Tag` paints from the [tint ladder](/ui/TINT_CLASS); override these hooks at `:root` (or any ancestor scope) to retheme.
|
|
23
|
+
`Tag` paints from the [tint ladder](/ui/TINT_CLASS); override these hooks at `:root` (or any ancestor scope) to retheme. Apply `color=` / `status=` (on the tag or an ancestor scope) to recolour the whole tag at once.
|
|
24
24
|
|
|
25
25
|
| Variable | Styles | Default |
|
|
26
26
|
|---|---|---|
|
|
27
|
-
| `--tag-tint` | Tint anchor for the tag scope | `inherit` (flows from `color=` / `status=` / parent) |
|
|
28
27
|
| `--tag-background` | Surface fill | `var(--tint-50)` |
|
|
29
28
|
| `--tag-hover-background` | Surface fill when an interactive tag is hovered | `var(--tint-55)` |
|
|
30
29
|
| `--tag-color` | Text colour | `var(--tint-100)` |
|
package/ui/misc/Tag.module.css
CHANGED
package/ui/misc/Tag.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ReactElement } from "react";
|
|
2
|
-
import { Clickable, type ClickableProps } from "../
|
|
2
|
+
import { Clickable, type ClickableProps } from "../button/Clickable.js";
|
|
3
3
|
import { getStatusClass, type StatusVariants } from "../style/Status.js";
|
|
4
4
|
import { getTypographyClass, type TypographyVariants } from "../style/Typography.js";
|
|
5
5
|
import { getClass, getModuleClass } from "../util/css.js";
|
package/ui/notice/Notice.md
CHANGED
|
@@ -28,11 +28,10 @@ import { LOADING_NOTICE } from "shelving/ui";
|
|
|
28
28
|
|
|
29
29
|
## Styling
|
|
30
30
|
|
|
31
|
-
`Notice` paints from the [tint ladder](/ui/TINT_CLASS); override these hooks at `:root` (or any ancestor scope) to retheme.
|
|
31
|
+
`Notice` paints from the [tint ladder](/ui/TINT_CLASS); override these hooks at `:root` (or any ancestor scope) to retheme. Its `status` (or a `color=` / `status=` on an ancestor scope) sets the tint that the surface, border, and text all derive from; reach for a per-property hook for a single change.
|
|
32
32
|
|
|
33
33
|
| Variable | Styles | Default |
|
|
34
34
|
|---|---|---|
|
|
35
|
-
| `--notice-tint` | Tint anchor for the notice scope | `inherit` (flows from `color=` / `status=` / parent) |
|
|
36
35
|
| `--notice-background` | Surface fill | `var(--tint-90)` |
|
|
37
36
|
| `--notice-color` | Text colour | `var(--tint-50)` |
|
|
38
37
|
| `--notice-border` | Border shorthand | `var(--notice-stroke) solid var(--tint-80)` |
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
2
|
import { renderToStaticMarkup } from "react-dom/server";
|
|
3
|
-
import { MetaContext } from "
|
|
4
|
-
import { createMeta } from "../util/meta.js";
|
|
5
|
-
import { Router } from "./Router.js";
|
|
6
|
-
import type { RouteProps } from "./Routes.js";
|
|
3
|
+
import { createMeta, MetaContext, type RouteProps, Router } from "shelving/ui";
|
|
7
4
|
|
|
8
5
|
const ROUTES = {
|
|
9
6
|
"/": () => <main>Home</main>,
|
package/ui/style/TINT_CLASS.md
CHANGED
|
@@ -42,7 +42,7 @@ Pairings follow contrast: long text reads at `00`-on-`90` or `00`-on-`100`; shor
|
|
|
42
42
|
A theme is a CSS file of custom-property overrides at `:root`, imported after the base styles. Work from broadest to narrowest:
|
|
43
43
|
|
|
44
44
|
1. **Move a palette colour.** Overriding `--color-gray` moves the default anchor, retinting every neutral ladder in the app — the broadest possible change. Overriding `--color-red`, `--color-primary`, etc. re-aims every variant and status that maps to it.
|
|
45
|
-
2. **Retint
|
|
45
|
+
2. **Retint a region.** Apply `color=` / `status=` to a container — `<Card color="purple">`, or a `<Panel color="purple">` wrapping a whole section — and everything inside re-tints, with text, border, surface, and hover shades all derived for free. Components don't expose a per-component `--x-tint` hook; the variant moves the anchor, not a bespoke variable.
|
|
46
46
|
3. **Override one property.** Per-property hooks are the scalpel: `--button-radius: 999px`, `--card-border: none`, `--tag-case: none`.
|
|
47
47
|
|
|
48
48
|
**Don't override individual ladder steps (`--tint-90`, etc.) at `:root`.** The ladder is *recomputed* from the anchor inside every `TINT_CLASS` scope — which includes every component that accepts `color=` or `status=` — so a step override at `:root` only reaches untinted regions and produces inconsistent surfaces. Move the anchor (option 1 or 2) instead, and the steps follow.
|
package/ui/style/Width.d.ts
CHANGED
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
* - `narrow` / `normal` / `wide` — fixed widths from the `--width-*` tokens (capped at 100%).
|
|
4
4
|
* - `full` — take the full available width.
|
|
5
5
|
* - `fit` — shrink to fit the content's intrinsic width (`fit-content`).
|
|
6
|
+
* - `1x`–`32x` — fixed multiples of `--space-normal` (1x–8x at 1x intervals, then 10x/12x, then 16x–32x at 4x intervals).
|
|
6
7
|
*
|
|
7
8
|
* @see https://shelving.cc/ui/WidthVariant
|
|
8
9
|
*/
|
|
9
|
-
export type WidthVariant = "
|
|
10
|
+
export type WidthVariant = "narrow" | "normal" | "wide" | "full" | "fit" | "1x" | "2x" | "3x" | "4x" | "5x" | "6x" | "7x" | "8x" | "10x" | "12x" | "16x" | "20x" | "24x" | "28x" | "32x";
|
|
10
11
|
/**
|
|
11
12
|
* Variant props that set (or unconstrain) a component's width, e.g. `width="narrow"` or `width="12x"`.
|
|
12
13
|
*
|
|
@@ -4,14 +4,9 @@
|
|
|
4
4
|
@layer defaults {
|
|
5
5
|
:root {
|
|
6
6
|
/* Semantic widths */
|
|
7
|
-
--width-xxnarrow: 16rem;
|
|
8
|
-
--width-xnarrow: 24rem;
|
|
9
7
|
--width-narrow: 36rem;
|
|
10
8
|
--width-normal: 48rem;
|
|
11
9
|
--width-wide: 80rem;
|
|
12
|
-
--width-xwide: 96rem;
|
|
13
|
-
--width-xxwide: 112rem;
|
|
14
|
-
--width-xxxwide: 128rem;
|
|
15
10
|
}
|
|
16
11
|
|
|
17
12
|
/* Frame shared by every width value (weak default — a component's own margin can still beat the centering). */
|
|
@@ -28,12 +23,6 @@
|
|
|
28
23
|
}
|
|
29
24
|
|
|
30
25
|
/* Semantic widths. */
|
|
31
|
-
.width-xxnarrow {
|
|
32
|
-
--width: var(--width-xxnarrow);
|
|
33
|
-
}
|
|
34
|
-
.width-xnarrow {
|
|
35
|
-
--width: var(--width-xnarrow);
|
|
36
|
-
}
|
|
37
26
|
.width-narrow {
|
|
38
27
|
--width: var(--width-narrow);
|
|
39
28
|
}
|
|
@@ -43,12 +32,6 @@
|
|
|
43
32
|
.width-wide {
|
|
44
33
|
--width: var(--width-wide);
|
|
45
34
|
}
|
|
46
|
-
.width-xwide {
|
|
47
|
-
--width: var(--width-xwide);
|
|
48
|
-
}
|
|
49
|
-
.width-xxwide {
|
|
50
|
-
--width: var(--width-xxwide);
|
|
51
|
-
}
|
|
52
35
|
.width-full {
|
|
53
36
|
--width: 100%;
|
|
54
37
|
}
|
|
@@ -56,6 +39,53 @@
|
|
|
56
39
|
--width: fit-content;
|
|
57
40
|
}
|
|
58
41
|
|
|
42
|
+
/* Numeric widths — multiples of `--space-normal` (no `--width-*` tokens; calculated directly). */
|
|
43
|
+
.width-1x {
|
|
44
|
+
--width: calc(1 * var(--space-normal));
|
|
45
|
+
}
|
|
46
|
+
.width-2x {
|
|
47
|
+
--width: calc(2 * var(--space-normal));
|
|
48
|
+
}
|
|
49
|
+
.width-3x {
|
|
50
|
+
--width: calc(3 * var(--space-normal));
|
|
51
|
+
}
|
|
52
|
+
.width-4x {
|
|
53
|
+
--width: calc(4 * var(--space-normal));
|
|
54
|
+
}
|
|
55
|
+
.width-5x {
|
|
56
|
+
--width: calc(5 * var(--space-normal));
|
|
57
|
+
}
|
|
58
|
+
.width-6x {
|
|
59
|
+
--width: calc(6 * var(--space-normal));
|
|
60
|
+
}
|
|
61
|
+
.width-7x {
|
|
62
|
+
--width: calc(7 * var(--space-normal));
|
|
63
|
+
}
|
|
64
|
+
.width-8x {
|
|
65
|
+
--width: calc(8 * var(--space-normal));
|
|
66
|
+
}
|
|
67
|
+
.width-10x {
|
|
68
|
+
--width: calc(10 * var(--space-normal));
|
|
69
|
+
}
|
|
70
|
+
.width-12x {
|
|
71
|
+
--width: calc(12 * var(--space-normal));
|
|
72
|
+
}
|
|
73
|
+
.width-16x {
|
|
74
|
+
--width: calc(16 * var(--space-normal));
|
|
75
|
+
}
|
|
76
|
+
.width-20x {
|
|
77
|
+
--width: calc(20 * var(--space-normal));
|
|
78
|
+
}
|
|
79
|
+
.width-24x {
|
|
80
|
+
--width: calc(24 * var(--space-normal));
|
|
81
|
+
}
|
|
82
|
+
.width-28x {
|
|
83
|
+
--width: calc(28 * var(--space-normal));
|
|
84
|
+
}
|
|
85
|
+
.width-32x {
|
|
86
|
+
--width: calc(32 * var(--space-normal));
|
|
87
|
+
}
|
|
88
|
+
|
|
59
89
|
/* Grow modifier — turn the chosen width into a floor and expand to fill (flex items + table columns). */
|
|
60
90
|
.grow {
|
|
61
91
|
flex-grow: 1;
|
package/ui/style/Width.tsx
CHANGED
|
@@ -6,10 +6,31 @@ import WIDTH_CSS from "./Width.module.css";
|
|
|
6
6
|
* - `narrow` / `normal` / `wide` — fixed widths from the `--width-*` tokens (capped at 100%).
|
|
7
7
|
* - `full` — take the full available width.
|
|
8
8
|
* - `fit` — shrink to fit the content's intrinsic width (`fit-content`).
|
|
9
|
+
* - `1x`–`32x` — fixed multiples of `--space-normal` (1x–8x at 1x intervals, then 10x/12x, then 16x–32x at 4x intervals).
|
|
9
10
|
*
|
|
10
11
|
* @see https://shelving.cc/ui/WidthVariant
|
|
11
12
|
*/
|
|
12
|
-
export type WidthVariant =
|
|
13
|
+
export type WidthVariant =
|
|
14
|
+
| "narrow"
|
|
15
|
+
| "normal"
|
|
16
|
+
| "wide"
|
|
17
|
+
| "full"
|
|
18
|
+
| "fit"
|
|
19
|
+
| "1x"
|
|
20
|
+
| "2x"
|
|
21
|
+
| "3x"
|
|
22
|
+
| "4x"
|
|
23
|
+
| "5x"
|
|
24
|
+
| "6x"
|
|
25
|
+
| "7x"
|
|
26
|
+
| "8x"
|
|
27
|
+
| "10x"
|
|
28
|
+
| "12x"
|
|
29
|
+
| "16x"
|
|
30
|
+
| "20x"
|
|
31
|
+
| "24x"
|
|
32
|
+
| "28x"
|
|
33
|
+
| "32x";
|
|
13
34
|
|
|
14
35
|
/**
|
|
15
36
|
* Variant props that set (or unconstrain) a component's width, e.g. `width="narrow"` or `width="12x"`.
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
# getWidthClass
|
|
2
2
|
|
|
3
|
-
The `width` variant prop sets a component's inline-size — `<Card width="narrow">`, `<Block width="wide">`, `<Cell width="
|
|
3
|
+
The `width` variant prop sets a component's inline-size — `<Card width="narrow">`, `<Block width="wide">`, `<Cell width="narrow">`. It's an **override** for one-off layout; for an app-wide change, retune the width variables below in a theme file. `<Section>` already defaults to the `--width-normal` width, so most pages never set `width` at all.
|
|
4
4
|
|
|
5
5
|
`getWidthClass({ width, grow })` maps the props to a width class. Every value is capped at 100% of the container.
|
|
6
6
|
|
|
7
7
|
**Values:**
|
|
8
8
|
|
|
9
|
-
- `
|
|
9
|
+
- `narrow` / `normal` / `wide` — fixed widths from the variables below.
|
|
10
10
|
- `full` — the full available width.
|
|
11
11
|
- `fit` — shrink to the content's intrinsic width (`fit-content`).
|
|
12
|
+
- `1x` / `2x` / `3x` / `4x` / `5x` / `6x` / `7x` / `8x` / `10x` / `12x` / `16x` / `20x` / `24x` / `28x` / `32x` — fixed multiples of `--space-normal` (no per-step variables; calculated directly).
|
|
12
13
|
|
|
13
14
|
**The `grow` flag** turns the chosen `width` into a floor rather than an exact size: it applies the value as `min-inline-size` and adds `flex-grow: 1`, so the element expands to fill the available space when it's a flex item. Set it on a `<Cell>` (`width="12x" grow`) to give that column a 192px minimum that absorbs the remaining width and keeps the table from collapsing the column on a narrow viewport — cells honour `min-width`, so the table scrolls instead.
|
|
14
15
|
|
|
@@ -18,11 +19,6 @@ The following `:root` variables are defined by this module and can be overridden
|
|
|
18
19
|
|
|
19
20
|
| Variable | Default | Used for |
|
|
20
21
|
|---|---|---
|
|
21
|
-
| `--width-
|
|
22
|
-
| `--width-xnarrow` | `24rem` |
|
|
23
|
-
| `--width-narrow` | `36rem` |
|
|
22
|
+
| `--width-narrow` | `36rem` | Focused single-purpose column, e.g. forms and login pages. |
|
|
24
23
|
| `--width-normal` | `48rem` | Standard content column. |
|
|
25
|
-
| `--width-wide` | `80rem` |
|
|
26
|
-
| `--width-xwide` | `96rem` |
|
|
27
|
-
| `--width-xxwide` | `112rem` |
|
|
28
|
-
| `--width-xxxwide` | `128rem` |
|
|
24
|
+
| `--width-wide` | `80rem` | Full dashboard-style content. |
|