tensile 0.1.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/LICENSE +21 -0
- package/README.md +409 -0
- package/THIRD_PARTY_NOTICES +93 -0
- package/dist/CalendarView.d.ts +20 -0
- package/dist/Check.d.ts +4 -0
- package/dist/Expand.d.ts +34 -0
- package/dist/Menu.d.ts +18 -0
- package/dist/Modal.d.ts +14 -0
- package/dist/SeekBar.d.ts +20 -0
- package/dist/Sheet.d.ts +12 -0
- package/dist/SliderTrack.d.ts +18 -0
- package/dist/calendar.d.ts +12 -0
- package/dist/color.d.ts +16 -0
- package/dist/components/actions/ActionMenu.d.ts +12 -0
- package/dist/components/actions/Button.d.ts +12 -0
- package/dist/components/actions/CommandPalette.d.ts +15 -0
- package/dist/components/actions/CopyButton.d.ts +8 -0
- package/dist/components/actions/HoldButton.d.ts +11 -0
- package/dist/components/actions/IconButton.d.ts +5 -0
- package/dist/components/actions/MorphButton.d.ts +6 -0
- package/dist/components/actions/SelectionBar.d.ts +12 -0
- package/dist/components/actions/SwipeButton.d.ts +9 -0
- package/dist/components/actions/Toolbar.d.ts +7 -0
- package/dist/components/data-display/Avatar.d.ts +14 -0
- package/dist/components/data-display/AvatarGroup.d.ts +15 -0
- package/dist/components/data-display/BarChart.d.ts +13 -0
- package/dist/components/data-display/DataTable.d.ts +32 -0
- package/dist/components/data-display/DescriptionList.d.ts +8 -0
- package/dist/components/data-display/DonutChart.d.ts +17 -0
- package/dist/components/data-display/Icon.d.ts +9 -0
- package/dist/components/data-display/Kbd.d.ts +2 -0
- package/dist/components/data-display/LineChart.d.ts +13 -0
- package/dist/components/data-display/List.d.ts +16 -0
- package/dist/components/data-display/NumberTicker.d.ts +6 -0
- package/dist/components/data-display/StatTile.d.ts +15 -0
- package/dist/components/data-display/Table.d.ts +27 -0
- package/dist/components/data-display/Tag.d.ts +9 -0
- package/dist/components/data-display/Timeline.d.ts +13 -0
- package/dist/components/data-display/TreeView.d.ts +18 -0
- package/dist/components/feedback/Alert.d.ts +7 -0
- package/dist/components/feedback/Badge.d.ts +9 -0
- package/dist/components/feedback/EmptyState.d.ts +8 -0
- package/dist/components/feedback/LoadingState.d.ts +6 -0
- package/dist/components/feedback/NotificationList.d.ts +21 -0
- package/dist/components/feedback/ProgressBar.d.ts +8 -0
- package/dist/components/feedback/ProgressRing.d.ts +10 -0
- package/dist/components/feedback/Skeleton.d.ts +5 -0
- package/dist/components/feedback/Spinner.d.ts +7 -0
- package/dist/components/feedback/StatusBadge.d.ts +6 -0
- package/dist/components/feedback/Toast.d.ts +6 -0
- package/dist/components/feedback/ToastStack.d.ts +13 -0
- package/dist/components/inputs/Checkbox.d.ts +7 -0
- package/dist/components/inputs/CheckboxGroup.d.ts +15 -0
- package/dist/components/inputs/ColorPicker.d.ts +16 -0
- package/dist/components/inputs/ColorSwatches.d.ts +16 -0
- package/dist/components/inputs/Combobox.d.ts +18 -0
- package/dist/components/inputs/DatePicker.d.ts +6 -0
- package/dist/components/inputs/DateRangePicker.d.ts +9 -0
- package/dist/components/inputs/EditableText.d.ts +9 -0
- package/dist/components/inputs/Field.d.ts +52 -0
- package/dist/components/inputs/Fieldset.d.ts +9 -0
- package/dist/components/inputs/FileUpload.d.ts +16 -0
- package/dist/components/inputs/Input.d.ts +7 -0
- package/dist/components/inputs/MultiSelect.d.ts +20 -0
- package/dist/components/inputs/NumberInput.d.ts +11 -0
- package/dist/components/inputs/NumberStepper.d.ts +17 -0
- package/dist/components/inputs/OTPInput.d.ts +15 -0
- package/dist/components/inputs/PasswordInput.d.ts +6 -0
- package/dist/components/inputs/RadioGroup.d.ts +17 -0
- package/dist/components/inputs/RangeSlider.d.ts +16 -0
- package/dist/components/inputs/Rating.d.ts +17 -0
- package/dist/components/inputs/SearchField.d.ts +11 -0
- package/dist/components/inputs/Select.d.ts +18 -0
- package/dist/components/inputs/Slider.d.ts +15 -0
- package/dist/components/inputs/TagInput.d.ts +13 -0
- package/dist/components/inputs/TextField.d.ts +7 -0
- package/dist/components/inputs/Textarea.d.ts +5 -0
- package/dist/components/inputs/ThemeToggle.d.ts +9 -0
- package/dist/components/inputs/TimePicker.d.ts +27 -0
- package/dist/components/inputs/TimeWheel.d.ts +25 -0
- package/dist/components/inputs/Toggle.d.ts +7 -0
- package/dist/components/inputs/ToggleGroup.d.ts +15 -0
- package/dist/components/layout/Accordion.d.ts +12 -0
- package/dist/components/layout/AppShell.d.ts +12 -0
- package/dist/components/layout/Card.d.ts +5 -0
- package/dist/components/layout/ExpandableCard.d.ts +14 -0
- package/dist/components/layout/Footer.d.ts +14 -0
- package/dist/components/layout/Header.d.ts +16 -0
- package/dist/components/layout/PageHeader.d.ts +8 -0
- package/dist/components/layout/Separator.d.ts +5 -0
- package/dist/components/layout/SplitPane.d.ts +12 -0
- package/dist/components/media/Carousel.d.ts +24 -0
- package/dist/components/media/CompareSlider.d.ts +14 -0
- package/dist/components/media/Image.d.ts +8 -0
- package/dist/components/media/Lightbox.d.ts +15 -0
- package/dist/components/media/MusicPlayer.d.ts +16 -0
- package/dist/components/media/VideoControls.d.ts +21 -0
- package/dist/components/media/VolumeSlider.d.ts +10 -0
- package/dist/components/media/WaveformScrubber.d.ts +13 -0
- package/dist/components/navigation/Breadcrumbs.d.ts +19 -0
- package/dist/components/navigation/CollapsibleSidebar.d.ts +21 -0
- package/dist/components/navigation/Link.d.ts +12 -0
- package/dist/components/navigation/PageDots.d.ts +11 -0
- package/dist/components/navigation/Pagination.d.ts +18 -0
- package/dist/components/navigation/SegmentedTabs.d.ts +13 -0
- package/dist/components/navigation/SidebarNav.d.ts +17 -0
- package/dist/components/navigation/TabBar.d.ts +14 -0
- package/dist/components/navigation/Tabs.d.ts +14 -0
- package/dist/components/navigation/UnderlineTabs.d.ts +18 -0
- package/dist/components/navigation/WizardSteps.d.ts +16 -0
- package/dist/components/overlays/AlertDialog.d.ts +12 -0
- package/dist/components/overlays/BottomSheet.d.ts +9 -0
- package/dist/components/overlays/ContextMenu.d.ts +9 -0
- package/dist/components/overlays/Dialog.d.ts +12 -0
- package/dist/components/overlays/Drawer.d.ts +10 -0
- package/dist/components/overlays/Island.d.ts +17 -0
- package/dist/components/overlays/Popover.d.ts +19 -0
- package/dist/components/overlays/Tooltip.d.ts +19 -0
- package/dist/drag.d.ts +15 -0
- package/dist/focus.d.ts +2 -0
- package/dist/geist-cyrillic-ext-wght-normal.woff2 +0 -0
- package/dist/geist-cyrillic-wght-normal.woff2 +0 -0
- package/dist/geist-latin-ext-wght-normal.woff2 +0 -0
- package/dist/geist-latin-wght-normal.woff2 +0 -0
- package/dist/geist-vietnamese-wght-normal.woff2 +0 -0
- package/dist/icons.d.ts +12 -0
- package/dist/index.d.ts +105 -0
- package/dist/index.js +7972 -0
- package/dist/list.d.ts +18 -0
- package/dist/overlay.d.ts +22 -0
- package/dist/playback.d.ts +4 -0
- package/dist/reset.css +2 -0
- package/dist/springs.d.ts +27 -0
- package/dist/styles.css +2 -0
- package/dist/useSize.d.ts +7 -0
- package/dist/useWidth.d.ts +2 -0
- package/package.json +64 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sébastien Graf
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
# Tensile
|
|
2
|
+
|
|
3
|
+
A React design system of animated components. Every control is one shape that morphs between its states; content inside it blur-swaps; things that slide use a liquid spring; drags follow the pointer and keep their speed on release. Colors, type, radii, shadows, focus and motion speed are CSS tokens an app overrides. Every component is generic: data and text come in as props with English defaults.
|
|
4
|
+
|
|
5
|
+
[Website and documentation](https://seb-graf.github.io/tensile/) · [Storybook](https://seb-graf.github.io/tensile/storybook/)
|
|
6
|
+
|
|
7
|
+
Stack: React 19, TypeScript, Motion (`motion/react`), Tailwind 4 (for the library's own build), Storybook 10, Geist.
|
|
8
|
+
|
|
9
|
+
- [Install and use](#install-and-use)
|
|
10
|
+
- [Tokens](#tokens)
|
|
11
|
+
- [Motion](#motion)
|
|
12
|
+
- [Components](#components)
|
|
13
|
+
- [Patterns and recipes](#patterns-and-recipes)
|
|
14
|
+
- [Forms](#forms)
|
|
15
|
+
- [Accessibility](#accessibility)
|
|
16
|
+
- [Responsive behavior](#responsive-behavior)
|
|
17
|
+
- [Migrating from the previous APIs](#migrating-from-the-previous-apis)
|
|
18
|
+
- [Known limitations](#known-limitations)
|
|
19
|
+
- [Developing the library](#developing-the-library)
|
|
20
|
+
|
|
21
|
+
## License
|
|
22
|
+
|
|
23
|
+
[MIT](LICENSE) © 2026 Sébastien Graf. Bundled Geist fonts retain their SIL Open Font License; see [THIRD_PARTY_NOTICES](THIRD_PARTY_NOTICES).
|
|
24
|
+
|
|
25
|
+
## Install and use
|
|
26
|
+
|
|
27
|
+
Install Tensile in an existing React 19 application:
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
npm install tensile
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The package includes:
|
|
34
|
+
|
|
35
|
+
- `index.js`: ESM with a `"use client"` banner; React, React DOM and Motion stay external.
|
|
36
|
+
- `index.d.ts` and the other declarations.
|
|
37
|
+
- `styles.css`: global tokens, unprefixed utilities, font faces, and generated CSS property initialization; no Preflight or body background rule.
|
|
38
|
+
- `reset.css`: Tailwind's preflight, opt-in.
|
|
39
|
+
|
|
40
|
+
Peer dependencies: `react` ^19 and `react-dom` ^19. Motion is a regular dependency of Tensile and installs automatically; you do not need a separate Motion install.
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
// Once, at the app's entry.
|
|
44
|
+
import "tensile/reset.css"; // optional: only if the app has no reset of its own
|
|
45
|
+
import "tensile/styles.css";
|
|
46
|
+
import "./app.css"; // your overrides, loaded after the library
|
|
47
|
+
|
|
48
|
+
import { Button, Field, Input } from "tensile";
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The app doesn't need Tailwind. `examples/consumer` is a Vite app without Tailwind that type-checks against the built declarations, builds, overrides tokens, and server-renders every export (`npm run check:consumer`).
|
|
52
|
+
|
|
53
|
+
The check installs an actual tarball in a temporary directory outside the checkout, with its own dependencies. It also type-checks the shared documentation examples. It does not validate hydration or promise framework-specific support.
|
|
54
|
+
|
|
55
|
+
For a first working component:
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
import { useState } from "react";
|
|
59
|
+
import { Toggle } from "tensile";
|
|
60
|
+
|
|
61
|
+
export default function App() {
|
|
62
|
+
const [enabled, setEnabled] = useState(false);
|
|
63
|
+
return <Toggle label="Notifications" checked={enabled} onCheckedChange={setEnabled} />;
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The reset changes native element defaults across the page. If you omit it, provide your own baseline for box sizing, form fonts, margins, borders, and native appearance in `@layer base`, then check the components in your app. Unlayered native-element rules can override component utilities. Apply `font-family: var(--font-sans)` to your app root if your reset does not establish it. Geist is served from bundled WOFF2 assets with `font-display: swap`; its license is in `THIRD_PARTY_NOTICES`.
|
|
68
|
+
|
|
69
|
+
ESM bundlers and React 19 are the intended environment. Peer-version lower bounds, non-Chromium engines, screen-reader speech, and framework hydration need separate verification. The library's compiled utilities are not a general Tailwind stylesheet; application layout classes need your own CSS or Tailwind build.
|
|
70
|
+
|
|
71
|
+
Server rendering: components render their markup on the server. The modal layers of Dialog, AlertDialog, BottomSheet, Drawer and Lightbox render nothing until they mount in the browser (their triggers and thumbnails do render). The motion scale is 1 on the server.
|
|
72
|
+
|
|
73
|
+
## Tokens
|
|
74
|
+
|
|
75
|
+
The tokens are CSS custom properties declared in `@layer theme` (`src/theme.css`). Override them on `:root`, or on any subtree, in CSS loaded after the library's: an unlayered rule always wins over the layer.
|
|
76
|
+
|
|
77
|
+
| Token | Default | Purpose |
|
|
78
|
+
|---|---|---|
|
|
79
|
+
| `--color-canvas` | `#ebe9e4` | page background (the app sets it on `body`; the library doesn't style `body`) |
|
|
80
|
+
| `--color-paper` | `#ffffff` | surfaces; text on ink |
|
|
81
|
+
| `--color-ink` | `#111110` | main text, primary surfaces |
|
|
82
|
+
| `--color-ink-3` | `#2e2e2c` | raised parts on ink (tracks), lines on ink |
|
|
83
|
+
| `--color-muted` | `#6b6964` | secondary text on paper, hover and canvas (WCAG AA on all three) |
|
|
84
|
+
| `--color-line` | `#e9e7e2` | separators, borders, and the ring of `--shadow-float` |
|
|
85
|
+
| `--color-hover` | `#f3f1ed` | hover and highlight on paper |
|
|
86
|
+
| `--color-accent` | `#b8f23e` | success and active fills |
|
|
87
|
+
| `--color-on-accent` | ink | text and icons on accent |
|
|
88
|
+
| `--color-focus` | ink | focus rings |
|
|
89
|
+
| `--font-sans` | Geist Variable | all text |
|
|
90
|
+
| `--text-caption` | 11 / 16 px | small print, axis labels |
|
|
91
|
+
| `--text-label` | 13 / 20 px | compact controls, secondary lines, errors |
|
|
92
|
+
| `--text-body` | 15 / 22 px | fields, buttons, dialog titles |
|
|
93
|
+
| `--radius-control` | 26px | controls (full pills up to 52 px tall) |
|
|
94
|
+
| `--radius-overlay` | 20px | open menus and popovers, alerts, open accordion items |
|
|
95
|
+
| `--radius-card` | 24px | cards, panels, full-view images |
|
|
96
|
+
| `--radius-dialog` | 28px | dialogs, sheets, drawers, expanded views |
|
|
97
|
+
| `--shadow-float` | a 1 px line ring, a contact shadow and a soft drop shadow | every floating surface and control |
|
|
98
|
+
| `--layer-raised`, `--layer-sticky`, `--layer-overlay` | 10, 20, 50 | stacking of raised shapes, sticky headers, exiting overlays |
|
|
99
|
+
| `--container-page` | 72rem | page content width (`max-w-page`) |
|
|
100
|
+
| `--motion-duration-scale` | 1 (0 under reduced motion) | multiplies every animation's duration and delay |
|
|
101
|
+
|
|
102
|
+
Tailwind's `text-sm` (14 px) and `text-base` and up (16 px+) complete the type scale. Control heights are a fixed scale, not tokens, because geometry is computed from them: 32 px compact controls, 44 px buttons, fields and sliders, 52 px large fields, 40 px list rows, 28 px chips, 24 px badges.
|
|
103
|
+
|
|
104
|
+
```css
|
|
105
|
+
/* app.css */
|
|
106
|
+
:root {
|
|
107
|
+
--color-accent: #3355ff;
|
|
108
|
+
--color-on-accent: #ffffff;
|
|
109
|
+
--radius-control: 12px;
|
|
110
|
+
--radius-overlay: 12px;
|
|
111
|
+
--radius-card: 14px;
|
|
112
|
+
--radius-dialog: 16px;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/* A speed change belongs inside no-preference, or it would undo reduced motion. */
|
|
116
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
117
|
+
:root {
|
|
118
|
+
--motion-duration-scale: 1.6;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/* A dark region: paper focus rings, dark separators and shadow rings inside it. */
|
|
123
|
+
.dark-band {
|
|
124
|
+
--color-focus: var(--color-paper);
|
|
125
|
+
--color-line: var(--color-ink-3);
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Notes:
|
|
130
|
+
|
|
131
|
+
- Text on accent uses `--color-on-accent`, never an assumed ink, so a dark accent works.
|
|
132
|
+
- Morphing radii are animated between `var(--radius-…)` values, so overrides reach the animations too.
|
|
133
|
+
- `--shadow-float` is compiled into the `shadow-float` utility; redefining the variable doesn't change the shadow. Its ring color does follow `--color-line`.
|
|
134
|
+
|
|
135
|
+
## Motion
|
|
136
|
+
|
|
137
|
+
- `--motion-duration-scale` is 1 by default: 2 is twice as slow, 0 turns animation off. The library CSS sets 0 under `prefers-reduced-motion: reduce`.
|
|
138
|
+
- Components read it from the root element when they mount. A change reaches components mounted afterwards; remount a subtree to apply a new speed right away (the Storybook Theme toolbar and the "Theme and motion" example do that).
|
|
139
|
+
- At 0 every state change is instant and repeating effects stop, but drags still follow the pointer, a flick still picks its target from its speed, and focus never waits for an animation.
|
|
140
|
+
- Functional timers never scale: hold durations, the copy reset, the tooltip delay, toast lifetimes, long-press delays and media time stay the same at any speed.
|
|
141
|
+
- CSS effects (`press`, `animate-spinner`, `animate-shimmer`) use the same token.
|
|
142
|
+
|
|
143
|
+
## Components
|
|
144
|
+
|
|
145
|
+
Run `npm run storybook`; each component's stories are at `/?path=/story/<id>--default`, and the Controls panel shows the full API with its defaults. Examples live under "Examples".
|
|
146
|
+
|
|
147
|
+
**Actions**
|
|
148
|
+
|
|
149
|
+
| Component | Story id | Purpose |
|
|
150
|
+
|---|---|---|
|
|
151
|
+
| Button | `components-button` | The ordinary action button: primary, secondary, ghost; 44 or 32 px. |
|
|
152
|
+
| IconButton | `components-iconbutton` | An icon-only Button with a required accessible label. |
|
|
153
|
+
| MorphButton | `components-morphbutton` | A submit/action button that morphs through loading and success. |
|
|
154
|
+
| CopyButton | `components-copybutton` | Copies a value and widens to a "Copied" check. |
|
|
155
|
+
| HoldButton | `components-holdbutton` | Press and hold to confirm a destructive action. |
|
|
156
|
+
| SwipeButton | `components-swipebutton` | Drag the knob across to confirm. |
|
|
157
|
+
| ActionMenu | `components-actionmenu` | A menu button whose shape grows into its menu. |
|
|
158
|
+
| CommandPalette | `components-commandpalette` | An inline filterable command list with ⌘K. |
|
|
159
|
+
| Toolbar | `components-toolbar` | A roving-focus toolbar whose tooltips share one gliding bubble. |
|
|
160
|
+
|
|
161
|
+
**Inputs**
|
|
162
|
+
|
|
163
|
+
| Component | Story id | Purpose |
|
|
164
|
+
|---|---|---|
|
|
165
|
+
| Input | `components-input` | A native text input in a paper pill, with leading/trailing slots. |
|
|
166
|
+
| Textarea | `components-textarea` | A native textarea whose surface springs with its text. |
|
|
167
|
+
| Field | `components-field` | Label, description and error wiring for one control. |
|
|
168
|
+
| Fieldset | `components-fieldset` | A native fieldset with a legend, description, error and disabled state. |
|
|
169
|
+
| TextField | `components-textfield` | A text field with its own floating label. |
|
|
170
|
+
| PasswordInput | `components-passwordinput` | Input with a show/hide password toggle. |
|
|
171
|
+
| SearchField | `components-searchfield` | A round search trigger that expands to its container. |
|
|
172
|
+
| NumberInput | `components-numberinput` | Typed numeric entry with formatting, clamping and arrow steps. |
|
|
173
|
+
| NumberStepper | `components-numberstepper` | A −/+ spinbutton with a rolling number. |
|
|
174
|
+
| Select | `components-select` | A select-only combobox with a top-layer menu. |
|
|
175
|
+
| Combobox | `components-combobox` | A filterable select with a text input. |
|
|
176
|
+
| MultiSelect | `components-multiselect` | Select for several values, with toggling checks. |
|
|
177
|
+
| Toggle | `components-toggle` | A native switch with a liquid knob. |
|
|
178
|
+
| ThemeToggle | `components-themetoggle` | A light/dark switch with a sun/moon knob. |
|
|
179
|
+
| Checkbox | `components-checkbox` | A native checkbox with an accent fill and indeterminate state. |
|
|
180
|
+
| CheckboxGroup | `components-checkboxgroup` | A named group of checkboxes with an array value. |
|
|
181
|
+
| RadioGroup | `components-radiogroup` | Native radios with a sliding dot. |
|
|
182
|
+
| ToggleGroup | `components-togglegroup` | Pressed-state buttons: filter chips, formatting toggles. |
|
|
183
|
+
| ColorSwatches | `components-colorswatches` | Native radios as color swatches with a sliding ring. |
|
|
184
|
+
| ColorPicker | `components-colorpicker` | Saturation/brightness area, hue slider and hex field. |
|
|
185
|
+
| Rating | `components-rating` | A star rating slider, or a read-only image. |
|
|
186
|
+
| Slider | `components-slider` | One value on a measured track with rubber overdrag. |
|
|
187
|
+
| RangeSlider | `components-rangeslider` | Two values on one track. |
|
|
188
|
+
| TagInput | `components-taginput` | Type to add removable tags. |
|
|
189
|
+
| OTPInput | `components-otpinput` | One-time code cells with paste support. |
|
|
190
|
+
| EditableText | `components-editabletext` | Inline text that morphs into an input. |
|
|
191
|
+
| TimeWheel | `components-timewheel` | Flickable hour, minute and AM/PM wheels. |
|
|
192
|
+
| TimePicker | `components-timepicker` | A trigger that grows into a TimeWheel. |
|
|
193
|
+
| DatePicker | `components-datepicker` | A month calendar for one date. |
|
|
194
|
+
| DateRangePicker | `components-daterangepicker` | A month calendar for a start and end date. |
|
|
195
|
+
| FileUpload | `components-fileupload` | A file picker and drop target with progress. |
|
|
196
|
+
|
|
197
|
+
**Navigation**
|
|
198
|
+
|
|
199
|
+
| Component | Story id | Purpose |
|
|
200
|
+
|---|---|---|
|
|
201
|
+
| Link | `components-link` | A text link; `LinkProvider` hands same-origin clicks to your router. |
|
|
202
|
+
| Tabs | `components-tabs` | Tabs with panels (underline or segmented). |
|
|
203
|
+
| SegmentedTabs | `components-segmentedtabs` | A segmented control tablist. |
|
|
204
|
+
| UnderlineTabs | `components-underlinetabs` | A tablist with a liquid underline. |
|
|
205
|
+
| TabBar | `components-tabbar` | Bottom navigation with an icon pill. |
|
|
206
|
+
| SidebarNav | `components-sidebarnav` | Vertical navigation with a liquid pill. |
|
|
207
|
+
| CollapsibleSidebar | `components-collapsiblesidebar` | SidebarNav in a rail that expands. |
|
|
208
|
+
| Breadcrumbs | `components-breadcrumbs` | A trail whose middle expands. |
|
|
209
|
+
| Pagination | `components-pagination` | Page buttons or links with a liquid pill. |
|
|
210
|
+
| PageDots | `components-pagedots` | A dot slider for pages. |
|
|
211
|
+
| WizardSteps | `components-wizardsteps` | A display-only step progress line. |
|
|
212
|
+
|
|
213
|
+
**Feedback**
|
|
214
|
+
|
|
215
|
+
| Component | Story id | Purpose |
|
|
216
|
+
|---|---|---|
|
|
217
|
+
| Spinner | `components-spinner` | A decorative loading arc. |
|
|
218
|
+
| Skeleton | `components-skeleton` | A shimmering placeholder. |
|
|
219
|
+
| StatusBadge | `components-statusbadge` | A status pill that fades between statuses. |
|
|
220
|
+
| Badge | `components-badge` | A count dot that grows into a pill. |
|
|
221
|
+
| Toast | `components-toast` | A status pill for one message. |
|
|
222
|
+
| ToastStack | `components-toaststack` | A stack of dismissible toasts. |
|
|
223
|
+
| Alert | `components-alert` | A status card that morphs between messages. |
|
|
224
|
+
| ProgressBar | `components-progressbar` | Determinate or indeterminate progress. |
|
|
225
|
+
| ProgressRing | `components-progressring` | Circular progress that ends in a check. |
|
|
226
|
+
| EmptyState | `components-emptystate` | A title, description and action for empty views. |
|
|
227
|
+
| LoadingState | `components-loadingstate` | A named loading status. |
|
|
228
|
+
| NotificationList | `components-notificationlist` | Notifications with read and dismiss actions. |
|
|
229
|
+
|
|
230
|
+
**Data display**
|
|
231
|
+
|
|
232
|
+
| Component | Story id | Purpose |
|
|
233
|
+
|---|---|---|
|
|
234
|
+
| Icon | `components-icon` | 24-grid icon shapes with a 1.5 px line at any size. |
|
|
235
|
+
| Kbd | `components-kbd` | A key cap for shortcuts. |
|
|
236
|
+
| Tag | `components-tag` | A label chip, optionally removable. |
|
|
237
|
+
| List | `components-list` | Rows with leading, title, description and trailing slots. |
|
|
238
|
+
| DescriptionList | `components-descriptionlist` | Label/value pairs that stack when narrow. |
|
|
239
|
+
| Timeline | `components-timeline` | Events joined by a line. |
|
|
240
|
+
| Avatar | `components-avatar` | An image or initials in a circle. |
|
|
241
|
+
| AvatarGroup | `components-avatargroup` | Overlapping avatars with a "+N" count. |
|
|
242
|
+
| NumberTicker | `components-numberticker` | Rolling digits. |
|
|
243
|
+
| StatTile | `components-stattile` | A metric card with a change chip. |
|
|
244
|
+
| LineChart | `components-linechart` | A line chart with a keyboard-reachable tooltip. |
|
|
245
|
+
| BarChart | `components-barchart` | A bar chart with a liquid highlight. |
|
|
246
|
+
| DonutChart | `components-donutchart` | A donut chart with a center readout. |
|
|
247
|
+
| Table | `components-table` | A native table on a card that scrolls when wide. |
|
|
248
|
+
| DataTable | `components-datatable` | Table with sorting, selection, pagination, loading, empty and row actions. |
|
|
249
|
+
| TreeView | `components-treeview` | A keyboard tree with a liquid selection pill. |
|
|
250
|
+
|
|
251
|
+
**Layout**
|
|
252
|
+
|
|
253
|
+
| Component | Story id | Purpose |
|
|
254
|
+
|---|---|---|
|
|
255
|
+
| Card | `components-card` | A paper or ink surface. |
|
|
256
|
+
| Separator | `components-separator` | A horizontal or vertical rule. |
|
|
257
|
+
| Accordion | `components-accordion` | Disclosures, one open at a time. |
|
|
258
|
+
| ExpandableCard | `components-expandablecard` | A card that grows into a detail view. |
|
|
259
|
+
| SplitPane | `components-splitpane` | Two panes with a draggable separator. |
|
|
260
|
+
| PageHeader | `components-pageheader` | Page title, description, breadcrumbs and actions. |
|
|
261
|
+
| Header | `components-header` | A sticky site/app header with a mobile drawer. |
|
|
262
|
+
| Footer | `components-footer` | Link groups and a note. |
|
|
263
|
+
| AppShell | `components-appshell` | Skip link, header, sidebar, main and mobile nav. |
|
|
264
|
+
|
|
265
|
+
**Overlays**
|
|
266
|
+
|
|
267
|
+
| Component | Story id | Purpose |
|
|
268
|
+
|---|---|---|
|
|
269
|
+
| Popover | `components-popover` | A trigger that grows into a non-modal panel, with six placements. |
|
|
270
|
+
| Tooltip | `components-tooltip` | A delayed hint for any trigger. |
|
|
271
|
+
| Dialog | `components-dialog` | A modal panel that flies from its trigger. |
|
|
272
|
+
| AlertDialog | `components-alertdialog` | A confirmation dialog. |
|
|
273
|
+
| BottomSheet | `components-bottomsheet` | A draggable sheet from the bottom. |
|
|
274
|
+
| Drawer | `components-drawer` | A draggable side panel. |
|
|
275
|
+
| ContextMenu | `components-contextmenu` | A menu on right-click, long press or Shift+F10. |
|
|
276
|
+
| Island | `components-island` | A compact activity pill that expands. |
|
|
277
|
+
|
|
278
|
+
**Media**
|
|
279
|
+
|
|
280
|
+
| Component | Story id | Purpose |
|
|
281
|
+
|---|---|---|
|
|
282
|
+
| Image | `components-image` | An image that fades in, with a fallback. |
|
|
283
|
+
| Carousel | `components-carousel` | Draggable slides with arrows and dots. |
|
|
284
|
+
| Lightbox | `components-lightbox` | Thumbnails that fly into a full view. |
|
|
285
|
+
| VolumeSlider | `components-volumeslider` | A speaker slider on paper or ink. |
|
|
286
|
+
| MusicPlayer | `components-musicplayer` | An island that expands into a player. |
|
|
287
|
+
| VideoControls | `components-videocontrols` | A controlled play, seek and volume bar. |
|
|
288
|
+
| WaveformScrubber | `components-waveformscrubber` | Scrub along a waveform. |
|
|
289
|
+
| CompareSlider | `components-compareslider` | Before/after images with a divider. |
|
|
290
|
+
|
|
291
|
+
Examples, built only from the public exports: `examples-settings-form`, `examples-authentication`, `examples-detail-page`, `examples-theme-and-motion`, `examples-data-management`, `examples-marketing`.
|
|
292
|
+
|
|
293
|
+
## Patterns and recipes
|
|
294
|
+
|
|
295
|
+
Layout needs no components; use the tokens and ordinary utilities (or your own CSS):
|
|
296
|
+
|
|
297
|
+
- Page container: `mx-auto max-w-page px-6`. Stack: `grid gap-4`. Inline row: `flex flex-wrap items-center gap-2`. Grid: `grid gap-4 sm:grid-cols-2 lg:grid-cols-3`. Aspect ratio: `aspect-video`, `aspect-3/2`.
|
|
298
|
+
- Type: `text-caption`, `text-label`, `text-sm`, `text-body`, then Tailwind sizes for headings; `text-ink` and `text-muted` on light surfaces, `text-paper` and `text-paper/55` on ink.
|
|
299
|
+
|
|
300
|
+
Recipes:
|
|
301
|
+
|
|
302
|
+
- **Button group**: related actions in `<div role="group" aria-label="…" className="flex flex-wrap gap-2">`; use `Toolbar` when it needs arrow-key navigation.
|
|
303
|
+
- **Chips**: selectable chips are `ToggleGroup`; removable filter chips are `Tag` with `onRemove`; counts are `Badge`; statuses are `StatusBadge`.
|
|
304
|
+
- **Date field**: a `Popover` whose trigger shows the date and whose panel holds a `DatePicker`; name the trigger by its label and its value, as `TimePicker` does, and close it in `onValueChange`.
|
|
305
|
+
|
|
306
|
+
```tsx
|
|
307
|
+
<p id="due-label" className="mb-1.5 text-label font-medium">Due date</p>
|
|
308
|
+
<Popover
|
|
309
|
+
open={open}
|
|
310
|
+
onOpenChange={setOpen}
|
|
311
|
+
trigger={<span id="due-value">{date ?? "Select a date"}</span>}
|
|
312
|
+
aria-labelledby="due-label due-value"
|
|
313
|
+
panelLabel="Due date"
|
|
314
|
+
panelWidth={320}
|
|
315
|
+
>
|
|
316
|
+
<DatePicker value={date} onValueChange={(next) => { setDate(next); setOpen(false); }} />
|
|
317
|
+
</Popover>
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
- **Video**: a native `<video>` drives `VideoControls`; the controls report changes and your handlers talk to the element.
|
|
321
|
+
|
|
322
|
+
```tsx
|
|
323
|
+
const video = useRef<HTMLVideoElement>(null);
|
|
324
|
+
<div className="relative aspect-video overflow-hidden rounded-card">
|
|
325
|
+
<video ref={video} src={src} className="size-full object-cover" onTimeUpdate={(e) => setTime(e.currentTarget.currentTime)} onLoadedMetadata={(e) => setDuration(e.currentTarget.duration)} />
|
|
326
|
+
<div className="absolute inset-x-3 bottom-3">
|
|
327
|
+
<VideoControls
|
|
328
|
+
duration={duration}
|
|
329
|
+
playing={playing}
|
|
330
|
+
onPlayingChange={(next) => { setPlaying(next); next ? video.current!.play() : video.current!.pause(); }}
|
|
331
|
+
currentTime={time}
|
|
332
|
+
onCurrentTimeChange={(next) => { video.current!.currentTime = next; setTime(next); }}
|
|
333
|
+
volume={volume}
|
|
334
|
+
onVolumeChange={(next) => { video.current!.volume = next; setVolume(next); }}
|
|
335
|
+
/>
|
|
336
|
+
</div>
|
|
337
|
+
</div>
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
- **Routers**: wrap the app in `<LinkProvider navigate={(href) => router.push(href)}>`. Plain left clicks on same-origin links (Link, TabBar, SidebarNav, Breadcrumbs, Pagination with `pageHref`, Header, Footer) go to `navigate`; modified clicks, new-tab links, downloads and `#fragment` links keep their native behavior.
|
|
341
|
+
- **Dark regions**: set `--color-focus: var(--color-paper)` and `--color-line: var(--color-ink-3)` on the region (as `Card tone="ink"` does).
|
|
342
|
+
|
|
343
|
+
## Forms
|
|
344
|
+
|
|
345
|
+
- Every value is controlled (`value` + `onValueChange`, `checked` + `onCheckedChange`); there are no uncontrolled modes.
|
|
346
|
+
- Native elements where they exist: Input, Textarea, Checkbox, Toggle, RadioGroup and ColorSwatches render native inputs, so `name`, `required`, `disabled`, `autoComplete` and form submission work as usual. Composite controls (Select, MultiSelect, DatePicker, Slider, TimePicker, ColorPicker, TagInput, OTPInput…) take `name` and render hidden inputs, so `new FormData(form)` contains their values.
|
|
347
|
+
- Reset: handle the form's `onReset` and set your state back; the hidden inputs follow.
|
|
348
|
+
- `Field` gives its control a visible label, a description and an error (`aria-labelledby`, `aria-describedby`, `aria-invalid`); `Fieldset` groups controls under a legend and can disable them all.
|
|
349
|
+
- Validation: validate in your submit handler and pass messages to `Field`'s `error`. Use `noValidate` on the form, or Chrome shows its own bubbles for `required` fields. Move focus to the first invalid control yourself.
|
|
350
|
+
- See the "Settings form" and "Authentication" examples.
|
|
351
|
+
|
|
352
|
+
## Accessibility
|
|
353
|
+
|
|
354
|
+
- Each component uses the matching native element or ARIA pattern (buttons, links, combobox/listbox, menu, tablist, slider, spinbutton, tree, dialog/alertdialog, radiogroup, toolbar, region/carousel), with its full keyboard support (arrows, Home/End, Enter, Space, Escape, typeahead where the pattern has it).
|
|
355
|
+
- Focus rings use `--color-focus` with a 2 px offset; dark surfaces switch it to paper. Overlays return focus to their opener. Modal overlays use a native `<dialog>`, so the page behind is inert.
|
|
356
|
+
- Every piece of user-facing text is a prop with an English default; icon-only actions require a label.
|
|
357
|
+
- Reduced motion turns animation off without changing behavior.
|
|
358
|
+
- Muted text meets WCAG AA on paper, hover and canvas; paper controls keep a visible edge on paper surfaces.
|
|
359
|
+
- Checked in Chromium with keyboard and pointer (and touch gestures for the context menu). Screen-reader speech and other browser engines haven't been tested.
|
|
360
|
+
|
|
361
|
+
## Responsive behavior
|
|
362
|
+
|
|
363
|
+
- Fields, tracks, tables, charts and cards fill their container; buttons, tabs, toggles and pills size to their content. Give a width to a wrapper, or pass a width through `className` (it's for placement and size only).
|
|
364
|
+
- DescriptionList and Footer use container queries, so they respond to their own width; PageHeader's actions wrap below the title when there's no room.
|
|
365
|
+
- Header switches to a drawer below 768 px; AppShell shows its sidebar from 1024 px and a bottom nav below.
|
|
366
|
+
- Overlays stay inside the viewport: menus and popovers flip and cap their height, tooltips clamp, sheets and dialogs cap to the viewport and scroll their body.
|
|
367
|
+
- Wide tables scroll horizontally inside a focusable, named region.
|
|
368
|
+
- Everything is checked at 390 px wide as well as desktop sizes.
|
|
369
|
+
|
|
370
|
+
## Migrating from the previous APIs
|
|
371
|
+
|
|
372
|
+
| Change | What to do |
|
|
373
|
+
|---|---|
|
|
374
|
+
| Tooltip is now per trigger | Replace `actions`/`onAction` with `<Tooltip label>{(trigger) => <IconButton {...trigger} … />}</Tooltip>`; put related buttons in a `Toolbar` (`label`, `orientation`) to share one gliding bubble and get arrow-key navigation. |
|
|
375
|
+
| Dialog `label` → `trigger` | Pass the trigger content as `trigger`; `trigger={null}` renders no button (the dialog grows from the viewport's center). |
|
|
376
|
+
| Popover `label` → `trigger`; `triggerWidth`, `panelHeight` removed | Pass the visible trigger as `trigger` (it's measured) and use `label` only to name an icon-only trigger; the panel sizes to its content (`panelWidth`, default 288); choose a `placement` if the default `bottom-left` doesn't fit. |
|
|
377
|
+
| TabBar is navigation | Items take `href` for links; it renders a `nav` with `aria-current`, and arrows move focus only. |
|
|
378
|
+
| BottomSheet covers the viewport | It renders in a modal layer over the page instead of inside its parent; remove any positioned wrapper you added for it. |
|
|
379
|
+
| Fields, tracks and charts fill their container | Components that had fixed widths (Select, Combobox, TextField, SearchField, TagInput, the sliders, the date pickers, the charts and stat tile, ProgressBar, Alert, Accordion, FileUpload, ToastStack, CommandPalette, SwipeButton, WizardSteps, WaveformScrubber, CompareSlider, VideoControls) now take their container's width; wrap them or pass `className="w-80"`. |
|
|
380
|
+
| Native inputs | Toggle, ThemeToggle, Checkbox, RadioGroup and ColorSwatches render native inputs and take native input props; read values from their callbacks or from form data. |
|
|
381
|
+
| Textarea's surface | `className` and `style` now go on the surface around the textarea, like Input's pill. |
|
|
382
|
+
| Library CSS | It no longer styles `body`; set your page background and font smoothing yourself. The reset is opt-in (`reset.css`). |
|
|
383
|
+
| Visible changes | Muted text is darker (`#6b6964`); floating surfaces have a hairline ring; ExpandableCard and MusicPlayer open with a 28 px radius; chart tooltips use 13 px text; Pagination's disabled state is 40%; play buttons press to 96%. |
|
|
384
|
+
|
|
385
|
+
## Known limitations
|
|
386
|
+
|
|
387
|
+
- Screen readers and non-Chromium browsers are untested; iOS long press on ContextMenu relies on its own 500 ms timer (iOS fires no touch `contextmenu`), and a Windows pen long press may also click what's under the pen.
|
|
388
|
+
- Deferred on purpose: dark mode, HoverCard, right-to-left layout, runtime control-size tokens, virtualized lists, async options in Combobox, and specialist systems (rich-text and code editors, maps, scheduling, diagram editors, spreadsheet grids, payments, backend auth, upload services).
|
|
389
|
+
- Breadcrumbs' expanded trail keeps its intrinsic width and can overflow at 390 px.
|
|
390
|
+
- DateRangePicker: resetting an unfinished range from null to null needs a remount; calendar inputs must be valid local ISO dates.
|
|
391
|
+
- Image keeps its loaded or failed state when `src` changes on a mounted instance; give it `key={src}`.
|
|
392
|
+
- Field errors are described (`aria-describedby`) but not announced live; a Fieldset nested inside a disabled one reports `disabled: false` to div-based controls.
|
|
393
|
+
- Popover's flip and Tooltip's clamping are decided when they open; a resize while open doesn't re-place them. An outside click closes a Popover and focus follows the click.
|
|
394
|
+
- Carousel: a hard flick can skip a slide; arrows don't announce the new slide.
|
|
395
|
+
- TreeView: ArrowRight on an open folder with no children at the end of the tree throws; item values must be unique across the tree.
|
|
396
|
+
- DataTable always shows five placeholder rows while loading; column widths follow the visible rows.
|
|
397
|
+
- MorphButton disables itself while loading, so a focused submit button drops focus to the page; move focus yourself after a save (a fix with `aria-disabled` is proposed in `docs/coverage.md`).
|
|
398
|
+
- `--shadow-float` can't be overridden through its variable (see Tokens).
|
|
399
|
+
- `Card tone="ink"` (and any dark region) doesn't remap `--color-muted`: use `text-paper/55` for secondary text on ink, and keep generic components with muted text on light surfaces. Field's label and error are ink, so forms belong on paper.
|
|
400
|
+
|
|
401
|
+
## Developing the library
|
|
402
|
+
|
|
403
|
+
- `npm run storybook`: the component workshop at http://localhost:6006.
|
|
404
|
+
- `npx tsc --noEmit`, `npm test` (calendar and color logic with Node's test runner).
|
|
405
|
+
- `npm run build`, `npm run check:consumer`.
|
|
406
|
+
- `npm run build:site` builds the landing page and documentation into `site-dist/`; `npm run preview:site` serves that production build locally.
|
|
407
|
+
- `npm run site` develops the landing page; documentation links require the combined production preview or a separately served Storybook build.
|
|
408
|
+
- [Contributing](CONTRIBUTING.md) covers checks and the release procedure; [Changelog](CHANGELOG.md) records package changes.
|
|
409
|
+
- `AGENTS.md` holds the rules (tokens, motion, API, stories, pitfalls) and the inventory; `docs/coverage.md` holds what's covered and how each wave was verified; `.claude/skills/morph-component/` is the workflow for adding a component, with `check_story.py` for browser checks.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Copyright 2024 The Geist Project Authors (https://github.com/vercel/geist-font) Geist-Italic[wght].ttf: Copyright 2024 The Geist Project Authors (https://github.com/vercel/geist-font)
|
|
2
|
+
|
|
3
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
|
+
This license is copied below, and is also available with a FAQ at:
|
|
5
|
+
http://scripts.sil.org/OFL
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
-----------------------------------------------------------
|
|
9
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
10
|
+
-----------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
PREAMBLE
|
|
13
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
14
|
+
development of collaborative font projects, to support the font creation
|
|
15
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
16
|
+
open framework in which fonts may be shared and improved in partnership
|
|
17
|
+
with others.
|
|
18
|
+
|
|
19
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
20
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
21
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
22
|
+
redistributed and/or sold with any software provided that any reserved
|
|
23
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
24
|
+
however, cannot be released under any other type of license. The
|
|
25
|
+
requirement for fonts to remain under this license does not apply
|
|
26
|
+
to any document created using the fonts or their derivatives.
|
|
27
|
+
|
|
28
|
+
DEFINITIONS
|
|
29
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
30
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
31
|
+
include source files, build scripts and documentation.
|
|
32
|
+
|
|
33
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
34
|
+
copyright statement(s).
|
|
35
|
+
|
|
36
|
+
"Original Version" refers to the collection of Font Software components as
|
|
37
|
+
distributed by the Copyright Holder(s).
|
|
38
|
+
|
|
39
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
40
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
41
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
42
|
+
new environment.
|
|
43
|
+
|
|
44
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
45
|
+
writer or other person who contributed to the Font Software.
|
|
46
|
+
|
|
47
|
+
PERMISSION & CONDITIONS
|
|
48
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
49
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
50
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
51
|
+
Software, subject to the following conditions:
|
|
52
|
+
|
|
53
|
+
1) Neither the Font Software nor any of its individual components,
|
|
54
|
+
in Original or Modified Versions, may be sold by itself.
|
|
55
|
+
|
|
56
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
57
|
+
redistributed and/or sold with any software, provided that each copy
|
|
58
|
+
contains the above copyright notice and this license. These can be
|
|
59
|
+
included either as stand-alone text files, human-readable headers or
|
|
60
|
+
in the appropriate machine-readable metadata fields within text or
|
|
61
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
62
|
+
|
|
63
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
64
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
65
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
66
|
+
presented to the users.
|
|
67
|
+
|
|
68
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
69
|
+
Software shall not be used to promote, endorse or advertise any
|
|
70
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
71
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
72
|
+
permission.
|
|
73
|
+
|
|
74
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
75
|
+
must be distributed entirely under this license, and must not be
|
|
76
|
+
distributed under any other license. The requirement for fonts to
|
|
77
|
+
remain under this license does not apply to any document created
|
|
78
|
+
using the Font Software.
|
|
79
|
+
|
|
80
|
+
TERMINATION
|
|
81
|
+
This license becomes null and void if any of the above conditions are
|
|
82
|
+
not met.
|
|
83
|
+
|
|
84
|
+
DISCLAIMER
|
|
85
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
86
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
87
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
88
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
89
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
90
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
91
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
92
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
93
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type CalendarViewProps = {
|
|
2
|
+
value: string | null;
|
|
3
|
+
onValueChange: (day: string) => void;
|
|
4
|
+
firstDayOfWeek?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
|
|
5
|
+
formatMonth?: (month: Date) => string;
|
|
6
|
+
formatWeekday?: (day: Date) => string;
|
|
7
|
+
formatDay?: (day: Date) => string;
|
|
8
|
+
previousLabel?: string;
|
|
9
|
+
nextLabel?: string;
|
|
10
|
+
min?: string;
|
|
11
|
+
max?: string;
|
|
12
|
+
id?: string;
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
required?: boolean;
|
|
15
|
+
multiple?: boolean;
|
|
16
|
+
isSelected: (day: string) => boolean;
|
|
17
|
+
onDayHover?: (day: string | null) => void;
|
|
18
|
+
selection: (cells: (string | null)[], labels: React.ReactNode[]) => React.ReactNode;
|
|
19
|
+
};
|
|
20
|
+
export declare function CalendarView({ value, onValueChange, firstDayOfWeek, formatMonth, formatWeekday, formatDay, previousLabel, nextLabel, min, max, id, disabled, required, multiple, isSelected, onDayHover, selection, }: CalendarViewProps): import("react").JSX.Element;
|
package/dist/Check.d.ts
ADDED
package/dist/Expand.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** `radius` is a CSS length, usually a token: `"var(--radius-control)"`. */
|
|
2
|
+
type Size = {
|
|
3
|
+
width: number;
|
|
4
|
+
height: number;
|
|
5
|
+
radius: string;
|
|
6
|
+
};
|
|
7
|
+
/** The side a shape grows toward and the edge it keeps aligned: `"bottom-left"` grows down from the closed shape's top edge with left edges aligned, `"top-center"` grows up from its bottom edge, centered. */
|
|
8
|
+
export type Placement = `${"top" | "bottom"}-${"left" | "center" | "right"}`;
|
|
9
|
+
export type ExpandProps = {
|
|
10
|
+
open: boolean;
|
|
11
|
+
onOpenChange: (open: boolean) => void;
|
|
12
|
+
closed: Size;
|
|
13
|
+
opened: Size;
|
|
14
|
+
/** Where the shape grows from: the closed shape's center, or a placement whose side and left/right alignment flip when the viewport has more room the other way; the shape also shifts sideways to stay in view. */
|
|
15
|
+
anchor: "center" | Placement;
|
|
16
|
+
/** Accessible name of the closed shape, which is the button that opens it. */
|
|
17
|
+
label?: string;
|
|
18
|
+
id?: string;
|
|
19
|
+
labelledBy?: string;
|
|
20
|
+
describedBy?: string;
|
|
21
|
+
invalid?: boolean;
|
|
22
|
+
disabled?: boolean;
|
|
23
|
+
/** Accessible name of the open shape; when set, the open shape is a dialog. */
|
|
24
|
+
panelLabel?: string;
|
|
25
|
+
/** Content of the closed shape. */
|
|
26
|
+
trigger: React.ReactNode;
|
|
27
|
+
/** Content of the open shape. */
|
|
28
|
+
children: React.ReactNode;
|
|
29
|
+
/** The shape's colors, e.g. "bg-ink text-paper". */
|
|
30
|
+
className: string;
|
|
31
|
+
};
|
|
32
|
+
/** One shape that springs between a closed and an open size and radius. It takes the closed size in the layout and overlays everything around it when open, from the top layer; its content blur-swaps, focus moves in on open and back on close (unless it has moved to something else), and Escape closes it. */
|
|
33
|
+
export declare function Expand({ open, onOpenChange, closed, opened, anchor, label, id, labelledBy, describedBy, invalid, disabled, panelLabel, trigger, children, className }: ExpandProps): import("react").JSX.Element;
|
|
34
|
+
export {};
|
package/dist/Menu.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type MenuAction = {
|
|
2
|
+
label: string;
|
|
3
|
+
icon?: React.ReactNode;
|
|
4
|
+
disabled?: boolean;
|
|
5
|
+
};
|
|
6
|
+
type MenuProps = {
|
|
7
|
+
actions: MenuAction[];
|
|
8
|
+
onAction: (action: MenuAction) => void;
|
|
9
|
+
onClose: (restoreFocus: boolean) => void;
|
|
10
|
+
open: boolean;
|
|
11
|
+
id: string;
|
|
12
|
+
label: string;
|
|
13
|
+
initialIndex: number;
|
|
14
|
+
maxHeight: number;
|
|
15
|
+
};
|
|
16
|
+
/** Menu rows, keyboard selection and dismissal shared by action and context menus. */
|
|
17
|
+
export declare function Menu({ actions, onAction, onClose, open, id, label, initialIndex, maxHeight }: MenuProps): import("react").JSX.Element;
|
|
18
|
+
export {};
|
package/dist/Modal.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type ModalProps = Omit<React.ComponentProps<"dialog">, "open" | "onClose" | "onCancel"> & {
|
|
2
|
+
open: boolean;
|
|
3
|
+
/** Called on Escape; the owner closes by setting `open` to false. */
|
|
4
|
+
onClose: () => void;
|
|
5
|
+
/** The layers that animate in and out, such as a backdrop and a panel, each with an `exit`. Mark the element to focus first with `data-autofocus` (React's `autoFocus` would focus it before the dialog opens). */
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* A modal layer: a native `<dialog>` shown with `showModal()` in a portal on `document.body`, so the page behind it is
|
|
10
|
+
* inert, Escape reaches `onClose`, focus returns to the element that had it, and the page doesn't scroll. When `open`
|
|
11
|
+
* turns false it closes the dialog at once, so focus and the page come back without waiting, and keeps the content
|
|
12
|
+
* painted above the page until its exit animations end. Nothing renders on the server.
|
|
13
|
+
*/
|
|
14
|
+
export declare function Modal({ open, onClose, children, className, ...props }: ModalProps): import("react").ReactPortal | null;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type SeekBarProps = {
|
|
2
|
+
/** Position in seconds. */
|
|
3
|
+
value: number;
|
|
4
|
+
/** Length in seconds. */
|
|
5
|
+
duration: number;
|
|
6
|
+
onValueChange: (value: number) => void;
|
|
7
|
+
/** Called with true when a drag starts and false when it ends, so playback can wait while scrubbing. */
|
|
8
|
+
onScrubChange: (scrubbing: boolean) => void;
|
|
9
|
+
label: string;
|
|
10
|
+
/** The position as text for screen readers. */
|
|
11
|
+
valueText: string;
|
|
12
|
+
className?: string;
|
|
13
|
+
};
|
|
14
|
+
/** Media progress bar for dark surfaces: while held it follows the pointer, thickens, and stretches past either end; ArrowLeft and ArrowRight skip 5 s. */
|
|
15
|
+
export declare function SeekBar({ value, duration, onValueChange, onScrubChange, label, valueText, className }: SeekBarProps): import("react").JSX.Element;
|
|
16
|
+
export declare function TimeReadout({ value, duration, formatTime }: {
|
|
17
|
+
value: number;
|
|
18
|
+
duration: number;
|
|
19
|
+
formatTime?: (seconds: number) => string;
|
|
20
|
+
}): import("react").JSX.Element;
|