shelving 1.271.2 → 1.271.4
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/block/List.d.ts +3 -2
- package/ui/block/List.tsx +3 -2
- package/ui/input/Popover.d.ts +1 -1
- package/ui/input/Popover.tsx +1 -1
- package/ui/layout/SidebarLayout.md +1 -0
- package/ui/layout/SidebarLayout.module.css +7 -0
- package/ui/menu/Menu.d.ts +1 -1
- package/ui/menu/Menu.tsx +1 -1
- package/ui/transition/CollapseTransition.md +1 -0
- package/ui/transition/CollapseTransition.module.css +10 -0
- package/ui/transition/FadeTransition.css +7 -0
- package/ui/transition/FadeTransition.md +1 -0
- package/ui/transition/HorizontalTransition.css +12 -0
- package/ui/transition/HorizontalTransition.md +1 -0
- package/ui/transition/Transition.md +1 -0
- package/ui/transition/VerticalTransition.css +14 -2
- package/ui/transition/VerticalTransition.md +1 -0
package/package.json
CHANGED
package/ui/block/List.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ReactElement, ReactNode } from "react";
|
|
2
|
+
import type { ImmutableArray } from "../../util/array.js";
|
|
2
3
|
import { type BlockVariants } from "../style/Block.js";
|
|
3
4
|
import { type GapVariants } from "../style/Gap.js";
|
|
4
5
|
/**
|
|
@@ -7,8 +8,8 @@ import { type GapVariants } from "../style/Gap.js";
|
|
|
7
8
|
* @see https://shelving.cc/ui/ListProps
|
|
8
9
|
*/
|
|
9
10
|
export interface ListProps extends GapVariants, BlockVariants {
|
|
10
|
-
children: ReactNode
|
|
11
|
-
ordered?: boolean;
|
|
11
|
+
readonly children: ImmutableArray<ReactNode>;
|
|
12
|
+
readonly ordered?: boolean | undefined;
|
|
12
13
|
}
|
|
13
14
|
/**
|
|
14
15
|
* List block — wraps each child in an `<li>` and renders an `<ul>` or `<ol>`.
|
package/ui/block/List.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ReactElement, ReactNode } from "react";
|
|
2
|
+
import type { ImmutableArray } from "../../util/array.js";
|
|
2
3
|
import { type BlockVariants, getBlockClass } from "../style/Block.js";
|
|
3
4
|
import { type GapVariants, getGapClass } from "../style/Gap.js";
|
|
4
5
|
import { getClass, getModuleClass } from "../util/css.js";
|
|
@@ -13,8 +14,8 @@ const LIST_UNORDERED_CLASS = getModuleClass(LIST_CSS, "unordered");
|
|
|
13
14
|
* @see https://shelving.cc/ui/ListProps
|
|
14
15
|
*/
|
|
15
16
|
export interface ListProps extends GapVariants, BlockVariants {
|
|
16
|
-
children: ReactNode
|
|
17
|
-
ordered?: boolean;
|
|
17
|
+
readonly children: ImmutableArray<ReactNode>;
|
|
18
|
+
readonly ordered?: boolean | undefined;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
/**
|
package/ui/input/Popover.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import type { Callback } from "../../util/function.js";
|
|
|
7
7
|
*
|
|
8
8
|
* @see https://shelving.cc/ui/PopoverChildren
|
|
9
9
|
*/
|
|
10
|
-
export type PopoverChildren = [
|
|
10
|
+
export type PopoverChildren = readonly [
|
|
11
11
|
/**
|
|
12
12
|
* First child of the <Popover> is element that activates the popover.
|
|
13
13
|
* - Should be a `<Button>` or `<Input>` that activates or provides the children.
|
package/ui/input/Popover.tsx
CHANGED
|
@@ -15,7 +15,7 @@ import styles from "./Popover.module.css";
|
|
|
15
15
|
*
|
|
16
16
|
* @see https://shelving.cc/ui/PopoverChildren
|
|
17
17
|
*/
|
|
18
|
-
export type PopoverChildren = [
|
|
18
|
+
export type PopoverChildren = readonly [
|
|
19
19
|
/**
|
|
20
20
|
* First child of the <Popover> is element that activates the popover.
|
|
21
21
|
* - Should be a `<Button>` or `<Input>` that activates or provides the children.
|
|
@@ -7,6 +7,7 @@ A full-viewport layout with a fixed-width side column next to a scrollable main
|
|
|
7
7
|
- Pass `right` to place the sidebar on the right rather than the left.
|
|
8
8
|
- The sidebar renders as `<nav>`, so it is a navigation landmark without extra markup — drop a `<Menu>` inside it.
|
|
9
9
|
- While the drawer is open an overlay dims the page; clicking the overlay closes it.
|
|
10
|
+
- Under `prefers-reduced-motion: reduce` the drawer snaps open/closed instead of sliding off-canvas; the overlay keeps its dimming fade, which is opacity-only and therefore reduced-motion-safe.
|
|
10
11
|
- Inside a `<Navigation>` context the drawer closes itself whenever the route changes (e.g. tapping a sidebar link).
|
|
11
12
|
- The layout owns scroll, padding, and safe-area insets so individual pages don't have to.
|
|
12
13
|
|
|
@@ -211,4 +211,11 @@
|
|
|
211
211
|
visibility: visible;
|
|
212
212
|
}
|
|
213
213
|
}
|
|
214
|
+
|
|
215
|
+
/* Reduced motion: snap the drawer open/closed instead of sliding it off-canvas. The overlay keeps its fade — an opacity-only fade is reduced-motion-safe, and `visibility` must stay transitioned so the overlay still flips hidden at the end of the fade-out. */
|
|
216
|
+
@media (width <= 48rem) and (prefers-reduced-motion: reduce) {
|
|
217
|
+
.sidebar {
|
|
218
|
+
transition: none;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
214
221
|
}
|
package/ui/menu/Menu.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ export interface MenuItemProps extends ClickableProps {
|
|
|
28
28
|
* The first child becomes the link label (rendered inside the `<a>`).
|
|
29
29
|
* - Any additional children form the submenu — only rendered when this item is "proud" (an ancestor of the current page). The caller is responsible for wrapping the submenu in a nested `<Menu>` if it wants the CSS `.menu .menu` descendant rules to apply.
|
|
30
30
|
*/
|
|
31
|
-
readonly children: ReactNode | [ReactNode, ...ReactNode[]];
|
|
31
|
+
readonly children: ReactNode | readonly [ReactNode, ...ReactNode[]];
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
34
|
* A `<li>` containing an `<a>` link, plus optional submenu content shown when this item is "proud".
|
package/ui/menu/Menu.tsx
CHANGED
|
@@ -52,7 +52,7 @@ export interface MenuItemProps extends ClickableProps {
|
|
|
52
52
|
* The first child becomes the link label (rendered inside the `<a>`).
|
|
53
53
|
* - Any additional children form the submenu — only rendered when this item is "proud" (an ancestor of the current page). The caller is responsible for wrapping the submenu in a nested `<Menu>` if it wants the CSS `.menu .menu` descendant rules to apply.
|
|
54
54
|
*/
|
|
55
|
-
readonly children: ReactNode | [ReactNode, ...ReactNode[]];
|
|
55
|
+
readonly children: ReactNode | readonly [ReactNode, ...ReactNode[]];
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
/**
|
|
@@ -6,6 +6,7 @@ A `<Transition>` preset that collapses its children in and out by animating thei
|
|
|
6
6
|
|
|
7
7
|
- Uses the `collapse` transition class — there is no direction-aware variant, so forward and back animate identically.
|
|
8
8
|
- Pass `overlay` to raise the transition group above surrounding content during the animation (`z-index: 100`).
|
|
9
|
+
- Under `prefers-reduced-motion: reduce` the collapse animation is disabled entirely — the size morph is positional movement, so the content swap happens as an instant cut (the DOM update still applies).
|
|
9
10
|
|
|
10
11
|
## Usage
|
|
11
12
|
|
|
@@ -1,3 +1,13 @@
|
|
|
1
1
|
::view-transition-image-pair(.collapse) {
|
|
2
2
|
overflow: hidden;
|
|
3
3
|
}
|
|
4
|
+
|
|
5
|
+
/* Reduced motion: the collapse IS a positional size morph (the default view-transition group animation), so disable it entirely — the swap becomes an instant cut while the DOM update still happens. */
|
|
6
|
+
@media (prefers-reduced-motion: reduce) {
|
|
7
|
+
::view-transition-group(.collapse),
|
|
8
|
+
::view-transition-image-pair(.collapse),
|
|
9
|
+
::view-transition-old(.collapse),
|
|
10
|
+
::view-transition-new(.collapse) {
|
|
11
|
+
animation: none;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -25,3 +25,10 @@
|
|
|
25
25
|
::view-transition-old(.fade) {
|
|
26
26
|
animation: fade-out var(--fade-transition-duration, var(--duration-fast)) ease-in-out both;
|
|
27
27
|
}
|
|
28
|
+
|
|
29
|
+
/* Reduced motion: keep the opacity-only crossfade — a fade moves nothing spatially, so it is reduced-motion-safe — but disable the group's default positional morph so content never slides between layouts. */
|
|
30
|
+
@media (prefers-reduced-motion: reduce) {
|
|
31
|
+
::view-transition-group(.fade) {
|
|
32
|
+
animation: none;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -6,6 +6,7 @@ A `<Transition>` preset that fades its children in and out by animating opacity.
|
|
|
6
6
|
|
|
7
7
|
- Uses the `fade` transition class — there is no direction-aware variant, so forward and back animate identically.
|
|
8
8
|
- Pass `overlay` to raise the transition group above surrounding content during the animation (`z-index: 100`).
|
|
9
|
+
- Under `prefers-reduced-motion: reduce` the fade keeps animating — an opacity-only crossfade moves nothing spatially, so it is reduced-motion-safe — but the transition group's positional morph is disabled so content never slides between layouts.
|
|
9
10
|
|
|
10
11
|
## Usage
|
|
11
12
|
|
|
@@ -68,3 +68,15 @@
|
|
|
68
68
|
::view-transition-old(.slide-left) {
|
|
69
69
|
animation: slide-out-to-right var(--horizontal-transition-duration) ease-in-out both;
|
|
70
70
|
}
|
|
71
|
+
|
|
72
|
+
/* Reduced motion: null the slide distance so the keyframes above degrade to an opacity-only crossfade (reduced-motion-safe), and disable the group's default positional morph. Unlayered so it wins over app-level overrides of the distance hook. */
|
|
73
|
+
@media (prefers-reduced-motion: reduce) {
|
|
74
|
+
:root {
|
|
75
|
+
--horizontal-transition-size: 0px;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
::view-transition-group(.slide-right),
|
|
79
|
+
::view-transition-group(.slide-left) {
|
|
80
|
+
animation: none;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -7,6 +7,7 @@ A direction-aware `<Transition>` preset that slides its children horizontally
|
|
|
7
7
|
- Defaults to `slideRight`; with the type set to `"forward"` it slides right (`slideRight`), and to `"back"` it slides left (`slideLeft`).
|
|
8
8
|
- Set the direction with `setTransitionType("forward" | "back")` inside a `startTransition()` callback before navigating — see `<Transition>`.
|
|
9
9
|
- Pass `overlay` to raise the transition group above surrounding content during the animation (`z-index: 100`).
|
|
10
|
+
- Under `prefers-reduced-motion: reduce` the slide distance is forced to `0`, so the transition degrades to an opacity-only crossfade with no positional movement (large viewport-level slides are exactly what the preference exists to suppress).
|
|
10
11
|
|
|
11
12
|
## Usage
|
|
12
13
|
|
|
@@ -7,6 +7,7 @@ The base View Transition wrapper. It wraps its children in React 19's `<ViewTran
|
|
|
7
7
|
- Set `default` for the base transition; `forward` and `back` default to it and let you pick a direction-aware variant. The class names must correspond to `::view-transition-old(.className)` / `::view-transition-new(.className)` rules in your CSS.
|
|
8
8
|
- Pass `overlay` to raise the transition group above surrounding content during the animation (`z-index: 100`, from `Transition.css`).
|
|
9
9
|
- Direction is driven by the active view-transition type. Call `setTransitionType("forward")` (or `"back"`) inside a `startTransition()` callback before navigating; the variants read that type to choose the correct slide.
|
|
10
|
+
- The preset variants honour `prefers-reduced-motion: reduce` — positional movement (slides, collapse) is removed while opacity-only fades are kept (see each preset's page). Custom transition classes should ship their own `@media (prefers-reduced-motion: reduce)` override; `animation: none` on the `::view-transition-*` pseudo-elements makes the swap an instant cut while the DOM update still happens.
|
|
10
11
|
|
|
11
12
|
## Usage
|
|
12
13
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
@keyframes slide-in-from-top {
|
|
9
9
|
from {
|
|
10
10
|
opacity: 0;
|
|
11
|
-
transform: translateY(calc(
|
|
11
|
+
transform: translateY(calc(0px - var(--vertical-transition-size)));
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
to {
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
|
|
38
38
|
to {
|
|
39
39
|
opacity: 0;
|
|
40
|
-
transform: translateY(calc(
|
|
40
|
+
transform: translateY(calc(0px - var(--vertical-transition-size)));
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -68,3 +68,15 @@
|
|
|
68
68
|
::view-transition-old(.slide-down) {
|
|
69
69
|
animation: slide-out-to-bottom var(--vertical-transition-duration) ease-in-out both;
|
|
70
70
|
}
|
|
71
|
+
|
|
72
|
+
/* Reduced motion: null the slide distance so the keyframes above degrade to an opacity-only crossfade (reduced-motion-safe), and disable the group's default positional morph. Unlayered so it wins over app-level overrides of the distance hook. */
|
|
73
|
+
@media (prefers-reduced-motion: reduce) {
|
|
74
|
+
:root {
|
|
75
|
+
--vertical-transition-size: 0px;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
::view-transition-group(.slide-up),
|
|
79
|
+
::view-transition-group(.slide-down) {
|
|
80
|
+
animation: none;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -7,6 +7,7 @@ A direction-aware `<Transition>` preset that slides its children vertically —
|
|
|
7
7
|
- Defaults to `slideDown`; with the type set to `"forward"` it slides down (`slideDown`), and to `"back"` it slides up (`slideUp`).
|
|
8
8
|
- Set the direction with `setTransitionType("forward" | "back")` inside a `startTransition()` callback before navigating — see `<Transition>`.
|
|
9
9
|
- Pass `overlay` to raise the transition group above surrounding content during the animation (`z-index: 100`).
|
|
10
|
+
- Under `prefers-reduced-motion: reduce` the slide distance is forced to `0`, so the transition degrades to an opacity-only crossfade with no positional movement (large viewport-level slides are exactly what the preference exists to suppress).
|
|
10
11
|
|
|
11
12
|
## Usage
|
|
12
13
|
|