@kennycorrea/ui 0.8.1 → 0.9.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/CHANGELOG.md +15 -0
- package/README.md +35 -0
- package/dist/atoms/Drawer/Drawer.d.ts +62 -0
- package/dist/atoms/Drawer/Drawer.js +190 -0
- package/dist/atoms/Drawer/index.d.ts +1 -0
- package/dist/atoms/Drawer/index.js +1 -0
- package/dist/atoms/index.d.ts +1 -0
- package/dist/atoms/index.js +1 -0
- package/dist/strings.d.ts +6 -0
- package/dist/strings.js +3 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.9.0 — 2026-10-18
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- **`Drawer`**, a bottom sheet with `collapsed` and `expanded` snap points, in two modes:
|
|
7
|
+
`modal` (scrim, focus trapped, page `inert`, Escape and scrim close) and `non-modal` (a
|
|
8
|
+
floating banner; the page stays usable). Drag the header with touch or mouse to change snap,
|
|
9
|
+
or past collapsed to close when `dismissible`. The handle is a real button with
|
|
10
|
+
`aria-expanded`/`aria-controls`. Controlled or uncontrolled `open` and `snap`.
|
|
11
|
+
- **`UiStrings`: `close`, `expand`, `collapse`**, used by the Drawer's close button and handle.
|
|
12
|
+
English defaults; the `closeLabel`, `expandLabel` and `collapseLabel` props override them.
|
|
13
|
+
- `examples/Drawers.tsx`: a non-modal promo banner and a modal form sheet.
|
|
14
|
+
|
|
15
|
+
### Not verified
|
|
16
|
+
- Only exercised in jsdom with simulated pointer events, not on a real touch device.
|
|
17
|
+
|
|
3
18
|
## 0.8.1 — 2026-10-11
|
|
4
19
|
|
|
5
20
|
### Fixed
|
package/README.md
CHANGED
|
@@ -310,3 +310,38 @@ is in `examples/BudgetCycleSlider.tsx`.
|
|
|
310
310
|
|
|
311
311
|
⚠ `--ui-slider-thumb-size` mirrors Themes' size-2 thumb (`--space-2 + --space-1`). The fill
|
|
312
312
|
and the marks are placed from it, so if Themes ever resizes its thumb, change it there.
|
|
313
|
+
|
|
314
|
+
## Drawer — bottom sheet
|
|
315
|
+
|
|
316
|
+
A sheet anchored to the bottom of the viewport: full width on phones, `max-w-lg` and centred
|
|
317
|
+
above that (`maxWidthClassName` to change it), safe-area aware, themed from the house tokens.
|
|
318
|
+
|
|
319
|
+
```tsx
|
|
320
|
+
// Non-modal: a floating banner, the page stays usable, no focus trap.
|
|
321
|
+
<Drawer mode="non-modal" title="Take deposits" peek={<p>Swipe up to see how.</p>}
|
|
322
|
+
footer={<Button>Get started</Button>}>
|
|
323
|
+
<ol>…steps…</ol>
|
|
324
|
+
</Drawer>
|
|
325
|
+
|
|
326
|
+
// Modal: scrim, focus trapped, page inert, Escape and the scrim close it.
|
|
327
|
+
<Drawer open={open} onOpenChange={setOpen} defaultSnap="expanded" title="New client"
|
|
328
|
+
showCloseButton footer={<Button type="submit" form="f">Save</Button>}>
|
|
329
|
+
<form id="f">…</form>
|
|
330
|
+
</Drawer>
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
- **Snap points** `collapsed` (header + `peek`) and `expanded` (body, scrolls inside, up to
|
|
334
|
+
80vh). Controlled with `snap`/`onSnapChange`, or uncontrolled from `defaultSnap`; likewise
|
|
335
|
+
`open`/`onOpenChange`/`defaultOpen`.
|
|
336
|
+
- **Drag** the header with touch or mouse: it follows the pointer, then settles past 60px or a
|
|
337
|
+
flick faster than 0.5px/ms. Down from collapsed closes when `dismissible` (the default).
|
|
338
|
+
A drag from inside the body counts only when the body is scrolled to the top and moving down.
|
|
339
|
+
- **The handle is a real button** with `aria-expanded`/`aria-controls`, so keyboard and screen
|
|
340
|
+
reader users toggle it the same way.
|
|
341
|
+
- **No words of its own.** The handle and close button names come from `expandLabel`,
|
|
342
|
+
`collapseLabel` and `closeLabel`, or the new `expand`, `collapse` and `close` keys of
|
|
343
|
+
`UiStringsProvider`.
|
|
344
|
+
- Motion is a CSS transform, switched off under `prefers-reduced-motion`.
|
|
345
|
+
|
|
346
|
+
Built by hand rather than on Radix Dialog because the non-modal half must not do what Dialog
|
|
347
|
+
does to the rest of the page. Both examples are in `examples/Drawers.tsx`.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
/** The two resting heights of a drawer. */
|
|
3
|
+
export type DrawerSnap = 'collapsed' | 'expanded';
|
|
4
|
+
/** `modal` traps focus behind a scrim; `non-modal` floats over a page that stays usable. */
|
|
5
|
+
export type DrawerMode = 'modal' | 'non-modal';
|
|
6
|
+
export interface DrawerProps {
|
|
7
|
+
/** `modal` (scrim, focus trap, inert page) or `non-modal` (floating banner). Default `modal`. */
|
|
8
|
+
mode?: DrawerMode;
|
|
9
|
+
/** Controlled visibility. Leave undefined to let the drawer own it. */
|
|
10
|
+
open?: boolean;
|
|
11
|
+
/** Initial visibility when uncontrolled. Default `true`. */
|
|
12
|
+
defaultOpen?: boolean;
|
|
13
|
+
/** Called whenever the drawer asks to open or close. */
|
|
14
|
+
onOpenChange?: (open: boolean) => void;
|
|
15
|
+
/** Called once when the drawer closes, after `onOpenChange(false)`. */
|
|
16
|
+
onClose?: () => void;
|
|
17
|
+
/** Controlled snap point. */
|
|
18
|
+
snap?: DrawerSnap;
|
|
19
|
+
/** Initial snap point when uncontrolled. Default `collapsed`. */
|
|
20
|
+
defaultSnap?: DrawerSnap;
|
|
21
|
+
/** Called whenever the drawer asks to change snap point. */
|
|
22
|
+
onSnapChange?: (snap: DrawerSnap) => void;
|
|
23
|
+
/** Whether dragging past collapsed (or the close button, Escape, the scrim) may close it. Default `true`. */
|
|
24
|
+
dismissible?: boolean;
|
|
25
|
+
/** Labels the region via `aria-labelledby`. */
|
|
26
|
+
title: ReactNode;
|
|
27
|
+
/** Optional, wired up via `aria-describedby`. */
|
|
28
|
+
description?: ReactNode;
|
|
29
|
+
/** Shown while collapsed, below the header. */
|
|
30
|
+
peek?: ReactNode;
|
|
31
|
+
/** The body, shown when expanded; scrolls inside the sheet. */
|
|
32
|
+
children?: ReactNode;
|
|
33
|
+
/** Action row pinned below the body. Shown in both snaps. */
|
|
34
|
+
footer?: ReactNode;
|
|
35
|
+
/** Render a close button in the header. Default `false`. */
|
|
36
|
+
showCloseButton?: boolean;
|
|
37
|
+
/** Overrides the close button's accessible name (otherwise the `close` UI string). */
|
|
38
|
+
closeLabel?: string;
|
|
39
|
+
/** Overrides the handle's accessible name while collapsed (otherwise the `expand` UI string). */
|
|
40
|
+
expandLabel?: string;
|
|
41
|
+
/** Overrides the handle's accessible name while expanded (otherwise the `collapse` UI string). */
|
|
42
|
+
collapseLabel?: string;
|
|
43
|
+
/** Caps the width on wider screens. Default `max-w-lg`; pass `max-w-none` for full width. */
|
|
44
|
+
maxWidthClassName?: string;
|
|
45
|
+
className?: string;
|
|
46
|
+
/** Where the portal mounts. Default `document.body`. */
|
|
47
|
+
container?: HTMLElement | null;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* A bottom sheet with two snap points and a drag handle.
|
|
51
|
+
*
|
|
52
|
+
* Built by hand rather than on Radix Dialog because half of it is non-modal: Dialog's focus
|
|
53
|
+
* trap and `aria-hidden` on the rest of the page are exactly what a floating banner must not do.
|
|
54
|
+
* In `modal` mode the same guarantees are provided here — the page's other top-level nodes are
|
|
55
|
+
* made `inert` and Tab cycles inside the sheet.
|
|
56
|
+
*
|
|
57
|
+
* Dragging follows the pointer with a transform and, on release, settles on the snap point the
|
|
58
|
+
* gesture points at: past {@link DISTANCE} pixels or faster than {@link VELOCITY} px/ms. A drag
|
|
59
|
+
* from inside the body only counts when the body is scrolled to its top and moving down, so the
|
|
60
|
+
* content still scrolls normally.
|
|
61
|
+
*/
|
|
62
|
+
export declare function Drawer({ mode, open: openProp, defaultOpen, onOpenChange, onClose, snap: snapProp, defaultSnap, onSnapChange, dismissible, title, description, peek, children, footer, showCloseButton, closeLabel, expandLabel, collapseLabel, maxWidthClassName, className, container, }: DrawerProps): import("react").ReactPortal | null;
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useId, useRef, useState, } from 'react';
|
|
3
|
+
import { createPortal } from 'react-dom';
|
|
4
|
+
import { useUiStrings } from '../../strings.js';
|
|
5
|
+
import { cn } from '../../utils/cn.js';
|
|
6
|
+
/** Pixels of travel that commit a drag regardless of speed. */
|
|
7
|
+
const DISTANCE = 60;
|
|
8
|
+
/** Pixels per millisecond that commit a flick regardless of distance. */
|
|
9
|
+
const VELOCITY = 0.5;
|
|
10
|
+
const FOCUSABLE = 'a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])';
|
|
11
|
+
function useControllable(value, initial, onChange) {
|
|
12
|
+
const [inner, setInner] = useState(initial);
|
|
13
|
+
const controlled = value !== undefined;
|
|
14
|
+
const current = controlled ? value : inner;
|
|
15
|
+
const set = useCallback((next) => {
|
|
16
|
+
if (!controlled)
|
|
17
|
+
setInner(next);
|
|
18
|
+
onChange?.(next);
|
|
19
|
+
}, [controlled, onChange]);
|
|
20
|
+
return [current, set];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* A bottom sheet with two snap points and a drag handle.
|
|
24
|
+
*
|
|
25
|
+
* Built by hand rather than on Radix Dialog because half of it is non-modal: Dialog's focus
|
|
26
|
+
* trap and `aria-hidden` on the rest of the page are exactly what a floating banner must not do.
|
|
27
|
+
* In `modal` mode the same guarantees are provided here — the page's other top-level nodes are
|
|
28
|
+
* made `inert` and Tab cycles inside the sheet.
|
|
29
|
+
*
|
|
30
|
+
* Dragging follows the pointer with a transform and, on release, settles on the snap point the
|
|
31
|
+
* gesture points at: past {@link DISTANCE} pixels or faster than {@link VELOCITY} px/ms. A drag
|
|
32
|
+
* from inside the body only counts when the body is scrolled to its top and moving down, so the
|
|
33
|
+
* content still scrolls normally.
|
|
34
|
+
*/
|
|
35
|
+
export function Drawer({ mode = 'modal', open: openProp, defaultOpen = true, onOpenChange, onClose, snap: snapProp, defaultSnap = 'collapsed', onSnapChange, dismissible = true, title, description, peek, children, footer, showCloseButton = false, closeLabel, expandLabel, collapseLabel, maxWidthClassName = 'max-w-lg', className, container, }) {
|
|
36
|
+
const strings = useUiStrings();
|
|
37
|
+
const [open, setOpen] = useControllable(openProp, defaultOpen, onOpenChange);
|
|
38
|
+
const [snap, setSnap] = useControllable(snapProp, defaultSnap, onSnapChange);
|
|
39
|
+
const [offset, setOffset] = useState(0);
|
|
40
|
+
const [dragging, setDragging] = useState(false);
|
|
41
|
+
const drag = useRef(null);
|
|
42
|
+
const suppressClick = useRef(false);
|
|
43
|
+
const sheetRef = useRef(null);
|
|
44
|
+
const bodyRef = useRef(null);
|
|
45
|
+
const wrapperRef = useRef(null);
|
|
46
|
+
const id = useId();
|
|
47
|
+
const titleId = `${id}-title`;
|
|
48
|
+
const descId = `${id}-desc`;
|
|
49
|
+
const bodyId = `${id}-body`;
|
|
50
|
+
const modal = mode === 'modal';
|
|
51
|
+
const expanded = snap === 'expanded';
|
|
52
|
+
const close = useCallback(() => {
|
|
53
|
+
setOpen(false);
|
|
54
|
+
onClose?.();
|
|
55
|
+
}, [setOpen, onClose]);
|
|
56
|
+
// Modal: everything else on the page goes inert, focus moves in, and comes back on close.
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
if (!open || !modal)
|
|
59
|
+
return;
|
|
60
|
+
const wrapper = wrapperRef.current;
|
|
61
|
+
const root = wrapper?.parentElement;
|
|
62
|
+
const previous = document.activeElement;
|
|
63
|
+
const made = [];
|
|
64
|
+
if (root) {
|
|
65
|
+
for (const el of Array.from(root.children)) {
|
|
66
|
+
if (el !== wrapper && !el.hasAttribute('inert')) {
|
|
67
|
+
el.setAttribute('inert', '');
|
|
68
|
+
made.push(el);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const first = sheetRef.current?.querySelector(FOCUSABLE);
|
|
73
|
+
(first ?? sheetRef.current)?.focus();
|
|
74
|
+
return () => {
|
|
75
|
+
for (const el of made)
|
|
76
|
+
el.removeAttribute('inert');
|
|
77
|
+
previous?.focus?.();
|
|
78
|
+
};
|
|
79
|
+
}, [open, modal]);
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
if (!open || !modal || !dismissible)
|
|
82
|
+
return;
|
|
83
|
+
const onKey = (e) => {
|
|
84
|
+
if (e.key === 'Escape')
|
|
85
|
+
close();
|
|
86
|
+
};
|
|
87
|
+
document.addEventListener('keydown', onKey);
|
|
88
|
+
return () => document.removeEventListener('keydown', onKey);
|
|
89
|
+
}, [open, modal, dismissible, close]);
|
|
90
|
+
const trapTab = (e) => {
|
|
91
|
+
if (!modal || e.key !== 'Tab' || !sheetRef.current)
|
|
92
|
+
return;
|
|
93
|
+
const items = Array.from(sheetRef.current.querySelectorAll(FOCUSABLE));
|
|
94
|
+
if (items.length === 0)
|
|
95
|
+
return;
|
|
96
|
+
const first = items[0];
|
|
97
|
+
const last = items[items.length - 1];
|
|
98
|
+
if (e.shiftKey && document.activeElement === first) {
|
|
99
|
+
e.preventDefault();
|
|
100
|
+
last.focus();
|
|
101
|
+
}
|
|
102
|
+
else if (!e.shiftKey && document.activeElement === last) {
|
|
103
|
+
e.preventDefault();
|
|
104
|
+
first.focus();
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
const begin = (e, fromBody) => {
|
|
108
|
+
if (e.button !== 0)
|
|
109
|
+
return;
|
|
110
|
+
if (fromBody && (!expanded || (bodyRef.current?.scrollTop ?? 0) > 0))
|
|
111
|
+
return;
|
|
112
|
+
drag.current = {
|
|
113
|
+
pointerId: e.pointerId,
|
|
114
|
+
startY: e.clientY,
|
|
115
|
+
lastY: e.clientY,
|
|
116
|
+
lastT: e.timeStamp,
|
|
117
|
+
velocity: 0,
|
|
118
|
+
moved: false,
|
|
119
|
+
fromBody,
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
const move = (e) => {
|
|
123
|
+
const d = drag.current;
|
|
124
|
+
if (!d || d.pointerId !== e.pointerId)
|
|
125
|
+
return;
|
|
126
|
+
const dy = e.clientY - d.startY;
|
|
127
|
+
if (!d.moved) {
|
|
128
|
+
if (Math.abs(dy) < 4)
|
|
129
|
+
return;
|
|
130
|
+
// Scrolling up inside the body is the content's business, not ours.
|
|
131
|
+
if (d.fromBody && dy < 0) {
|
|
132
|
+
drag.current = null;
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
d.moved = true;
|
|
136
|
+
setDragging(true);
|
|
137
|
+
e.currentTarget.setPointerCapture?.(e.pointerId);
|
|
138
|
+
}
|
|
139
|
+
// At least one frame, so two events in the same tick do not read as an infinite flick.
|
|
140
|
+
const dt = Math.max(16, e.timeStamp - d.lastT);
|
|
141
|
+
d.velocity = (e.clientY - d.lastY) / dt;
|
|
142
|
+
d.lastY = e.clientY;
|
|
143
|
+
d.lastT = e.timeStamp;
|
|
144
|
+
// Past the top snap the sheet resists rather than detaching.
|
|
145
|
+
setOffset(dy < 0 && expanded ? dy / 4 : dy);
|
|
146
|
+
};
|
|
147
|
+
const end = (e) => {
|
|
148
|
+
const d = drag.current;
|
|
149
|
+
if (!d || d.pointerId !== e.pointerId)
|
|
150
|
+
return;
|
|
151
|
+
drag.current = null;
|
|
152
|
+
if (!d.moved)
|
|
153
|
+
return;
|
|
154
|
+
suppressClick.current = true;
|
|
155
|
+
const dy = e.clientY - d.startY;
|
|
156
|
+
const up = dy < -DISTANCE || d.velocity < -VELOCITY;
|
|
157
|
+
const down = dy > DISTANCE || d.velocity > VELOCITY;
|
|
158
|
+
setDragging(false);
|
|
159
|
+
setOffset(0);
|
|
160
|
+
if (up && !expanded)
|
|
161
|
+
setSnap('expanded');
|
|
162
|
+
else if (down && expanded)
|
|
163
|
+
setSnap('collapsed');
|
|
164
|
+
else if (down && dismissible)
|
|
165
|
+
close();
|
|
166
|
+
};
|
|
167
|
+
const cancel = () => {
|
|
168
|
+
drag.current = null;
|
|
169
|
+
setDragging(false);
|
|
170
|
+
setOffset(0);
|
|
171
|
+
};
|
|
172
|
+
const onHandleClick = () => {
|
|
173
|
+
if (suppressClick.current) {
|
|
174
|
+
suppressClick.current = false;
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
setSnap(expanded ? 'collapsed' : 'expanded');
|
|
178
|
+
};
|
|
179
|
+
if (!open)
|
|
180
|
+
return null;
|
|
181
|
+
const target = container ?? (typeof document === 'undefined' ? null : document.body);
|
|
182
|
+
if (!target)
|
|
183
|
+
return null;
|
|
184
|
+
const dragHandlers = {
|
|
185
|
+
onPointerMove: move,
|
|
186
|
+
onPointerUp: end,
|
|
187
|
+
onPointerCancel: cancel,
|
|
188
|
+
};
|
|
189
|
+
return createPortal(_jsxs("div", { ref: wrapperRef, "data-drawer-root": "", children: [modal ? (_jsx("div", { "data-testid": "drawer-scrim", "aria-hidden": "true", className: "fixed inset-0 z-40 bg-scrim", onClick: dismissible ? close : undefined })) : null, _jsxs("div", { ref: sheetRef, role: modal ? 'dialog' : 'region', "aria-modal": modal ? true : undefined, "aria-labelledby": titleId, "aria-describedby": description ? descId : undefined, tabIndex: -1, "data-snap": snap, "data-mode": mode, onKeyDown: trapTab, style: { transform: `translateY(${Math.max(offset, -40)}px)` }, className: cn('fixed inset-x-0 bottom-0 z-50 mx-auto flex w-full flex-col', 'rounded-t-2xl border border-b-0 border-hairline bg-sheet text-ink shadow-2xl', 'pb-[env(safe-area-inset-bottom)] outline-none', !dragging && 'transition-transform duration-200 ease-out motion-reduce:transition-none', maxWidthClassName, className), children: [_jsxs("div", { className: "touch-none select-none px-5 pt-2", onPointerDown: (e) => begin(e, false), ...dragHandlers, children: [_jsx("button", { type: "button", "aria-expanded": expanded, "aria-controls": bodyId, "aria-label": expanded ? (collapseLabel ?? strings.collapse) : (expandLabel ?? strings.expand), onClick: onHandleClick, className: "mx-auto flex h-6 w-16 cursor-grab items-center justify-center rounded-full focus-visible:outline-2 focus-visible:outline-brand-700 active:cursor-grabbing", children: _jsx("span", { "aria-hidden": "true", className: "h-1.5 w-10 rounded-full bg-hairline" }) }), _jsxs("div", { className: "flex items-start gap-3 pb-3 pt-1", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("h2", { id: titleId, className: "m-0 text-base font-medium text-brand-900", children: title }), description ? (_jsx("p", { id: descId, className: "m-0 mt-1 text-sm text-ink-muted", children: description })) : null] }), showCloseButton && dismissible ? (_jsx("button", { type: "button", "aria-label": closeLabel ?? strings.close, onClick: close, className: "-mr-1 flex size-8 shrink-0 items-center justify-center rounded-full text-ink-muted hover:bg-brand-700/8 focus-visible:outline-2 focus-visible:outline-brand-700", children: _jsx("svg", { "aria-hidden": "true", width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", children: _jsx("path", { d: "M3.5 3.5l8 8m0-8l-8 8", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) }) })) : null] })] }), !expanded && peek ? _jsx("div", { className: "px-5 pb-4", children: peek }) : null, _jsx("div", { ref: bodyRef, id: bodyId, hidden: !expanded, className: "max-h-[80vh] overflow-y-auto overscroll-contain px-5 pb-4", onPointerDown: (e) => begin(e, true), ...dragHandlers, children: children }), footer ? (_jsx("div", { className: "flex justify-end gap-2 border-t border-hairline px-5 py-3", children: footer })) : null] })] }), target);
|
|
190
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Drawer.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Drawer.js';
|
package/dist/atoms/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export * from './Card/index.js';
|
|
|
6
6
|
export * from './Checkbox/index.js';
|
|
7
7
|
export * from './ContextMenu/index.js';
|
|
8
8
|
export * from './Dialog/index.js';
|
|
9
|
+
export * from './Drawer/index.js';
|
|
9
10
|
export * from './Icon/index.js';
|
|
10
11
|
export * from './Input/index.js';
|
|
11
12
|
export * from './Label/index.js';
|
package/dist/atoms/index.js
CHANGED
|
@@ -6,6 +6,7 @@ export * from './Card/index.js';
|
|
|
6
6
|
export * from './Checkbox/index.js';
|
|
7
7
|
export * from './ContextMenu/index.js';
|
|
8
8
|
export * from './Dialog/index.js';
|
|
9
|
+
export * from './Drawer/index.js';
|
|
9
10
|
export * from './Icon/index.js';
|
|
10
11
|
export * from './Input/index.js';
|
|
11
12
|
export * from './Label/index.js';
|
package/dist/strings.d.ts
CHANGED
|
@@ -28,6 +28,12 @@ export interface UiStrings {
|
|
|
28
28
|
heading: string;
|
|
29
29
|
bulletList: string;
|
|
30
30
|
orderedList: string;
|
|
31
|
+
/** Drawer: the close button's accessible name. */
|
|
32
|
+
close: string;
|
|
33
|
+
/** Drawer: the handle's accessible name while collapsed. */
|
|
34
|
+
expand: string;
|
|
35
|
+
/** Drawer: the handle's accessible name while expanded. */
|
|
36
|
+
collapse: string;
|
|
31
37
|
}
|
|
32
38
|
/**
|
|
33
39
|
* Feeds the atoms their strings, once, near the root.
|
package/dist/strings.js
CHANGED