vireuikit 0.5.0 → 0.7.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.
- package/README.md +111 -1
- package/dist/a11y-D3SS74I3.d.cts +25 -0
- package/dist/a11y-D3SS74I3.d.ts +25 -0
- package/dist/chunk-AR2AM3BR.js +557 -0
- package/dist/chunk-AR2AM3BR.js.map +1 -0
- package/dist/index.cjs +421 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +283 -4
- package/dist/index.d.ts +283 -4
- package/dist/index.js +1 -186
- package/dist/index.js.map +1 -1
- package/dist/web.cjs +1892 -0
- package/dist/web.cjs.map +1 -0
- package/dist/web.d.cts +37 -0
- package/dist/web.d.ts +37 -0
- package/dist/web.js +1339 -0
- package/dist/web.js.map +1 -0
- package/package.json +18 -6
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ capsule-to-target growth morph.
|
|
|
12
12
|
npm install vireuikit vireglass
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
`vireglass` is a peer dependency — this package draws on its material model rather than
|
|
15
|
+
`vireglass` (3.x) is a peer dependency — this package draws on its material model rather than
|
|
16
16
|
shipping its own.
|
|
17
17
|
|
|
18
18
|
## Atom state and morph
|
|
@@ -43,6 +43,116 @@ const frame = growthFrame(sourceShape, targetShape, anchorPoint, growthPhase(sta
|
|
|
43
43
|
// frame.body: the shape to draw as glass this frame.
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
+
The default timing is fitted to Apple's reference of a menu growing out of its toolbar. The menu itself is a model
|
|
47
|
+
too, so every target shares its keyboard, where it sits and what its surface is on each frame:
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
import { MENU_CLOSED, menuPlacement, menuSurfaceFrame, stepMenu } from 'vireuikit';
|
|
51
|
+
|
|
52
|
+
const step = stepMenu(MENU_CLOSED, { type: 'open', focus: 'first' }, items); // items: { label, disabled, focusable? }[]
|
|
53
|
+
// step.focus says where focus goes; a choice always closes the menu.
|
|
54
|
+
const { rect, anchor } = menuPlacement(triggerRect, menuSize, viewport);
|
|
55
|
+
const surface = menuSurfaceFrame(triggerBox, { ...rect, radius }, anchor, growthPhase(state));
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Web elements
|
|
59
|
+
|
|
60
|
+
`vireuikit/web` upgrades native controls with custom elements. The control inside works before the
|
|
61
|
+
upgrade; afterwards the element drives its states from the model. Glass is opt-in: put `glass` on pieces
|
|
62
|
+
of the navigation layer, and leave it off for content.
|
|
63
|
+
|
|
64
|
+
```html
|
|
65
|
+
<vire-button><button>Play</button></vire-button>
|
|
66
|
+
<vire-icon-button glass><button aria-label="Share">…</button></vire-icon-button>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
import { defineVireElements, setA11yOverride } from 'vireuikit/web';
|
|
71
|
+
|
|
72
|
+
defineVireElements({ nonce: cspNonce });
|
|
73
|
+
setA11yOverride({ reduceTransparency: true });
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
- `<vire-button>` is an action: it sinks and grows slightly under press, and nothing opens out of it unless it is the
|
|
77
|
+
trigger of a `<vire-menu>`.
|
|
78
|
+
- `<vire-icon-button>` lifts into the glass under the finger; the lens response is visible while the
|
|
79
|
+
press is held.
|
|
80
|
+
- Attributes: `glass` (empty or `present`: a lens at rest; `touch`: a lens only under the finger; absent: no
|
|
81
|
+
glass), `size` (`touch`, `small`, `medium`, `large`, `xlarge`; by default `touch` on a coarse pointer and
|
|
82
|
+
`medium` otherwise), `disabled`.
|
|
83
|
+
- On a coarse pointer every size keeps a hit area of at least 44 dp without changing layout.
|
|
84
|
+
- The lens reads the backdrop from declared colours and cannot see an image, a video or a canvas. A host that knows
|
|
85
|
+
what lies under the control sets the element's `sample` (a `BackdropSample` from `vireglass`), at any time; `null`
|
|
86
|
+
hands it back to the probe.
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
import { statsFromSamples } from 'vireglass/dom';
|
|
90
|
+
|
|
91
|
+
playButton.sample = statsFromSamples(coverColours); // [{ r, g, b }, …] in 0–255
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
- The element dispatches `vire-glass-ready` once its lens is attached. If the lens cannot be loaded or attached,
|
|
95
|
+
the control stays a complete one on its plain (or, under reduced transparency, opaque frosted) surface, and the next
|
|
96
|
+
setting change tries again.
|
|
97
|
+
- Set `disabled` on the host element: it is mirrored onto the inner `<button>` and wins over it. Clearing it on
|
|
98
|
+
the host re-enables the button.
|
|
99
|
+
- Under `forced-colors` the elements keep the system colours and drop their own tints and blur.
|
|
100
|
+
- Accessibility follows the system `prefers-*` settings; `setA11yOverride` or the element's `a11y`
|
|
101
|
+
property overrides them. Reduced transparency keeps the lens and frosts it: a blurrier lens and a denser body, with the
|
|
102
|
+
ink following the body. Text takes the page's colour; the frosted fallback and the high-contrast bodies assume
|
|
103
|
+
the page's `color-scheme` matches it.
|
|
104
|
+
- The elements inject one stylesheet. Under a strict CSP pass `nonce` to `defineVireElements`, or ship the
|
|
105
|
+
exported `STYLES` string yourself.
|
|
106
|
+
- Importing the module touches no DOM, so it is safe on a server; `defineVireElements()` is the only call
|
|
107
|
+
that registers anything. An element defined before its markup is parsed waits for its button.
|
|
108
|
+
|
|
109
|
+
### Menu
|
|
110
|
+
|
|
111
|
+
`<vire-menu>` wraps a platform popover menu: a trigger button with `popovertarget` (bare, or inside `<vire-button>` or
|
|
112
|
+
`<vire-icon-button>`) and a `popover` list of item buttons.
|
|
113
|
+
|
|
114
|
+
```html
|
|
115
|
+
<vire-menu glass>
|
|
116
|
+
<vire-icon-button glass>
|
|
117
|
+
<button popovertarget="more" aria-label="More">…</button>
|
|
118
|
+
</vire-icon-button>
|
|
119
|
+
<div id="more" popover>
|
|
120
|
+
<button popovertarget="more" popovertargetaction="hide"><svg>…</svg>Copy link</button>
|
|
121
|
+
<button popovertarget="more" popovertargetaction="hide">Rename</button>
|
|
122
|
+
<button popovertarget="more" popovertargetaction="hide" disabled>Delete</button>
|
|
123
|
+
</div>
|
|
124
|
+
</vire-menu>
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
- Before the element is defined the browser runs it: the trigger toggles the list, a choice clicks the item and closes
|
|
128
|
+
it, Escape and a press outside dismiss it, and focus comes back to the trigger. Write the markup without menu roles.
|
|
129
|
+
- After the upgrade the element adds the menu-button roles (`aria-haspopup`, `aria-expanded`, `menu`, `menuitem`)
|
|
130
|
+
together with their keyboard: Enter, Space or ArrowDown open on the first item and ArrowUp on the last; the arrows,
|
|
131
|
+
Home, End and typeahead move over the items; Escape and a choice return focus to the trigger; Tab closes and moves
|
|
132
|
+
on. A pointer opens it with focus on the menu. Removing the element restores the markup.
|
|
133
|
+
- Disabled items are yours to set and clear at any time; the element never rewrites them. A `disabled` item cannot take
|
|
134
|
+
focus, so the keyboard passes over it; an `aria-disabled="true"` item stays focusable, the WAI-ARIA APG way. Neither can
|
|
135
|
+
be chosen.
|
|
136
|
+
- The press that opened the menu chooses nothing: a pointer click on an item counts once the menu has arrived, a key
|
|
137
|
+
once its content shows, and neither the second click of a double click nor a held key ever counts.
|
|
138
|
+
- The list's own `beforetoggle` and `toggle` events fire when it leaves the top layer, after the growth has run back;
|
|
139
|
+
`aria-expanded` turns false as the closing begins.
|
|
140
|
+
- The menu grows out of its trigger and covers it: the trigger's body contracts into a drop, the drop grows into the
|
|
141
|
+
menu with a small overshoot, and the content comes into focus near size. A choice closes it, and closing runs the
|
|
142
|
+
same path back into the trigger. Reduced motion opens and closes it in one frame. A menu that has to stay open for
|
|
143
|
+
several picks is a popover, which is another atom.
|
|
144
|
+
- While the menu is out, the trigger hands its body to the menu's surface (`setCarried` on `<vire-button>` and
|
|
145
|
+
`<vire-icon-button>`), so there is never glass on glass.
|
|
146
|
+
- Attributes: `glass` (empty, `present` or `touch`: the surface is a lens; absent or anything else: an opaque surface), `size` (as for the buttons; rows are as tall
|
|
147
|
+
as the tier), `corner` (`top-left`, `top-right`, `bottom-left`, `bottom-right`: the trigger corner the menu pins to;
|
|
148
|
+
by default the one facing the nearest viewport corner). `sample` works as on the buttons; without one, the backdrop
|
|
149
|
+
under the menu is read once as it opens and held while it is out.
|
|
150
|
+
|
|
151
|
+
Sizes, behaviour state machines and accessibility modes are exported from `vireuikit` and shared by every
|
|
152
|
+
target. How an atom is accepted:
|
|
153
|
+
[design](https://github.com/pruffit/vireuikit/blob/main/docs/design.md),
|
|
154
|
+
[acceptance](https://github.com/pruffit/vireuikit/blob/main/docs/acceptance.md).
|
|
155
|
+
|
|
46
156
|
## License
|
|
47
157
|
|
|
48
158
|
Apache-2.0. See [LICENSE](./LICENSE) and [NOTICE](./NOTICE).
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
type A11yMode = {
|
|
2
|
+
reduceTransparency: boolean;
|
|
3
|
+
increaseContrast: boolean;
|
|
4
|
+
reduceMotion: boolean;
|
|
5
|
+
};
|
|
6
|
+
declare const A11Y_NONE: A11yMode;
|
|
7
|
+
/** `undefined` follows the system; a boolean overrides it. */
|
|
8
|
+
type A11yOverride = {
|
|
9
|
+
[K in keyof A11yMode]?: boolean | undefined;
|
|
10
|
+
};
|
|
11
|
+
declare function resolveA11y(system: A11yMode, override?: A11yOverride): A11yMode;
|
|
12
|
+
/** `plain`: no glass was asked for. `frosted`: the stand-in when glass under reduced transparency cannot attach. */
|
|
13
|
+
type Surface = 'plain' | 'frosted' | 'glass';
|
|
14
|
+
type Presentation = {
|
|
15
|
+
glass: boolean;
|
|
16
|
+
/** Reduced transparency: the glass stays and frosts. */
|
|
17
|
+
frost: boolean;
|
|
18
|
+
surface: Surface;
|
|
19
|
+
contrastBorder: boolean;
|
|
20
|
+
instantSprings: boolean;
|
|
21
|
+
};
|
|
22
|
+
declare function presentationFor(mode: A11yMode, wantsGlass: boolean): Presentation;
|
|
23
|
+
declare function sameA11y(a: A11yMode, b: A11yMode): boolean;
|
|
24
|
+
|
|
25
|
+
export { A11Y_NONE as A, type Presentation as P, type Surface as S, type A11yMode as a, type A11yOverride as b, presentationFor as p, resolveA11y as r, sameA11y as s };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
type A11yMode = {
|
|
2
|
+
reduceTransparency: boolean;
|
|
3
|
+
increaseContrast: boolean;
|
|
4
|
+
reduceMotion: boolean;
|
|
5
|
+
};
|
|
6
|
+
declare const A11Y_NONE: A11yMode;
|
|
7
|
+
/** `undefined` follows the system; a boolean overrides it. */
|
|
8
|
+
type A11yOverride = {
|
|
9
|
+
[K in keyof A11yMode]?: boolean | undefined;
|
|
10
|
+
};
|
|
11
|
+
declare function resolveA11y(system: A11yMode, override?: A11yOverride): A11yMode;
|
|
12
|
+
/** `plain`: no glass was asked for. `frosted`: the stand-in when glass under reduced transparency cannot attach. */
|
|
13
|
+
type Surface = 'plain' | 'frosted' | 'glass';
|
|
14
|
+
type Presentation = {
|
|
15
|
+
glass: boolean;
|
|
16
|
+
/** Reduced transparency: the glass stays and frosts. */
|
|
17
|
+
frost: boolean;
|
|
18
|
+
surface: Surface;
|
|
19
|
+
contrastBorder: boolean;
|
|
20
|
+
instantSprings: boolean;
|
|
21
|
+
};
|
|
22
|
+
declare function presentationFor(mode: A11yMode, wantsGlass: boolean): Presentation;
|
|
23
|
+
declare function sameA11y(a: A11yMode, b: A11yMode): boolean;
|
|
24
|
+
|
|
25
|
+
export { A11Y_NONE as A, type Presentation as P, type Surface as S, type A11yMode as a, type A11yOverride as b, presentationFor as p, resolveA11y as r, sameA11y as s };
|