@nadicodeai/ui 12.1.111 → 12.1.112
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/AGENTS.md +11 -9
- package/README.md +3 -2
- package/dist/components/account-menu.d.ts +1 -1
- package/dist/components/account-menu.js +1 -1
- package/dist/components/action-menu.d.ts +2 -2
- package/dist/components/action-menu.js +2 -2
- package/dist/components/activity-feed.d.ts +1 -1
- package/dist/components/activity-feed.js +1 -1
- package/dist/components/agent-card.d.ts +5 -3
- package/dist/components/agent-card.d.ts.map +1 -1
- package/dist/components/agent-card.js +5 -3
- package/dist/components/agent-list-row.d.ts +2 -2
- package/dist/components/agent-list-row.js +2 -2
- package/dist/components/agent-orb.d.ts +31 -7
- package/dist/components/agent-orb.d.ts.map +1 -1
- package/dist/components/agent-orb.js +29 -5
- package/dist/components/agent-profile.d.ts +6 -2
- package/dist/components/agent-profile.d.ts.map +1 -1
- package/dist/components/agent-profile.js +6 -2
- package/dist/components/aspect-ratio.d.ts +7 -3
- package/dist/components/aspect-ratio.d.ts.map +1 -1
- package/dist/components/aspect-ratio.js +7 -3
- package/dist/components/avatar.d.ts +11 -5
- package/dist/components/avatar.d.ts.map +1 -1
- package/dist/components/avatar.js +11 -5
- package/dist/components/breadcrumb.d.ts +1 -1
- package/dist/components/breadcrumb.js +1 -1
- package/dist/components/button.d.ts +23 -10
- package/dist/components/button.d.ts.map +1 -1
- package/dist/components/button.js +23 -10
- package/dist/components/card-row.d.ts +4 -2
- package/dist/components/card-row.d.ts.map +1 -1
- package/dist/components/card-row.js +4 -2
- package/dist/components/card.d.ts +1 -1
- package/dist/components/card.js +1 -1
- package/dist/components/carousel.d.ts +9 -4
- package/dist/components/carousel.d.ts.map +1 -1
- package/dist/components/carousel.js +9 -4
- package/dist/components/catalog-drawer.d.ts +1 -1
- package/dist/components/catalog-drawer.js +1 -1
- package/dist/components/chart-card.d.ts +1 -1
- package/dist/components/chart-card.js +1 -1
- package/dist/components/checkbox.d.ts +2 -1
- package/dist/components/checkbox.d.ts.map +1 -1
- package/dist/components/checkbox.js +2 -1
- package/dist/components/choicebox.d.ts +9 -5
- package/dist/components/choicebox.d.ts.map +1 -1
- package/dist/components/choicebox.js +9 -5
- package/dist/components/clearable-input.d.ts +2 -1
- package/dist/components/clearable-input.d.ts.map +1 -1
- package/dist/components/clearable-input.js +2 -1
- package/dist/components/code-block.d.ts +13 -10
- package/dist/components/code-block.d.ts.map +1 -1
- package/dist/components/code-block.js +13 -10
- package/dist/components/collection-filters.d.ts +1 -1
- package/dist/components/collection-filters.js +1 -1
- package/dist/components/collection-search.d.ts +11 -7
- package/dist/components/collection-search.d.ts.map +1 -1
- package/dist/components/collection-search.js +11 -7
- package/dist/components/combobox.d.ts +4 -1
- package/dist/components/combobox.d.ts.map +1 -1
- package/dist/components/combobox.js +4 -1
- package/dist/components/command.d.ts +1 -1
- package/dist/components/command.js +1 -1
- package/dist/components/company-card.d.ts +28 -5
- package/dist/components/company-card.d.ts.map +1 -1
- package/dist/components/company-card.js +28 -5
- package/dist/components/confirm-dialog.d.ts +3 -2
- package/dist/components/confirm-dialog.d.ts.map +1 -1
- package/dist/components/confirm-dialog.js +2 -2
- package/dist/components/copy-button.d.ts +2 -2
- package/dist/components/copy-button.js +2 -2
- package/dist/components/data-table.d.ts +2 -2
- package/dist/components/data-table.js +2 -2
- package/dist/components/drawer.d.ts +4 -4
- package/dist/components/drawer.d.ts.map +1 -1
- package/dist/components/drawer.js +3 -3
- package/dist/components/dropdown-menu.d.ts +2 -2
- package/dist/components/dropdown-menu.js +2 -2
- package/dist/components/empty-state.d.ts +2 -2
- package/dist/components/empty-state.js +2 -2
- package/dist/components/field.d.ts +4 -0
- package/dist/components/field.d.ts.map +1 -1
- package/dist/components/field.js +4 -0
- package/dist/components/file-diff.d.ts +5 -2
- package/dist/components/file-diff.d.ts.map +1 -1
- package/dist/components/file-diff.js +5 -2
- package/dist/components/form-dialog.d.ts +1 -1
- package/dist/components/form-dialog.js +1 -1
- package/dist/components/form-drawer.d.ts +1 -1
- package/dist/components/form-drawer.js +1 -1
- package/dist/components/gauge.d.ts +9 -7
- package/dist/components/gauge.d.ts.map +1 -1
- package/dist/components/gauge.js +9 -7
- package/dist/components/hover-card.d.ts +5 -2
- package/dist/components/hover-card.d.ts.map +1 -1
- package/dist/components/hover-card.js +5 -2
- package/dist/components/identity-mark.d.ts +3 -3
- package/dist/components/identity-mark.js +3 -3
- package/dist/components/input-group.d.ts +1 -0
- package/dist/components/input-group.d.ts.map +1 -1
- package/dist/components/input-group.js +1 -0
- package/dist/components/input-otp.d.ts +5 -3
- package/dist/components/input-otp.d.ts.map +1 -1
- package/dist/components/input-otp.js +5 -3
- package/dist/components/input.d.ts +4 -2
- package/dist/components/input.d.ts.map +1 -1
- package/dist/components/input.js +4 -2
- package/dist/components/item.d.ts +1 -1
- package/dist/components/item.js +1 -1
- package/dist/components/kbd.d.ts +4 -2
- package/dist/components/kbd.d.ts.map +1 -1
- package/dist/components/kbd.js +4 -2
- package/dist/components/label.d.ts +8 -3
- package/dist/components/label.d.ts.map +1 -1
- package/dist/components/label.js +8 -3
- package/dist/components/load-more-button.d.ts +3 -2
- package/dist/components/load-more-button.d.ts.map +1 -1
- package/dist/components/load-more-button.js +3 -2
- package/dist/components/message-notice.d.ts +1 -1
- package/dist/components/message-notice.js +1 -1
- package/dist/components/multi-select.d.ts +6 -4
- package/dist/components/multi-select.d.ts.map +1 -1
- package/dist/components/multi-select.js +6 -4
- package/dist/components/notice-banner.d.ts +2 -2
- package/dist/components/notice-banner.js +2 -2
- package/dist/components/object-workspace.d.ts +3 -3
- package/dist/components/object-workspace.d.ts.map +1 -1
- package/dist/components/object-workspace.js +2 -2
- package/dist/components/pairing-code.d.ts +2 -2
- package/dist/components/pairing-code.js +2 -2
- package/dist/components/picture-label.d.ts +3 -2
- package/dist/components/picture-label.d.ts.map +1 -1
- package/dist/components/picture-label.js +3 -2
- package/dist/components/popover.d.ts +7 -3
- package/dist/components/popover.d.ts.map +1 -1
- package/dist/components/popover.js +7 -3
- package/dist/components/progress-checklist.d.ts +1 -1
- package/dist/components/progress-checklist.js +1 -1
- package/dist/components/progress.d.ts +4 -2
- package/dist/components/progress.d.ts.map +1 -1
- package/dist/components/progress.js +4 -2
- package/dist/components/qr-code.d.ts +5 -2
- package/dist/components/qr-code.d.ts.map +1 -1
- package/dist/components/qr-code.js +5 -2
- package/dist/components/radio-group.d.ts +8 -5
- package/dist/components/radio-group.d.ts.map +1 -1
- package/dist/components/radio-group.js +8 -5
- package/dist/components/record-identity.d.ts +1 -1
- package/dist/components/record-identity.js +1 -1
- package/dist/components/record-list.d.ts +2 -2
- package/dist/components/record-list.js +2 -2
- package/dist/components/record-sheet.d.ts +2 -2
- package/dist/components/record-sheet.js +2 -2
- package/dist/components/record-time.d.ts +1 -1
- package/dist/components/record-time.js +1 -1
- package/dist/components/resizable.d.ts +2 -2
- package/dist/components/resizable.js +2 -2
- package/dist/components/row-edit-form.d.ts +1 -1
- package/dist/components/row-edit-form.js +1 -1
- package/dist/components/run-timeline.d.ts +2 -2
- package/dist/components/run-timeline.js +2 -2
- package/dist/components/scroll-area.d.ts +5 -3
- package/dist/components/scroll-area.d.ts.map +1 -1
- package/dist/components/scroll-area.js +5 -3
- package/dist/components/segmented-control.d.ts +1 -1
- package/dist/components/segmented-control.js +1 -1
- package/dist/components/select.d.ts +5 -3
- package/dist/components/select.d.ts.map +1 -1
- package/dist/components/select.js +5 -3
- package/dist/components/separator.d.ts +4 -2
- package/dist/components/separator.d.ts.map +1 -1
- package/dist/components/separator.js +4 -2
- package/dist/components/settings-facts.d.ts +3 -2
- package/dist/components/settings-facts.d.ts.map +1 -1
- package/dist/components/settings-facts.js +3 -2
- package/dist/components/settings-section.d.ts +1 -1
- package/dist/components/settings-section.js +1 -1
- package/dist/components/sheet.d.ts +6 -3
- package/dist/components/sheet.d.ts.map +1 -1
- package/dist/components/sheet.js +6 -3
- package/dist/components/skeleton.d.ts +1 -1
- package/dist/components/skeleton.js +1 -1
- package/dist/components/slider.d.ts +2 -1
- package/dist/components/slider.d.ts.map +1 -1
- package/dist/components/slider.js +2 -1
- package/dist/components/snippet.d.ts +3 -1
- package/dist/components/snippet.d.ts.map +1 -1
- package/dist/components/snippet.js +3 -1
- package/dist/components/sonner.d.ts +2 -2
- package/dist/components/sonner.js +2 -2
- package/dist/components/status-badge.d.ts +5 -2
- package/dist/components/status-badge.d.ts.map +1 -1
- package/dist/components/status-badge.js +5 -2
- package/dist/components/status-dot.d.ts +2 -1
- package/dist/components/status-dot.d.ts.map +1 -1
- package/dist/components/status-dot.js +2 -1
- package/dist/components/switch.d.ts +7 -6
- package/dist/components/switch.d.ts.map +1 -1
- package/dist/components/switch.js +7 -6
- package/dist/components/table.d.ts +18 -11
- package/dist/components/table.d.ts.map +1 -1
- package/dist/components/table.js +18 -11
- package/dist/components/tabs.d.ts +19 -13
- package/dist/components/tabs.d.ts.map +1 -1
- package/dist/components/tabs.js +19 -13
- package/dist/components/text-link.d.ts +9 -4
- package/dist/components/text-link.d.ts.map +1 -1
- package/dist/components/text-link.js +9 -4
- package/dist/components/text-with-copy-button.d.ts +2 -2
- package/dist/components/text-with-copy-button.js +2 -2
- package/dist/components/textarea.d.ts +4 -3
- package/dist/components/textarea.d.ts.map +1 -1
- package/dist/components/textarea.js +4 -3
- package/dist/components/tooltip.d.ts +5 -3
- package/dist/components/tooltip.d.ts.map +1 -1
- package/dist/components/tooltip.js +5 -3
- package/dist/components/usage-meter.d.ts +2 -2
- package/dist/components/usage-meter.js +2 -2
- package/dist/components/waiting-line.d.ts +1 -1
- package/dist/components/waiting-line.js +1 -1
- package/dist/showcase/usage.generated.d.ts.map +1 -1
- package/dist/showcase/usage.generated.js +147 -147
- package/package.json +2 -2
|
@@ -38,7 +38,7 @@ export type CollectionFiltersProps = {
|
|
|
38
38
|
* dashed chips.
|
|
39
39
|
*
|
|
40
40
|
* @family Compositions
|
|
41
|
-
* @when A collection or a feed a person narrows by a property its records share: a status, an owner, a kind. It stands in the toolbar after the search and before the sort.
|
|
41
|
+
* @when A collection or a feed a person narrows by a property its records share (its query facets): a status, an owner, a kind. It stands in the toolbar after the search and before the sort.
|
|
42
42
|
* @instead Finding one record by its name is the search. Changing the order is the sort. Switching between sibling collections is the page's tabs.
|
|
43
43
|
* @behaviour Add filter opens a picker of the facets, then of a facet's values, each searchable; Backspace in an empty search goes back to the facets. A facet in force is a chip that reopens its values, with a button that removes it. A suggested value waits as a dashed chip in the muted grey, led by a + and never by the value's own mark, so it never reads as a filter in force, while its facet is unset, and applies in one click. Focus returns to Add filter when a facet is removed. The product keeps each facet's value, in the URL where it has one.
|
|
44
44
|
* @words Every string is the product's: `copy` names Add filter, the two searches, the empty result, Back and Remove; each facet names itself, its values and its "All" choice.
|
|
@@ -44,7 +44,7 @@ function FilterPicker({ facets, copy, initialField, returnFocus, children, }) {
|
|
|
44
44
|
* dashed chips.
|
|
45
45
|
*
|
|
46
46
|
* @family Compositions
|
|
47
|
-
* @when A collection or a feed a person narrows by a property its records share: a status, an owner, a kind. It stands in the toolbar after the search and before the sort.
|
|
47
|
+
* @when A collection or a feed a person narrows by a property its records share (its query facets): a status, an owner, a kind. It stands in the toolbar after the search and before the sort.
|
|
48
48
|
* @instead Finding one record by its name is the search. Changing the order is the sort. Switching between sibling collections is the page's tabs.
|
|
49
49
|
* @behaviour Add filter opens a picker of the facets, then of a facet's values, each searchable; Backspace in an empty search goes back to the facets. A facet in force is a chip that reopens its values, with a button that removes it. A suggested value waits as a dashed chip in the muted grey, led by a + and never by the value's own mark, so it never reads as a filter in force, while its facet is unset, and applies in one click. Focus returns to Add filter when a facet is removed. The product keeps each facet's value, in the URL where it has one.
|
|
50
50
|
* @words Every string is the product's: `copy` names Add filter, the two searches, the empty result, Back and Remove; each facet names itself, its values and its "All" choice.
|
|
@@ -22,24 +22,28 @@ export type CollectionSearchProps = {
|
|
|
22
22
|
* @family Inputs
|
|
23
23
|
* @when "Pre-configured search input with a magnifying glass icon and clear button."
|
|
24
24
|
* (https://vercel.com/geist/search-input) Ours: finding a record inside one collection, at the
|
|
25
|
-
* start of its
|
|
25
|
+
* start of its `CollectionToolbar`.
|
|
26
26
|
* @instead Finding anything across the product is `CommandDialog`. Narrowing by a facet is
|
|
27
27
|
* `CollectionFilters`. A free value in a form is `Input`. "For an inline search box, set the
|
|
28
28
|
* `search` variant with a scoped placeholder like `Search projects`; don’t embed a `<SearchInput>`
|
|
29
29
|
* inside an unrelated form." (https://vercel.com/geist/input) Ours: this component is the search;
|
|
30
30
|
* `Input` has no `search` variant.
|
|
31
|
-
* @behaviour
|
|
32
|
-
* the end of the box once it has text. Ring, halo, hover and disabled are `Input`'s. Results stay
|
|
33
|
-
* on screen while a search updates; `loading` marks the box busy and draws the waiting line after a
|
|
34
|
-
* second. "Automatically clears the input if escape is pressed." (https://vercel.com/geist/input)
|
|
31
|
+
* @behaviour "Automatically clears the input if escape is pressed." (https://vercel.com/geist/input)
|
|
35
32
|
* "Displays the <kbd>⌘</kbd> <kbd>K</kbd> shortcut to indicate that the input supports a command
|
|
36
33
|
* palette." (https://vercel.com/geist/input) "Transitions to showing <kbd>Esc</kbd> when the field
|
|
37
|
-
* is dirty." (https://vercel.com/geist/input)
|
|
34
|
+
* is dirty." (https://vercel.com/geist/input) Ours: a `ClearableInput` with the search mark in a
|
|
35
|
+
* 14 px slot, or a custom `prefix` in its place. Once the box has text and is enabled, an Esc key
|
|
36
|
+
* cap (a close mark on a touch screen) stands flush against its end; pressing it, or Escape inside
|
|
37
|
+
* the box, empties the value, calls `onClear` and puts focus back in the box. Ring, halo, hover and
|
|
38
|
+
* disabled are `Input`'s. Results stay on screen while a search updates; `loading` marks the box
|
|
39
|
+
* busy and draws the waiting line after a second. Optional `shortcut` keys stand at the end while
|
|
40
|
+
* the box is empty and give way to the Esc key cap once it has text.
|
|
38
41
|
* @words "A `SearchInput` placeholder names the scope (`Search projects`) so the role is clear
|
|
39
42
|
* without sighted context." (https://vercel.com/geist/input) Ours: the search's label is what it
|
|
40
43
|
* finds, also shown as its placeholder: *Find a skill*, *Search the hub*.
|
|
41
44
|
* @access The input carries `aria-label` from `label` and `type="search"`; the clear button is
|
|
42
|
-
* named by `clearLabel
|
|
45
|
+
* named by `clearLabel` and appears only while the box has text and is enabled; the search mark is
|
|
46
|
+
* decorative. A search always has both names, so neither
|
|
43
47
|
* can be left out.
|
|
44
48
|
*/
|
|
45
49
|
export declare function CollectionSearch({ label, clearLabel, value, onValueChange, onClear, disabled, loading, prefix, shortcut, }: CollectionSearchProps): import("react").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collection-search.d.ts","sourceRoot":"","sources":["../../src/components/collection-search.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,OAAO,EAAkB,KAAK,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAE3F,MAAM,MAAM,qBAAqB,GAAG;IAClC,2FAA2F;IAC3F,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,sDAAsD;IACtD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,sBAAsB,CAAC;CACnC,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"collection-search.d.ts","sourceRoot":"","sources":["../../src/components/collection-search.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,OAAO,EAAkB,KAAK,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAE3F,MAAM,MAAM,qBAAqB,GAAG;IAClC,2FAA2F;IAC3F,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,sDAAsD;IACtD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,sBAAsB,CAAC;CACnC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,UAAU,EACV,KAAK,EACL,aAAa,EACb,OAAO,EACP,QAAQ,EACR,OAAO,EACP,MAAM,EACN,QAAQ,GACT,EAAE,qBAAqB,+BAgBvB"}
|
|
@@ -8,24 +8,28 @@ import { ClearableInput } from "./clearable-input.js";
|
|
|
8
8
|
* @family Inputs
|
|
9
9
|
* @when "Pre-configured search input with a magnifying glass icon and clear button."
|
|
10
10
|
* (https://vercel.com/geist/search-input) Ours: finding a record inside one collection, at the
|
|
11
|
-
* start of its
|
|
11
|
+
* start of its `CollectionToolbar`.
|
|
12
12
|
* @instead Finding anything across the product is `CommandDialog`. Narrowing by a facet is
|
|
13
13
|
* `CollectionFilters`. A free value in a form is `Input`. "For an inline search box, set the
|
|
14
14
|
* `search` variant with a scoped placeholder like `Search projects`; don’t embed a `<SearchInput>`
|
|
15
15
|
* inside an unrelated form." (https://vercel.com/geist/input) Ours: this component is the search;
|
|
16
16
|
* `Input` has no `search` variant.
|
|
17
|
-
* @behaviour
|
|
18
|
-
* the end of the box once it has text. Ring, halo, hover and disabled are `Input`'s. Results stay
|
|
19
|
-
* on screen while a search updates; `loading` marks the box busy and draws the waiting line after a
|
|
20
|
-
* second. "Automatically clears the input if escape is pressed." (https://vercel.com/geist/input)
|
|
17
|
+
* @behaviour "Automatically clears the input if escape is pressed." (https://vercel.com/geist/input)
|
|
21
18
|
* "Displays the <kbd>⌘</kbd> <kbd>K</kbd> shortcut to indicate that the input supports a command
|
|
22
19
|
* palette." (https://vercel.com/geist/input) "Transitions to showing <kbd>Esc</kbd> when the field
|
|
23
|
-
* is dirty." (https://vercel.com/geist/input)
|
|
20
|
+
* is dirty." (https://vercel.com/geist/input) Ours: a `ClearableInput` with the search mark in a
|
|
21
|
+
* 14 px slot, or a custom `prefix` in its place. Once the box has text and is enabled, an Esc key
|
|
22
|
+
* cap (a close mark on a touch screen) stands flush against its end; pressing it, or Escape inside
|
|
23
|
+
* the box, empties the value, calls `onClear` and puts focus back in the box. Ring, halo, hover and
|
|
24
|
+
* disabled are `Input`'s. Results stay on screen while a search updates; `loading` marks the box
|
|
25
|
+
* busy and draws the waiting line after a second. Optional `shortcut` keys stand at the end while
|
|
26
|
+
* the box is empty and give way to the Esc key cap once it has text.
|
|
24
27
|
* @words "A `SearchInput` placeholder names the scope (`Search projects`) so the role is clear
|
|
25
28
|
* without sighted context." (https://vercel.com/geist/input) Ours: the search's label is what it
|
|
26
29
|
* finds, also shown as its placeholder: *Find a skill*, *Search the hub*.
|
|
27
30
|
* @access The input carries `aria-label` from `label` and `type="search"`; the clear button is
|
|
28
|
-
* named by `clearLabel
|
|
31
|
+
* named by `clearLabel` and appears only while the box has text and is enabled; the search mark is
|
|
32
|
+
* decorative. A search always has both names, so neither
|
|
29
33
|
* can be left out.
|
|
30
34
|
*/
|
|
31
35
|
export function CollectionSearch({ label, clearLabel, value, onValueChange, onClear, disabled, loading, prefix, shortcut, }) {
|
|
@@ -18,7 +18,10 @@ import { type FieldSize } from "../internal/input-box.js";
|
|
|
18
18
|
* (https://vercel.com/geist/combobox) Ours: several values chosen from a list you scan rather than
|
|
19
19
|
* type into is a `MultiSelect`; `Combobox` takes several with `multiple`. `Input` has no `search`
|
|
20
20
|
* variant, so free text is an `Input` and narrowing a collection is `CollectionFilters`.
|
|
21
|
-
* @behaviour The
|
|
21
|
+
* @behaviour The parts are `ComboboxInput`, `ComboboxContent`, `ComboboxList`, `ComboboxItem`,
|
|
22
|
+
* `ComboboxGroup` with its `ComboboxLabel`, `ComboboxLoading`, and `ComboboxChips` with its
|
|
23
|
+
* `ComboboxChip` and `ComboboxChipsInput` for `multiple`; the line for no match is the `empty` of
|
|
24
|
+
* `ComboboxContent`. The box fills its container and is `Input`'s: its three sizes (`size` on `ComboboxInput`), its ring, hover,
|
|
22
25
|
* focus halo and disabled, with the search mark at the start, a `placeholder` that names the scope,
|
|
23
26
|
* and the open-list or clear button flush at the end, in the muted grey until hovered (the
|
|
24
27
|
* open-list button is 30 px high and centred at the default size, full height at `sm` and `lg`).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"combobox.d.ts","sourceRoot":"","sources":["../../src/components/combobox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,QAAQ,IAAI,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAIxE,OAAO,EAAU,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAgC,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AASpF
|
|
1
|
+
{"version":3,"file":"combobox.d.ts","sourceRoot":"","sources":["../../src/components/combobox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,QAAQ,IAAI,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAIxE,OAAO,EAAU,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAgC,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AASpF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiEG;AACH,QAAA,MAAM,QAAQ,+BAAyB,CAAC;AAExC,iBAAS,aAAa,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAAK,qBAEjE;AAED,iBAAS,eAAe,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,CAAC,OAAO,CAAC,KAAK,qBAW1F;AAkBD,KAAK,qBAAqB,GACtB;IAAE,WAAW,EAAE,KAAK,CAAC;IAAC,YAAY,CAAC,EAAE,SAAS,CAAA;CAAE,GAChD;IAAE,WAAW,CAAC,EAAE,IAAI,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD,KAAK,mBAAmB,GACpB;IAAE,SAAS,CAAC,EAAE,KAAK,CAAC;IAAC,UAAU,CAAC,EAAE,SAAS,CAAA;CAAE,GAC7C;IAAE,SAAS,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5C,iBAAS,aAAa,CAAC,EACrB,SAAS,EACT,QAAQ,EACR,QAAgB,EAChB,WAAkB,EAClB,YAAY,EACZ,SAAiB,EACjB,UAAU,EACV,IAAI,EACJ,KAAK,EACL,KAAK,EACL,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAAC,GAAG;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,wFAAwF;IACxF,WAAW,EAAE,MAAM,CAAC;IACpB,wFAAwF;IACxF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,SAAS,GACX,qBAAqB,GACrB,mBAAmB,qBA0CpB;AAED,iBAAS,eAAe,CAAC,EACvB,SAAS,EACT,IAAe,EACf,UAAc,EACd,KAAgB,EAChB,WAAe,EACf,MAAM,EACN,KAAK,EACL,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAAK,GAC9B,IAAI,CACF,iBAAiB,CAAC,UAAU,CAAC,KAAK,EAClC,MAAM,GAAG,OAAO,GAAG,YAAY,GAAG,aAAa,GAAG,QAAQ,CAC3D,GAAG;IACF,8FAA8F;IAC9F,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,qBA2BF;AAED,iBAAS,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,CAAC,IAAI,CAAC,KAAK,qBAW1E;AAED,iBAAS,YAAY,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,CAAC,IAAI,CAAC,KAAK,qBAwBpF;AAED,iBAAS,aAAa,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAAK,qBAI5E;AAED,iBAAS,aAAa,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,CAAC,UAAU,CAAC,KAAK,qBAQjF;AAED,iBAAS,kBAAkB,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,CAAC,UAAU,CAAC,KAAK,qBAE3E;AAeD,iBAAS,eAAe,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,CAAC,MAAM,CAAC,KAAK,qBAQ/E;AAED,iBAAS,iBAAiB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,CAAC,SAAS,CAAC,KAAK,qBAQpF;AAED,iBAAS,aAAa,CAAC,EACrB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,qBAAqB,CAAC,OAAO,iBAAiB,CAAC,KAAK,CAAC,GAAG,iBAAiB,CAAC,KAAK,CAAC,KAAK,qBAa7F;AAED,KAAK,kBAAkB,GACnB;IAAE,UAAU,EAAE,KAAK,CAAC;IAAC,WAAW,CAAC,EAAE,SAAS,CAAA;CAAE,GAC9C;IAAE,UAAU,CAAC,EAAE,IAAI,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/C,iBAAS,YAAY,CAAC,EACpB,SAAS,EACT,QAAQ,EACR,UAAiB,EACjB,WAAW,EACX,GAAG,KAAK,EACT,EAAE,iBAAiB,CAAC,IAAI,CAAC,KAAK,GAAG,kBAAkB,qBAsBnD;AAED,iBAAS,kBAAkB,CAAC,EAC1B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAAK,GAAG,cAAc,qBAShD;AAED,iBAAS,iBAAiB,2CAEzB;AAED,OAAO,EACL,QAAQ,EACR,aAAa,EACb,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,aAAa,EACb,iBAAiB,GAClB,CAAC"}
|
|
@@ -23,7 +23,10 @@ import { ChevronDownIcon, XIcon, CheckIcon, SearchIcon } from "lucide-react";
|
|
|
23
23
|
* (https://vercel.com/geist/combobox) Ours: several values chosen from a list you scan rather than
|
|
24
24
|
* type into is a `MultiSelect`; `Combobox` takes several with `multiple`. `Input` has no `search`
|
|
25
25
|
* variant, so free text is an `Input` and narrowing a collection is `CollectionFilters`.
|
|
26
|
-
* @behaviour The
|
|
26
|
+
* @behaviour The parts are `ComboboxInput`, `ComboboxContent`, `ComboboxList`, `ComboboxItem`,
|
|
27
|
+
* `ComboboxGroup` with its `ComboboxLabel`, `ComboboxLoading`, and `ComboboxChips` with its
|
|
28
|
+
* `ComboboxChip` and `ComboboxChipsInput` for `multiple`; the line for no match is the `empty` of
|
|
29
|
+
* `ComboboxContent`. The box fills its container and is `Input`'s: its three sizes (`size` on `ComboboxInput`), its ring, hover,
|
|
27
30
|
* focus halo and disabled, with the search mark at the start, a `placeholder` that names the scope,
|
|
28
31
|
* and the open-list or clear button flush at the end, in the muted grey until hovered (the
|
|
29
32
|
* open-list button is 30 px high and centred at the default size, full height at `sm` and `lg`).
|
|
@@ -13,7 +13,7 @@ declare function Command({ className, children, resultCount, ...props }: React.C
|
|
|
13
13
|
* @family Navigation
|
|
14
14
|
* @when "Use CommandMenu for a global, keyboard-first command palette that finds resources and runs actions across the app." (https://vercel.com/geist/command-menu) Ours: finding anything across the product and going there: an Agent, a customer, a page, a creation page (*New Agent*). Opened by ⌘K or the sidebar's Find. It goes to places and never runs a command.
|
|
15
15
|
* @instead "For a menu opened from a visible trigger on a single resource, use `Menu`; for right-click on a row, use `ContextMenu`." (https://vercel.com/geist/command-menu) "Group items into pages (`Projects`, `Team Settings`) when a single flat list would exceed roughly 30 items or span multiple resource types." (https://vercel.com/geist/command-menu) Ours: those are `DropdownMenu` and `ContextMenu`. One record's commands are its `ActionMenu`. Search inside one collection is `CollectionSearch`. Choosing the page's scope is `ScopeSwitcher`. `CommandDialog` has no pages: its list is groups.
|
|
16
|
-
* @behaviour "Bind `⌘K` on macOS and `Ctrl+K` elsewhere. Don’t reuse the binding for any in-page filter input; it’s a global shortcut." (https://vercel.com/geist/command-menu) "Open into the root page; preserve the search query when navigating back from a sub-page so the user’s typing isn’t lost." (https://vercel.com/geist/command-menu) "Trap focus inside the overlay while it’s open and return focus to the previously active element on close." (https://vercel.com/geist/command-menu) "Show a recent or default item set when the input is empty so the menu is useful before typing." (https://vercel.com/geist/command-menu) Ours: a solid surface, never glass; opens instantly, 640 px wide and 15% down the window; on a phone it is a bottom sheet, 640 px high with 8 px top corners and the list filling it. The input row stands above the list with a line under it, the field in large type with no icon and an *Esc* key at its end that closes the dialog and is the next stop after the field on Tab; the list scrolls past 436 px. The first row is highlighted on open. No match says so. Every row is 36 px with the pointer cursor, a group's heading is a muted 36 px row, a divider bleeds across the list. A row's shortcut is a `CommandShortcut` and a word or icon at its end is a `CommandSuffix`. Colour carries nothing: the highlighted row is a faint neutral wash with its text unchanged, group headings, suffixes and the empty line are muted, and no row, key or divider takes a hue.
|
|
16
|
+
* @behaviour "Bind `⌘K` on macOS and `Ctrl+K` elsewhere. Don’t reuse the binding for any in-page filter input; it’s a global shortcut." (https://vercel.com/geist/command-menu) "Open into the root page; preserve the search query when navigating back from a sub-page so the user’s typing isn’t lost." (https://vercel.com/geist/command-menu) "Trap focus inside the overlay while it’s open and return focus to the previously active element on close." (https://vercel.com/geist/command-menu) "Show a recent or default item set when the input is empty so the menu is useful before typing." (https://vercel.com/geist/command-menu) Ours: a solid surface, never glass; opens instantly, 640 px wide and 15% down the window; on a phone it is a bottom sheet, 640 px high with 8 px top corners and the list filling it. The input row stands above the list with a line under it, the field in large type with no icon and an *Esc* key at its end that closes the dialog and is the next stop after the field on Tab; the list scrolls past 436 px. The first row is highlighted on open. No match says so. Every row is 36 px with the pointer cursor, a group's heading is a muted 36 px row, a divider bleeds across the list. A row's shortcut is a `CommandShortcut` and a word or icon at its end is a `CommandSuffix`. Colour carries nothing: the highlighted row is a faint neutral wash with its text unchanged, group headings, suffixes and the empty line are muted, and no row, key or divider takes a hue. `CommandDialog` draws `Command` itself, so a product never mounts one; its parts are `CommandInput`, `CommandList`, `CommandEmpty`, `CommandGroup`, `CommandItem` and `CommandShortcut` (a `Kbd`).
|
|
17
17
|
* @words "`<CommandMenu.Item>` children are Title Case verb phrases (`Deploy Project`, `Invite Team Member`). Avoid navigation phrasing like `Go to project page`; CommandMenu commands act, not browse." (https://vercel.com/geist/command-menu) "`CommandMenuPage.label` is Title Case and names the scope (`Projects`, `Team Settings`)." (https://vercel.com/geist/command-menu) "`CommandMenuPage.placeholder` is sentence case, action-oriented, and ends with `…` (`Search projects…`, `Type a command or search…`). Bare `Search…` is wrong because it doesn’t name the scope." (https://vercel.com/geist/command-menu) "`<CommandMenu.Group heading>` is Title Case, 1–2 words (`Actions`, `Recent`)." (https://vercel.com/geist/command-menu) Ours: groups are plural nouns in sentence case (*Agents*, *Go to*), one or two words. Items are names, or verb and noun for a creation page (*New Agent*), because the dialog goes to places. The placeholder names what is searched, never a bare "Search". No match quotes the query.
|
|
18
18
|
* @access "Use `aria-live="polite"` on the result count so screen readers hear how the list narrows as the user types." (https://vercel.com/geist/command-menu) "Up/Down arrows move highlight, Enter activates, Escape closes. Backspace at an empty input pops the page stack." (https://vercel.com/geist/command-menu) "Display each item’s `keybind` as a `Kbd` slot so the shortcut is discoverable to sighted users and announced as a label to screen readers." (https://vercel.com/geist/command-menu) Ours: a dialog with a screen-reader `title` and `description`, both required; the *Esc* key is a button named by `closeLabel`, which is required; the field is a combobox over a listbox; the highlighted item is `aria-selected`. A polite live region reads `resultCount` as the list narrows, and it is required. `CommandInput` requires its `placeholder`, `CommandGroup` its `heading` and `CommandItem` its `onSelect`, so no field, group or row is left unnamed or inert; a row with no group stands outside a `CommandGroup`. A shortcut is a `CommandShortcut`, drawn as `kbd` elements. With no pages there is no stack for Backspace to pop.
|
|
19
19
|
*/
|
|
@@ -21,7 +21,7 @@ function Command({ className, children, resultCount, ...props }) {
|
|
|
21
21
|
* @family Navigation
|
|
22
22
|
* @when "Use CommandMenu for a global, keyboard-first command palette that finds resources and runs actions across the app." (https://vercel.com/geist/command-menu) Ours: finding anything across the product and going there: an Agent, a customer, a page, a creation page (*New Agent*). Opened by ⌘K or the sidebar's Find. It goes to places and never runs a command.
|
|
23
23
|
* @instead "For a menu opened from a visible trigger on a single resource, use `Menu`; for right-click on a row, use `ContextMenu`." (https://vercel.com/geist/command-menu) "Group items into pages (`Projects`, `Team Settings`) when a single flat list would exceed roughly 30 items or span multiple resource types." (https://vercel.com/geist/command-menu) Ours: those are `DropdownMenu` and `ContextMenu`. One record's commands are its `ActionMenu`. Search inside one collection is `CollectionSearch`. Choosing the page's scope is `ScopeSwitcher`. `CommandDialog` has no pages: its list is groups.
|
|
24
|
-
* @behaviour "Bind `⌘K` on macOS and `Ctrl+K` elsewhere. Don’t reuse the binding for any in-page filter input; it’s a global shortcut." (https://vercel.com/geist/command-menu) "Open into the root page; preserve the search query when navigating back from a sub-page so the user’s typing isn’t lost." (https://vercel.com/geist/command-menu) "Trap focus inside the overlay while it’s open and return focus to the previously active element on close." (https://vercel.com/geist/command-menu) "Show a recent or default item set when the input is empty so the menu is useful before typing." (https://vercel.com/geist/command-menu) Ours: a solid surface, never glass; opens instantly, 640 px wide and 15% down the window; on a phone it is a bottom sheet, 640 px high with 8 px top corners and the list filling it. The input row stands above the list with a line under it, the field in large type with no icon and an *Esc* key at its end that closes the dialog and is the next stop after the field on Tab; the list scrolls past 436 px. The first row is highlighted on open. No match says so. Every row is 36 px with the pointer cursor, a group's heading is a muted 36 px row, a divider bleeds across the list. A row's shortcut is a `CommandShortcut` and a word or icon at its end is a `CommandSuffix`. Colour carries nothing: the highlighted row is a faint neutral wash with its text unchanged, group headings, suffixes and the empty line are muted, and no row, key or divider takes a hue.
|
|
24
|
+
* @behaviour "Bind `⌘K` on macOS and `Ctrl+K` elsewhere. Don’t reuse the binding for any in-page filter input; it’s a global shortcut." (https://vercel.com/geist/command-menu) "Open into the root page; preserve the search query when navigating back from a sub-page so the user’s typing isn’t lost." (https://vercel.com/geist/command-menu) "Trap focus inside the overlay while it’s open and return focus to the previously active element on close." (https://vercel.com/geist/command-menu) "Show a recent or default item set when the input is empty so the menu is useful before typing." (https://vercel.com/geist/command-menu) Ours: a solid surface, never glass; opens instantly, 640 px wide and 15% down the window; on a phone it is a bottom sheet, 640 px high with 8 px top corners and the list filling it. The input row stands above the list with a line under it, the field in large type with no icon and an *Esc* key at its end that closes the dialog and is the next stop after the field on Tab; the list scrolls past 436 px. The first row is highlighted on open. No match says so. Every row is 36 px with the pointer cursor, a group's heading is a muted 36 px row, a divider bleeds across the list. A row's shortcut is a `CommandShortcut` and a word or icon at its end is a `CommandSuffix`. Colour carries nothing: the highlighted row is a faint neutral wash with its text unchanged, group headings, suffixes and the empty line are muted, and no row, key or divider takes a hue. `CommandDialog` draws `Command` itself, so a product never mounts one; its parts are `CommandInput`, `CommandList`, `CommandEmpty`, `CommandGroup`, `CommandItem` and `CommandShortcut` (a `Kbd`).
|
|
25
25
|
* @words "`<CommandMenu.Item>` children are Title Case verb phrases (`Deploy Project`, `Invite Team Member`). Avoid navigation phrasing like `Go to project page`; CommandMenu commands act, not browse." (https://vercel.com/geist/command-menu) "`CommandMenuPage.label` is Title Case and names the scope (`Projects`, `Team Settings`)." (https://vercel.com/geist/command-menu) "`CommandMenuPage.placeholder` is sentence case, action-oriented, and ends with `…` (`Search projects…`, `Type a command or search…`). Bare `Search…` is wrong because it doesn’t name the scope." (https://vercel.com/geist/command-menu) "`<CommandMenu.Group heading>` is Title Case, 1–2 words (`Actions`, `Recent`)." (https://vercel.com/geist/command-menu) Ours: groups are plural nouns in sentence case (*Agents*, *Go to*), one or two words. Items are names, or verb and noun for a creation page (*New Agent*), because the dialog goes to places. The placeholder names what is searched, never a bare "Search". No match quotes the query.
|
|
26
26
|
* @access "Use `aria-live="polite"` on the result count so screen readers hear how the list narrows as the user types." (https://vercel.com/geist/command-menu) "Up/Down arrows move highlight, Enter activates, Escape closes. Backspace at an empty input pops the page stack." (https://vercel.com/geist/command-menu) "Display each item’s `keybind` as a `Kbd` slot so the shortcut is discoverable to sighted users and announced as a label to screen readers." (https://vercel.com/geist/command-menu) Ours: a dialog with a screen-reader `title` and `description`, both required; the *Esc* key is a button named by `closeLabel`, which is required; the field is a combobox over a listbox; the highlighted item is `aria-selected`. A polite live region reads `resultCount` as the list narrows, and it is required. `CommandInput` requires its `placeholder`, `CommandGroup` its `heading` and `CommandItem` its `onSelect`, so no field, group or row is left unnamed or inert; a row with no group stands outside a `CommandGroup`. A shortcut is a `CommandShortcut`, drawn as `kbd` elements. With no pages there is no stack for Backspace to pop.
|
|
27
27
|
*/
|
|
@@ -16,13 +16,36 @@ export type CompanyCardLabels = {
|
|
|
16
16
|
*
|
|
17
17
|
* @family Other
|
|
18
18
|
* @when Sign-up, where a person watches their company's card being made, and the website, which
|
|
19
|
-
* shows one being issued.
|
|
19
|
+
* shows one being issued. Beside a wide form it fills in as the form is typed; on a phone the form
|
|
20
|
+
* keeps the screen, and the card appears once it is issued. The account's Profile shows the person
|
|
21
|
+
* the same card. The Partner invitation panel opens with its card, the `partner` edition, on the
|
|
22
|
+
* identity plane, as the invitation it shares, and the Partner's email invitation dialog shows the
|
|
23
|
+
* card the invited company will be issued. Arriving through a Partner's referral link, the sign-up
|
|
24
|
+
* plane stands the Partner's card behind the one being made, leaning back, so the person's own
|
|
25
|
+
* card stays in front and whole.
|
|
20
26
|
* @instead A company's facts are `SettingsFactsSection`. A company in a row is its `IdentityMark`.
|
|
21
|
-
* @behaviour
|
|
22
|
-
*
|
|
27
|
+
* @behaviour One object of the ID-1 proportion (856 by 540), dark by nature in every theme. Its
|
|
28
|
+
* top line carries the wordmark and, once Sofia has found it on the company's site, the company's
|
|
29
|
+
* own logo after a hairline, both stamped in `{colors.identity-white}` as one ink; a company with
|
|
30
|
+
* no logo found has the wordmark alone. Below are the holder's name and the company's domain. No
|
|
31
|
+
* Agent stands on it, and nothing sits in the engraving: a guilloché engraving in
|
|
32
|
+
* `{colors.identity-white}` at 10%. It fills in as the form is typed and answers the pointer. It
|
|
33
|
+
* is the one object besides an Agent that moves on its own, once: when it first appears, and
|
|
34
|
+
* again when the account is asked for and it is issued, it turns in the light in 2.2 s, leaning
|
|
35
|
+
* one way and back while the light crosses it from corner to corner, so a person sees it is a card
|
|
36
|
+
* that answers the hand, and then it is still. The foil wakes as the pointer comes within one card
|
|
37
|
+
* width and eases toward it; a pointer that near ends the turn, and a pointer anywhere else on the
|
|
38
|
+
* page moves nothing. Where the browser has WebGPU, its foil is vgpu's holographic card shader:
|
|
39
|
+
* matte graphite (`{colors.card-graphite}`, its own tone, so the card keeps its look whatever the
|
|
40
|
+
* heights do) whose etched contours diffract the pointer's light, turning toward it by at most 9°.
|
|
41
|
+
* The diffraction and its pearlescent wash fall in pure bands of the identity hues, never a colour
|
|
42
|
+
* between two of them: a company's card takes the cool half, cobalto, azzurro and verde, and a
|
|
43
|
+
* Partner's the warm half, giallo, arancio and rosso. Without WebGPU the engraving catches the
|
|
44
|
+
* light as flat, hard-edged stripes of the same hues. Under reduced motion the card keeps still
|
|
45
|
+
* and the light still finds the foil.
|
|
23
46
|
* @words Every word it shows is a prop from the product's catalogue.
|
|
24
|
-
* @access Hidden from assistive technology and holds nothing interactive; the form
|
|
25
|
-
*
|
|
47
|
+
* @access Hidden from assistive technology and holds nothing interactive; the form owns every word
|
|
48
|
+
* the card repeats.
|
|
26
49
|
*/
|
|
27
50
|
export declare function CompanyCard({ name, domain, edition, issued, labels, logo, sweepInView, }: {
|
|
28
51
|
name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"company-card.d.ts","sourceRoot":"","sources":["../../src/components/company-card.tsx"],"names":[],"mappings":"AASA,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,SAAS,CAAC;AAEvD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC;AAqBF
|
|
1
|
+
{"version":3,"file":"company-card.d.ts","sourceRoot":"","sources":["../../src/components/company-card.tsx"],"names":[],"mappings":"AASA,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,SAAS,CAAC;AAEvD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC;AAqBF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,MAAM,EACN,OAAO,EACP,MAAM,EACN,MAAM,EACN,IAAI,EACJ,WAAmB,GACpB,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,kBAAkB,CAAC;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,mFAAmF;IACnF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,+BAsSA"}
|
|
@@ -31,13 +31,36 @@ function reason(cause) {
|
|
|
31
31
|
*
|
|
32
32
|
* @family Other
|
|
33
33
|
* @when Sign-up, where a person watches their company's card being made, and the website, which
|
|
34
|
-
* shows one being issued.
|
|
34
|
+
* shows one being issued. Beside a wide form it fills in as the form is typed; on a phone the form
|
|
35
|
+
* keeps the screen, and the card appears once it is issued. The account's Profile shows the person
|
|
36
|
+
* the same card. The Partner invitation panel opens with its card, the `partner` edition, on the
|
|
37
|
+
* identity plane, as the invitation it shares, and the Partner's email invitation dialog shows the
|
|
38
|
+
* card the invited company will be issued. Arriving through a Partner's referral link, the sign-up
|
|
39
|
+
* plane stands the Partner's card behind the one being made, leaning back, so the person's own
|
|
40
|
+
* card stays in front and whole.
|
|
35
41
|
* @instead A company's facts are `SettingsFactsSection`. A company in a row is its `IdentityMark`.
|
|
36
|
-
* @behaviour
|
|
37
|
-
*
|
|
42
|
+
* @behaviour One object of the ID-1 proportion (856 by 540), dark by nature in every theme. Its
|
|
43
|
+
* top line carries the wordmark and, once Sofia has found it on the company's site, the company's
|
|
44
|
+
* own logo after a hairline, both stamped in `{colors.identity-white}` as one ink; a company with
|
|
45
|
+
* no logo found has the wordmark alone. Below are the holder's name and the company's domain. No
|
|
46
|
+
* Agent stands on it, and nothing sits in the engraving: a guilloché engraving in
|
|
47
|
+
* `{colors.identity-white}` at 10%. It fills in as the form is typed and answers the pointer. It
|
|
48
|
+
* is the one object besides an Agent that moves on its own, once: when it first appears, and
|
|
49
|
+
* again when the account is asked for and it is issued, it turns in the light in 2.2 s, leaning
|
|
50
|
+
* one way and back while the light crosses it from corner to corner, so a person sees it is a card
|
|
51
|
+
* that answers the hand, and then it is still. The foil wakes as the pointer comes within one card
|
|
52
|
+
* width and eases toward it; a pointer that near ends the turn, and a pointer anywhere else on the
|
|
53
|
+
* page moves nothing. Where the browser has WebGPU, its foil is vgpu's holographic card shader:
|
|
54
|
+
* matte graphite (`{colors.card-graphite}`, its own tone, so the card keeps its look whatever the
|
|
55
|
+
* heights do) whose etched contours diffract the pointer's light, turning toward it by at most 9°.
|
|
56
|
+
* The diffraction and its pearlescent wash fall in pure bands of the identity hues, never a colour
|
|
57
|
+
* between two of them: a company's card takes the cool half, cobalto, azzurro and verde, and a
|
|
58
|
+
* Partner's the warm half, giallo, arancio and rosso. Without WebGPU the engraving catches the
|
|
59
|
+
* light as flat, hard-edged stripes of the same hues. Under reduced motion the card keeps still
|
|
60
|
+
* and the light still finds the foil.
|
|
38
61
|
* @words Every word it shows is a prop from the product's catalogue.
|
|
39
|
-
* @access Hidden from assistive technology and holds nothing interactive; the form
|
|
40
|
-
*
|
|
62
|
+
* @access Hidden from assistive technology and holds nothing interactive; the form owns every word
|
|
63
|
+
* the card repeats.
|
|
41
64
|
*/
|
|
42
65
|
export function CompanyCard({ name, domain, edition, issued, labels, logo, sweepInView = false, }) {
|
|
43
66
|
// A CSS `url(#…)` reference cannot carry the punctuation React puts in an id.
|
|
@@ -2,6 +2,7 @@ import { type ReactNode } from "react";
|
|
|
2
2
|
import { type ResolvedMessage } from "./product-message.js";
|
|
3
3
|
export type ConfirmDialogProps = {
|
|
4
4
|
open: boolean;
|
|
5
|
+
/** Runs the operation. The caller owns `open` and closes the dialog after the operation settles, or keeps it open with `error` set. */
|
|
5
6
|
onConfirm: () => void;
|
|
6
7
|
onCancel: () => void;
|
|
7
8
|
/** Names the record, as a statement: "Remove pec@acme.it". Never a question. */
|
|
@@ -41,8 +42,8 @@ export type ConfirmDialogProps = {
|
|
|
41
42
|
* A consequence confirmed before it happens, in a blocking alert dialog.
|
|
42
43
|
*
|
|
43
44
|
* @family Compositions
|
|
44
|
-
* @when "Reach for this over `Modal` when the action is destructive and warrants friction: delete, rotate, revoke, disconnect, downgrade, disable a security setting. The typed gate forces deliberate intent." (https://vercel.com/geist/destructive-action-modal) "Use it for reversible destructive actions too, when the consequence is serious enough to warrant a pause — disabling deployment protection, revoking a shared token. Keep the typed gate; drop `irreversibleDescription`." (https://vercel.com/geist/destructive-action-modal) "For high-stakes destructive actions (delete production resource, rotate signing key, downgrade plan), gate the primary button on a typed match of the resource name." (https://vercel.com/geist/modal) Ours: `ConfirmDialog` is Geist's DestructiveActionModal: remove a mailbox, delete an Agent, with `verify` as the typed gate.
|
|
45
|
-
* @instead "Don't use for routine confirmations (save draft, discard changes, close without saving). The typed gate reads as melodrama when the stakes are low — use a plain `Modal` instead." (https://vercel.com/geist/destructive-action-modal) "Confirm destructive actions in a Modal. `Drawer` and `Sheet` don’t fully dim the page, so they read as too soft for a delete or revoke." (https://vercel.com/geist/modal) Ours: an action that can be undone runs at once and offers its undo in a toast; a form of a few fields is a `FormDialog`; a choice from a catalogue is a `CatalogDrawer`.
|
|
45
|
+
* @when "Reach for this over `Modal` when the action is destructive and warrants friction: delete, rotate, revoke, disconnect, downgrade, disable a security setting. The typed gate forces deliberate intent." (https://vercel.com/geist/destructive-action-modal) "Use it for reversible destructive actions too, when the consequence is serious enough to warrant a pause — disabling deployment protection, revoking a shared token. Keep the typed gate; drop `irreversibleDescription`." (https://vercel.com/geist/destructive-action-modal) "For high-stakes destructive actions (delete production resource, rotate signing key, downgrade plan), gate the primary button on a typed match of the resource name." (https://vercel.com/geist/modal) Ours: `ConfirmDialog` is Geist's DestructiveActionModal: remove a mailbox, delete an Agent, with `verify` as the typed gate. It asks for the record's name before the confirm enables on a high-stakes action (delete, rotate, revoke, disconnect, downgrade, a protection switched off), even a reversible one; `irreversible` names what cannot be undone and is left out when the action can be reversed.
|
|
46
|
+
* @instead "Don't use for routine confirmations (save draft, discard changes, close without saving). The typed gate reads as melodrama when the stakes are low — use a plain `Modal` instead." (https://vercel.com/geist/destructive-action-modal) "Confirm destructive actions in a Modal. `Drawer` and `Sheet` don’t fully dim the page, so they read as too soft for a delete or revoke." (https://vercel.com/geist/modal) Ours: a routine confirmation (discard a draft) takes neither `verify` nor `irreversible`; an action that can be undone runs at once and offers its undo in a toast; a form of a few fields is a `FormDialog`; a choice from a catalogue is a `CatalogDrawer`.
|
|
46
47
|
* @behaviour "The verification input gets focus on open so the user can start typing immediately. Submit stays disabled until the value matches `verificationPhrase` exactly." (https://vercel.com/geist/destructive-action-modal) "Enter submits only when the gate is open; it's a no-op otherwise. Cancel, outside-click, and Escape all dismiss." (https://vercel.com/geist/destructive-action-modal) "`loading` disables both buttons. The caller owns `open` — do not self-dismiss from `onConfirm`. Close the modal after the API settles (success or error), or keep it open on error so the user can retry." (https://vercel.com/geist/destructive-action-modal) "Default focus to `Cancel` on any destructive Modal. Enter must never trigger the destructive action without a typed confirmation." (https://vercel.com/geist/modal) "Allow Escape and outside-click to dismiss non-destructive Modals; gate dismissal on destructive ones with unsaved input." (https://vercel.com/geist/modal) Ours: `title`, `description`, `confirmLabel` and `cancelLabel` are required; `irreversible` and `verify` are optional, and the absence of `irreversible` is what marks the action reversible. Geist's `irreversibleDescription` is `irreversible`, `verificationPhrase` and `verificationLabel` are `verify.phrase` and `verify.prompt`, and `error` is the catalogue's message. 480 px wide over a scrim. The title and the description, then the body in a 24 px column: the `irreversible` note, the `verify` field, the failure under it. `irreversible` is a flat red note with a red mark and red words, not a band over the footer; besides it the only red is the failure and the enabled destructive confirm. While `loading` the field turns read-only and keeps focus, Escape does not close it, and the confirm says `confirmPendingLabel`, which falls back to the confirm's label. A press outside does not close it, so a stray click never discards a typed phrase or an action in flight; Escape and Cancel do. The footer is a bar that stays at the bottom while a tall confirmation scrolls, and a row on a phone too.
|
|
47
48
|
* @words "`title` is Title Case, `Verb + Noun`, a statement — never a question. `Delete Project`, not `Delete this project?`." (https://vercel.com/geist/destructive-action-modal) "`description` is sentence case, names the consequence, and interpolates the specific resource when relevant. `<b>my-project</b> and all its deployments will be permanently deleted.` reads stronger than `This project and all its deployments will be deleted.`." (https://vercel.com/geist/destructive-action-modal) "`confirmLabel` matches the title 1:1. Never generic (`Confirm`, `OK`, `Continue`), never a bare verb (`Delete`)." (https://vercel.com/geist/destructive-action-modal) "`cancelLabel` defaults to `Cancel`. Override when Cancel is ambiguous, such as `Keep Turn Running` when the primary action is itself a cancellation." (https://vercel.com/geist/destructive-action-modal) "`verificationPhrase`: for entity deletes, type the **resource name itself** (`my-project`) and pair with `verificationLabel="project name"` so the prompt reads `To confirm, type the project name "my-project"`. That's the canonical signal that the user knows which thing they're acting on. Fall back to a lowercase verb phrase (`disable vercel authentication`) only when there's no entity to name." (https://vercel.com/geist/destructive-action-modal) "`irreversibleDescription` names the specific action and resource and ends with `cannot be undone.` — `Deleting my-project cannot be undone.` rather than the generic `This cannot be undone.`. Omit the prop entirely for reversible actions; the prop's absence is the signal, not a falsy value." (https://vercel.com/geist/destructive-action-modal) "`error` surfaces the API failure verbatim in Vercel voice: `Couldn't save settings. Try again.`. Never dump a raw error object." (https://vercel.com/geist/destructive-action-modal) "Pair the post-confirm success toast verb 1:1 with the primary button: `Delete Project` button, `Project deleted` toast. Never `Project removed`." (https://vercel.com/geist/destructive-action-modal) "Close irreversible bodies with `This cannot be undone.`; close cascade-only bodies with `Some effects cannot be undone.`. Don’t claim full irreversibility for a partial cascade." (https://vercel.com/geist/modal) Ours: the title is sentence case and names the record, "Remove pec@acme.it", and the confirm repeats the verb and the noun, "Remove mailbox", so the two share a verb and not every word; its success toast uses the same verb ("Mailbox removed"). The description names the record in medium weight.
|
|
48
49
|
* @access "The verification input is associated with its prompt via `aria-labelledby` + `htmlFor`. Screen readers announce the full prompt (`To confirm, type "delete my-project"`) on focus." (https://vercel.com/geist/destructive-action-modal) "The Warning icon in the irreversibility band is `aria-hidden`; the sentence carries the meaning so nothing is announced twice." (https://vercel.com/geist/destructive-action-modal) "Focus stays inside the modal across an `error` transition so the user can retry without losing context. After success, return focus to the trigger." (https://vercel.com/geist/destructive-action-modal) "Set `aria-labelledby` to the `Modal.Title` id so screen readers announce the title on open." (https://vercel.com/geist/modal) "Keep the Cancel button literally `Cancel` so screen-reader users hear a stable dismissal label across destructive flows." (https://vercel.com/geist/modal) Ours: `role="alertdialog"` named by its title and described by its consequence; the note is `role="note"` with its icon hidden. Focus starts on Cancel, or in the field with `verify`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"confirm-dialog.d.ts","sourceRoot":"","sources":["../../src/components/confirm-dialog.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAA2C,MAAM,OAAO,CAAC;AAgBhF,OAAO,EAAmB,KAAK,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAErF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAC;IACd,uBAAuB;IACvB,WAAW,EAAE,SAAS,CAAC;IACvB,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC;IACrB,gGAAgG;IAChG,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,MAAM,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,KAAK,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;CAChC,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,KAAK,EACL,WAAW,EACX,YAAY,EACZ,mBAAmB,EACnB,WAAW,EACX,WAAmB,EACnB,OAAe,EACf,MAAM,EACN,YAAY,EACZ,KAAK,GACN,EAAE,kBAAkB,+BAgCpB"}
|
|
1
|
+
{"version":3,"file":"confirm-dialog.d.ts","sourceRoot":"","sources":["../../src/components/confirm-dialog.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAA2C,MAAM,OAAO,CAAC;AAgBhF,OAAO,EAAmB,KAAK,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAErF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,uIAAuI;IACvI,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAC;IACd,uBAAuB;IACvB,WAAW,EAAE,SAAS,CAAC;IACvB,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC;IACrB,gGAAgG;IAChG,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,MAAM,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,KAAK,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;CAChC,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,KAAK,EACL,WAAW,EACX,YAAY,EACZ,mBAAmB,EACnB,WAAW,EACX,WAAmB,EACnB,OAAe,EACf,MAAM,EACN,YAAY,EACZ,KAAK,GACN,EAAE,kBAAkB,+BAgCpB"}
|
|
@@ -12,8 +12,8 @@ import { bodyBeyondTitle } from "./product-message.js";
|
|
|
12
12
|
* A consequence confirmed before it happens, in a blocking alert dialog.
|
|
13
13
|
*
|
|
14
14
|
* @family Compositions
|
|
15
|
-
* @when "Reach for this over `Modal` when the action is destructive and warrants friction: delete, rotate, revoke, disconnect, downgrade, disable a security setting. The typed gate forces deliberate intent." (https://vercel.com/geist/destructive-action-modal) "Use it for reversible destructive actions too, when the consequence is serious enough to warrant a pause — disabling deployment protection, revoking a shared token. Keep the typed gate; drop `irreversibleDescription`." (https://vercel.com/geist/destructive-action-modal) "For high-stakes destructive actions (delete production resource, rotate signing key, downgrade plan), gate the primary button on a typed match of the resource name." (https://vercel.com/geist/modal) Ours: `ConfirmDialog` is Geist's DestructiveActionModal: remove a mailbox, delete an Agent, with `verify` as the typed gate.
|
|
16
|
-
* @instead "Don't use for routine confirmations (save draft, discard changes, close without saving). The typed gate reads as melodrama when the stakes are low — use a plain `Modal` instead." (https://vercel.com/geist/destructive-action-modal) "Confirm destructive actions in a Modal. `Drawer` and `Sheet` don’t fully dim the page, so they read as too soft for a delete or revoke." (https://vercel.com/geist/modal) Ours: an action that can be undone runs at once and offers its undo in a toast; a form of a few fields is a `FormDialog`; a choice from a catalogue is a `CatalogDrawer`.
|
|
15
|
+
* @when "Reach for this over `Modal` when the action is destructive and warrants friction: delete, rotate, revoke, disconnect, downgrade, disable a security setting. The typed gate forces deliberate intent." (https://vercel.com/geist/destructive-action-modal) "Use it for reversible destructive actions too, when the consequence is serious enough to warrant a pause — disabling deployment protection, revoking a shared token. Keep the typed gate; drop `irreversibleDescription`." (https://vercel.com/geist/destructive-action-modal) "For high-stakes destructive actions (delete production resource, rotate signing key, downgrade plan), gate the primary button on a typed match of the resource name." (https://vercel.com/geist/modal) Ours: `ConfirmDialog` is Geist's DestructiveActionModal: remove a mailbox, delete an Agent, with `verify` as the typed gate. It asks for the record's name before the confirm enables on a high-stakes action (delete, rotate, revoke, disconnect, downgrade, a protection switched off), even a reversible one; `irreversible` names what cannot be undone and is left out when the action can be reversed.
|
|
16
|
+
* @instead "Don't use for routine confirmations (save draft, discard changes, close without saving). The typed gate reads as melodrama when the stakes are low — use a plain `Modal` instead." (https://vercel.com/geist/destructive-action-modal) "Confirm destructive actions in a Modal. `Drawer` and `Sheet` don’t fully dim the page, so they read as too soft for a delete or revoke." (https://vercel.com/geist/modal) Ours: a routine confirmation (discard a draft) takes neither `verify` nor `irreversible`; an action that can be undone runs at once and offers its undo in a toast; a form of a few fields is a `FormDialog`; a choice from a catalogue is a `CatalogDrawer`.
|
|
17
17
|
* @behaviour "The verification input gets focus on open so the user can start typing immediately. Submit stays disabled until the value matches `verificationPhrase` exactly." (https://vercel.com/geist/destructive-action-modal) "Enter submits only when the gate is open; it's a no-op otherwise. Cancel, outside-click, and Escape all dismiss." (https://vercel.com/geist/destructive-action-modal) "`loading` disables both buttons. The caller owns `open` — do not self-dismiss from `onConfirm`. Close the modal after the API settles (success or error), or keep it open on error so the user can retry." (https://vercel.com/geist/destructive-action-modal) "Default focus to `Cancel` on any destructive Modal. Enter must never trigger the destructive action without a typed confirmation." (https://vercel.com/geist/modal) "Allow Escape and outside-click to dismiss non-destructive Modals; gate dismissal on destructive ones with unsaved input." (https://vercel.com/geist/modal) Ours: `title`, `description`, `confirmLabel` and `cancelLabel` are required; `irreversible` and `verify` are optional, and the absence of `irreversible` is what marks the action reversible. Geist's `irreversibleDescription` is `irreversible`, `verificationPhrase` and `verificationLabel` are `verify.phrase` and `verify.prompt`, and `error` is the catalogue's message. 480 px wide over a scrim. The title and the description, then the body in a 24 px column: the `irreversible` note, the `verify` field, the failure under it. `irreversible` is a flat red note with a red mark and red words, not a band over the footer; besides it the only red is the failure and the enabled destructive confirm. While `loading` the field turns read-only and keeps focus, Escape does not close it, and the confirm says `confirmPendingLabel`, which falls back to the confirm's label. A press outside does not close it, so a stray click never discards a typed phrase or an action in flight; Escape and Cancel do. The footer is a bar that stays at the bottom while a tall confirmation scrolls, and a row on a phone too.
|
|
18
18
|
* @words "`title` is Title Case, `Verb + Noun`, a statement — never a question. `Delete Project`, not `Delete this project?`." (https://vercel.com/geist/destructive-action-modal) "`description` is sentence case, names the consequence, and interpolates the specific resource when relevant. `<b>my-project</b> and all its deployments will be permanently deleted.` reads stronger than `This project and all its deployments will be deleted.`." (https://vercel.com/geist/destructive-action-modal) "`confirmLabel` matches the title 1:1. Never generic (`Confirm`, `OK`, `Continue`), never a bare verb (`Delete`)." (https://vercel.com/geist/destructive-action-modal) "`cancelLabel` defaults to `Cancel`. Override when Cancel is ambiguous, such as `Keep Turn Running` when the primary action is itself a cancellation." (https://vercel.com/geist/destructive-action-modal) "`verificationPhrase`: for entity deletes, type the **resource name itself** (`my-project`) and pair with `verificationLabel="project name"` so the prompt reads `To confirm, type the project name "my-project"`. That's the canonical signal that the user knows which thing they're acting on. Fall back to a lowercase verb phrase (`disable vercel authentication`) only when there's no entity to name." (https://vercel.com/geist/destructive-action-modal) "`irreversibleDescription` names the specific action and resource and ends with `cannot be undone.` — `Deleting my-project cannot be undone.` rather than the generic `This cannot be undone.`. Omit the prop entirely for reversible actions; the prop's absence is the signal, not a falsy value." (https://vercel.com/geist/destructive-action-modal) "`error` surfaces the API failure verbatim in Vercel voice: `Couldn't save settings. Try again.`. Never dump a raw error object." (https://vercel.com/geist/destructive-action-modal) "Pair the post-confirm success toast verb 1:1 with the primary button: `Delete Project` button, `Project deleted` toast. Never `Project removed`." (https://vercel.com/geist/destructive-action-modal) "Close irreversible bodies with `This cannot be undone.`; close cascade-only bodies with `Some effects cannot be undone.`. Don’t claim full irreversibility for a partial cascade." (https://vercel.com/geist/modal) Ours: the title is sentence case and names the record, "Remove pec@acme.it", and the confirm repeats the verb and the noun, "Remove mailbox", so the two share a verb and not every word; its success toast uses the same verb ("Mailbox removed"). The description names the record in medium weight.
|
|
19
19
|
* @access "The verification input is associated with its prompt via `aria-labelledby` + `htmlFor`. Screen readers announce the full prompt (`To confirm, type "delete my-project"`) on focus." (https://vercel.com/geist/destructive-action-modal) "The Warning icon in the irreversibility band is `aria-hidden`; the sentence carries the meaning so nothing is announced twice." (https://vercel.com/geist/destructive-action-modal) "Focus stays inside the modal across an `error` transition so the user can retry without losing context. After success, return focus to the trigger." (https://vercel.com/geist/destructive-action-modal) "Set `aria-labelledby` to the `Modal.Title` id so screen readers announce the title on open." (https://vercel.com/geist/modal) "Keep the Cancel button literally `Cancel` so screen-reader users hear a stable dismissal label across destructive flows." (https://vercel.com/geist/modal) Ours: `role="alertdialog"` named by its title and described by its consequence; the note is `role="note"` with its icon hidden. Focus starts on Cancel, or in the field with `verify`.
|
|
@@ -12,9 +12,9 @@ export type CopyButtonProps = {
|
|
|
12
12
|
*
|
|
13
13
|
* @family Actions
|
|
14
14
|
* @when An exact value someone will paste elsewhere: an Agent ID, a server address, a command. A shell prompt shown before a command stays outside the copied value.
|
|
15
|
-
* @instead Several lines of code are a `CodeBlock`. Ordinary prose never gets copy chrome. A secret needs its reveal policy first.
|
|
15
|
+
* @instead Several lines of code are a `CodeBlock`. Ordinary prose never gets copy chrome. A secret needs its reveal policy first. A shown value that is copied is a `TextWithCopyButton`, which binds the value to this button.
|
|
16
16
|
* @behaviour "A button that copies a given string to the clipboard and provides feedback when copied." (https://vercel.com/geist/copy-button)
|
|
17
|
-
* Ours: copies the full underlying value even when the shown one is shortened. The copy mark fades into the check for about a second, and only after the clipboard confirms; no colour changes. A failure shows the alert mark and the button stays for a retry. The standalone `icon` button is outlined; `icon-sm` sits after a value and `icon-xs` inside a field, both without chrome. `copied` shows the check from outside for a parent that copies other text, and `onCopy` runs once the clipboard confirms. While the clipboard works a second press is ignored and the button looks as it did, with no held look.
|
|
17
|
+
* Ours: it is a `Button` over the existing clipboard behaviour, with the pending state and the announced result below, and adds no clipboard code of its own. It copies the full underlying value even when the shown one is shortened. The copy mark fades into the check for about a second, and only after the clipboard confirms; no colour changes. A failure shows the alert mark and the button stays for a retry. The standalone `icon` button is outlined; `icon-sm` sits after a value and `icon-xs` inside a field, both without chrome. `copied` shows the check from outside for a parent that copies other text, and `onCopy` runs once the clipboard confirms. While the clipboard works a second press is ignored and the button looks as it did, with no held look.
|
|
18
18
|
* @words Three catalogue strings: `copyLabel` names the target ("Copy Agent ID"), `copiedLabel` ("Copied"), `copyFailedLabel` ("Couldn't copy").
|
|
19
19
|
* @access `aria-label` is the copy label and does not change. The result is read once from a hidden `role="status"`.
|
|
20
20
|
*/
|
|
@@ -10,9 +10,9 @@ import { cn } from "../lib/utils.js";
|
|
|
10
10
|
*
|
|
11
11
|
* @family Actions
|
|
12
12
|
* @when An exact value someone will paste elsewhere: an Agent ID, a server address, a command. A shell prompt shown before a command stays outside the copied value.
|
|
13
|
-
* @instead Several lines of code are a `CodeBlock`. Ordinary prose never gets copy chrome. A secret needs its reveal policy first.
|
|
13
|
+
* @instead Several lines of code are a `CodeBlock`. Ordinary prose never gets copy chrome. A secret needs its reveal policy first. A shown value that is copied is a `TextWithCopyButton`, which binds the value to this button.
|
|
14
14
|
* @behaviour "A button that copies a given string to the clipboard and provides feedback when copied." (https://vercel.com/geist/copy-button)
|
|
15
|
-
* Ours: copies the full underlying value even when the shown one is shortened. The copy mark fades into the check for about a second, and only after the clipboard confirms; no colour changes. A failure shows the alert mark and the button stays for a retry. The standalone `icon` button is outlined; `icon-sm` sits after a value and `icon-xs` inside a field, both without chrome. `copied` shows the check from outside for a parent that copies other text, and `onCopy` runs once the clipboard confirms. While the clipboard works a second press is ignored and the button looks as it did, with no held look.
|
|
15
|
+
* Ours: it is a `Button` over the existing clipboard behaviour, with the pending state and the announced result below, and adds no clipboard code of its own. It copies the full underlying value even when the shown one is shortened. The copy mark fades into the check for about a second, and only after the clipboard confirms; no colour changes. A failure shows the alert mark and the button stays for a retry. The standalone `icon` button is outlined; `icon-sm` sits after a value and `icon-xs` inside a field, both without chrome. `copied` shows the check from outside for a parent that copies other text, and `onCopy` runs once the clipboard confirms. While the clipboard works a second press is ignored and the button looks as it did, with no held look.
|
|
16
16
|
* @words Three catalogue strings: `copyLabel` names the target ("Copy Agent ID"), `copiedLabel` ("Copied"), `copyFailedLabel` ("Couldn't copy").
|
|
17
17
|
* @access `aria-label` is the copy label and does not change. The result is read once from a hidden `role="status"`.
|
|
18
18
|
*/
|
|
@@ -226,7 +226,7 @@ export declare function columnMenuLabel<TData extends RowData, TValue extends Ce
|
|
|
226
226
|
* @instead “For a row of descriptive content paired with a single action (membership row, integration row), use `Entity` instead.” (https://vercel.com/geist/table)
|
|
227
227
|
* “For a key/value metadata block on a detail page, use `Description`, not a two-column table.” (https://vercel.com/geist/table)
|
|
228
228
|
* Ours: Geist's `Entity` is a `RecordList` row. A registry of entities whose columns `RecordList` cannot hold, more than three facts beside a filter bar the product owns, as Vercel's Deployments list, is this table with `rows="entities"`, which draws the same rows: headings for assistive technology only, 72 px rows, a `RecordIdentity` in the identity column. Its `Description` is `ObjectFacts`. A list on a page of its own is a `CollectionPage`. A descriptive list is `ItemGroup`.
|
|
229
|
-
* @behaviour Every column has a `header`; a column without one does not compile. The headings are always visible, medium weight in the cells' body grey,
|
|
229
|
+
* @behaviour Every column has a `header`; a column without one does not compile. The headings are always visible, medium weight in the cells' body grey, 48 px high, with 12 px of room under the labels and then the rule, so the first row starts at the rule like every other; rows are 40 px. Each column is as wide as its definition's `size`, in pixels, and the columns without one share the rest, so a table gives a size to every column but the one that takes the spare width; a value too long for its column ends in an ellipsis, whole in its title (a record's name carries its own), unless the column `wraps`; a column marked `identifier` holds ids or paths and is cut in the middle instead. The last column trails unless it `wraps` or is `centered`; a `centered` column's heading and values sit in the middle of it. Records are divided by a 1 px rule, none after the last. The first and last columns stand in from the card's edges by the card's spacing, so the first lines up with the title. Records of several kinds stand in one table under `group` headings (Vercel's Usage page: *Delivery network*, *Functions*): a heading row that spans the columns, in ink, medium text, 36 px high with the same rule under it, one per group in the order the groups first appear, never a second table; a heading is the group's name and carries no figure of its own. A row that opens a record takes `accent` on hover, and any row on focus within and while its menu is open; a row that opens nothing never reacts to hover. A selected row takes `muted`; headers and footers never highlight and carry no fill. A row never scrolls sideways: on a card narrower than its columns (the sized ones and 160 px for each without a size) the row keeps its name and its `primaryColumns`, and every other column leaves it, its value joining the one muted line under the name, joined by a middle dot and ending in an ellipsis (a `Tag` reads as its text there, and a `wraps` column's prose wraps the line whole), or `dropped` when its `compact` says so, as Vercel's lists read on a phone: no labels, no second line; an `optional` column's empty value is left out of the line. A table whose every column is in `primaryColumns`, a settings matrix, lays out by its content there instead, so the name wraps beside the columns. A document's table, such as a legal page's, is read whole instead: its columns take the `wraps` option, so their words wrap and the row grows, and it keeps its header row; in the compact layout every cell but the identity wraps between words. A bounded page's paging stands in the card's footer strip at its trailing edge, opposite `footer`, which stands at the leading edge: its `status` ("Page 2 of 7") before Previous and Next, which are the product's router links (`previousLink`, `nextLink`) when each page is its own address, and buttons otherwise; the one that leads nowhere stays, disabled. A note about the whole table is `footerNote`, in a strip of its own under that one: one muted line, an optional *Learn more* after it at the left and one secondary action at the right (Vercel's deployments list ends "Deployment retention is enabled. Learn more" with *View recently deleted*); it is the one place a table says a sentence. Colour is neutral: headings and cells in the body grey, no hue, except a status badge or a tone the cell itself carries.
|
|
230
230
|
* “When the underlying list is empty (filter cleared, never created), render `Empty State` outside the table rather than an empty `<Table.Body>`.” (https://vercel.com/geist/table)
|
|
231
231
|
* “After an async filter change, wrap the region in `aria-live="polite"` so screen readers announce the new state.” (https://vercel.com/geist/empty-state)
|
|
232
232
|
* Ours: empty sits outside the body, in a polite live region that stays in place so a filter that empties the table is announced.
|
|
@@ -238,7 +238,7 @@ export declare function columnMenuLabel<TData extends RowData, TValue extends Ce
|
|
|
238
238
|
* “Render `—` in cells where a value is unknown or not applicable. Don’t substitute `N/A`, `null`, or an empty string.” (https://vercel.com/geist/table)
|
|
239
239
|
* “Use the canonical short relative-time form in cells (`2m ago`, `5h ago`); switch to `Mar 14, 2026` past 7 days. See `Relative Time Card`.” (https://vercel.com/geist/table)
|
|
240
240
|
* “Pagination labels are `Previous` and `Next`. Page-count copy reads `Page 2 of 7` or `21–40 of 142` with an en-dash inside the range.” (https://vercel.com/geist/table)
|
|
241
|
-
* Ours: headings are sentence case nouns with their unit, "Cost (€)", "Tokens", where Geist writes Title Case. The words of a time and of Previous and Next are the product's catalogue, in both languages. The footer is a count or the paging; the summary row is a labelled total. Italian headings run a third longer and never wrap.
|
|
241
|
+
* Ours: headings are sentence case nouns with their unit, "Cost (€)", "Tokens", where Geist writes Title Case. The words of a time and of Previous and Next are the product's catalogue, in both languages. The footer is a count or the paging; totals and paging each stand in a footer zone of their own, the paging at the trailing edge; the summary row is a labelled total. Italian headings run a third longer and never wrap.
|
|
242
242
|
* @access A native table named by `tableLabel`, which is required; `th scope="col"`; the record's name is the row's one link. A sorted column's heading carries `aria-sort`. Ours: a missing value is a hidden "—" with screen-reader text, never blank.
|
|
243
243
|
*/
|
|
244
244
|
export declare function DataTable<TData extends RowData>(props: DataTableProps<TData>): React.JSX.Element;
|
|
@@ -183,7 +183,7 @@ function DefaultToolbar({ actions }) {
|
|
|
183
183
|
* @instead “For a row of descriptive content paired with a single action (membership row, integration row), use `Entity` instead.” (https://vercel.com/geist/table)
|
|
184
184
|
* “For a key/value metadata block on a detail page, use `Description`, not a two-column table.” (https://vercel.com/geist/table)
|
|
185
185
|
* Ours: Geist's `Entity` is a `RecordList` row. A registry of entities whose columns `RecordList` cannot hold, more than three facts beside a filter bar the product owns, as Vercel's Deployments list, is this table with `rows="entities"`, which draws the same rows: headings for assistive technology only, 72 px rows, a `RecordIdentity` in the identity column. Its `Description` is `ObjectFacts`. A list on a page of its own is a `CollectionPage`. A descriptive list is `ItemGroup`.
|
|
186
|
-
* @behaviour Every column has a `header`; a column without one does not compile. The headings are always visible, medium weight in the cells' body grey,
|
|
186
|
+
* @behaviour Every column has a `header`; a column without one does not compile. The headings are always visible, medium weight in the cells' body grey, 48 px high, with 12 px of room under the labels and then the rule, so the first row starts at the rule like every other; rows are 40 px. Each column is as wide as its definition's `size`, in pixels, and the columns without one share the rest, so a table gives a size to every column but the one that takes the spare width; a value too long for its column ends in an ellipsis, whole in its title (a record's name carries its own), unless the column `wraps`; a column marked `identifier` holds ids or paths and is cut in the middle instead. The last column trails unless it `wraps` or is `centered`; a `centered` column's heading and values sit in the middle of it. Records are divided by a 1 px rule, none after the last. The first and last columns stand in from the card's edges by the card's spacing, so the first lines up with the title. Records of several kinds stand in one table under `group` headings (Vercel's Usage page: *Delivery network*, *Functions*): a heading row that spans the columns, in ink, medium text, 36 px high with the same rule under it, one per group in the order the groups first appear, never a second table; a heading is the group's name and carries no figure of its own. A row that opens a record takes `accent` on hover, and any row on focus within and while its menu is open; a row that opens nothing never reacts to hover. A selected row takes `muted`; headers and footers never highlight and carry no fill. A row never scrolls sideways: on a card narrower than its columns (the sized ones and 160 px for each without a size) the row keeps its name and its `primaryColumns`, and every other column leaves it, its value joining the one muted line under the name, joined by a middle dot and ending in an ellipsis (a `Tag` reads as its text there, and a `wraps` column's prose wraps the line whole), or `dropped` when its `compact` says so, as Vercel's lists read on a phone: no labels, no second line; an `optional` column's empty value is left out of the line. A table whose every column is in `primaryColumns`, a settings matrix, lays out by its content there instead, so the name wraps beside the columns. A document's table, such as a legal page's, is read whole instead: its columns take the `wraps` option, so their words wrap and the row grows, and it keeps its header row; in the compact layout every cell but the identity wraps between words. A bounded page's paging stands in the card's footer strip at its trailing edge, opposite `footer`, which stands at the leading edge: its `status` ("Page 2 of 7") before Previous and Next, which are the product's router links (`previousLink`, `nextLink`) when each page is its own address, and buttons otherwise; the one that leads nowhere stays, disabled. A note about the whole table is `footerNote`, in a strip of its own under that one: one muted line, an optional *Learn more* after it at the left and one secondary action at the right (Vercel's deployments list ends "Deployment retention is enabled. Learn more" with *View recently deleted*); it is the one place a table says a sentence. Colour is neutral: headings and cells in the body grey, no hue, except a status badge or a tone the cell itself carries.
|
|
187
187
|
* “When the underlying list is empty (filter cleared, never created), render `Empty State` outside the table rather than an empty `<Table.Body>`.” (https://vercel.com/geist/table)
|
|
188
188
|
* “After an async filter change, wrap the region in `aria-live="polite"` so screen readers announce the new state.” (https://vercel.com/geist/empty-state)
|
|
189
189
|
* Ours: empty sits outside the body, in a polite live region that stays in place so a filter that empties the table is announced.
|
|
@@ -195,7 +195,7 @@ function DefaultToolbar({ actions }) {
|
|
|
195
195
|
* “Render `—` in cells where a value is unknown or not applicable. Don’t substitute `N/A`, `null`, or an empty string.” (https://vercel.com/geist/table)
|
|
196
196
|
* “Use the canonical short relative-time form in cells (`2m ago`, `5h ago`); switch to `Mar 14, 2026` past 7 days. See `Relative Time Card`.” (https://vercel.com/geist/table)
|
|
197
197
|
* “Pagination labels are `Previous` and `Next`. Page-count copy reads `Page 2 of 7` or `21–40 of 142` with an en-dash inside the range.” (https://vercel.com/geist/table)
|
|
198
|
-
* Ours: headings are sentence case nouns with their unit, "Cost (€)", "Tokens", where Geist writes Title Case. The words of a time and of Previous and Next are the product's catalogue, in both languages. The footer is a count or the paging; the summary row is a labelled total. Italian headings run a third longer and never wrap.
|
|
198
|
+
* Ours: headings are sentence case nouns with their unit, "Cost (€)", "Tokens", where Geist writes Title Case. The words of a time and of Previous and Next are the product's catalogue, in both languages. The footer is a count or the paging; totals and paging each stand in a footer zone of their own, the paging at the trailing edge; the summary row is a labelled total. Italian headings run a third longer and never wrap.
|
|
199
199
|
* @access A native table named by `tableLabel`, which is required; `th scope="col"`; the record's name is the row's one link. A sorted column's heading carries `aria-sort`. Ours: a missing value is a hidden "—" with screen-reader text, never blank.
|
|
200
200
|
*/
|
|
201
201
|
export function DataTable(props) {
|
|
@@ -5,7 +5,7 @@ type DrawerProps = Omit<DrawerPrimitive.Root.Props, "swipeDirection"> & {
|
|
|
5
5
|
showSwipeHandle?: boolean;
|
|
6
6
|
/** The panel's height in px, only when the default clips the primary action. */
|
|
7
7
|
height?: number;
|
|
8
|
-
/** Typed input a swipe, Escape or a press outside would lose: while `dirty` they are held back and `onDismissBlocked` runs. */
|
|
8
|
+
/** Typed input a swipe, Escape, the system back gesture or a press outside would lose: while `dirty` they are held back and `onDismissBlocked` runs. */
|
|
9
9
|
unsaved?: UnsavedGuard;
|
|
10
10
|
};
|
|
11
11
|
/**
|
|
@@ -18,12 +18,12 @@ type DrawerProps = Omit<DrawerPrimitive.Root.Props, "swipeDirection"> & {
|
|
|
18
18
|
* Ours: no screen calls it today.
|
|
19
19
|
* @instead "Don’t use Drawer to confirm destructive actions. The lack of a fully blocking dim weakens the severity signal that delete and revoke flows need; route to `Modal`." (https://vercel.com/geist/drawer)
|
|
20
20
|
* Ours: on a desktop a blocking job is `Dialog` and context beside a record is `Sheet`; a catalogue
|
|
21
|
-
*
|
|
21
|
+
* is `CatalogDrawer` and a setup in steps is `FormDrawer`; both are the right-side sheet, not this one.
|
|
22
22
|
* @behaviour "Tap-outside and swipe-down dismiss by default; preserve both unless the form has dirty input." (https://vercel.com/geist/drawer)
|
|
23
23
|
* "Use `verticalScroll` so the drawer body scrolls inside its frame instead of the page behind it." (https://vercel.com/geist/drawer)
|
|
24
24
|
* "Cap content height with `customHeight` only when the default height clips the primary action; the action and `Cancel` must stay above the fold." (https://vercel.com/geist/drawer)
|
|
25
|
-
* Ours: `unsaved.dirty` holds back the swipe, Escape and a press outside
|
|
26
|
-
* runs. The body always scrolls inside the frame, so there is no `verticalScroll`; `height` is
|
|
25
|
+
* Ours: `unsaved.dirty` holds back the swipe, Escape, the system back gesture and a press outside
|
|
26
|
+
* while input is typed, and `unsaved.onDismissBlocked` runs. The body always scrolls inside the frame, so there is no `verticalScroll`; `height` is
|
|
27
27
|
* Geist's `customHeight`. It rises from the bottom edge and follows the finger, is at most 80% of
|
|
28
28
|
* the viewport tall, and is all neutral. Nested drawers stack.
|
|
29
29
|
* @words "`DrawerTitle` is a Title Case statement that names the entity (`Deployment Details`, `Filter Logs`)." (https://vercel.com/geist/drawer)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drawer.d.ts","sourceRoot":"","sources":["../../src/components/drawer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAElE,OAAO,EAA4B,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAsBvF,KAAK,WAAW,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,EAAE,gBAAgB,CAAC,GAAG;IACtE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB
|
|
1
|
+
{"version":3,"file":"drawer.d.ts","sourceRoot":"","sources":["../../src/components/drawer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAElE,OAAO,EAA4B,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAsBvF,KAAK,WAAW,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,EAAE,gBAAgB,CAAC,GAAG;IACtE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wJAAwJ;IACxJ,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,iBAAS,MAAM,CAAC,EACd,KAAY,EACZ,eAAuB,EACvB,UAAU,EACV,MAAM,EACN,OAAO,EACP,YAAY,EACZ,GAAG,KAAK,EACT,EAAE,WAAW,qBAqBb;AAED,iBAAS,aAAa,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK,qBAEjE;AAED,iBAAS,YAAY,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,MAAM,CAAC,KAAK,qBAE/D;AAED,iBAAS,WAAW,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,KAAK,CAAC,KAAK,qBAE7D;AAED,iBAAS,aAAa,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,QAAQ,CAAC,KAAK,qBAW7E;AAED,iBAAS,iBAAiB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAY9E;AAED,iBAAS,aAAa,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,KAAK,CAAC,KAAK,qBAoDpF;AAED;;;;GAIG;AACH,iBAAS,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWzE;AAED;;;GAGG;AACH,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWvE;AAED,iBAAS,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWzE;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,KAAK,CAAC,KAAK,qBAQxE;AAED,iBAAS,iBAAiB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,WAAW,CAAC,KAAK,qBAQpF;AAED,OAAO,EACL,MAAM,EACN,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,aAAa,EACb,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,WAAW,EACX,iBAAiB,GAClB,CAAC"}
|
|
@@ -22,12 +22,12 @@ function useDrawer() {
|
|
|
22
22
|
* Ours: no screen calls it today.
|
|
23
23
|
* @instead "Don’t use Drawer to confirm destructive actions. The lack of a fully blocking dim weakens the severity signal that delete and revoke flows need; route to `Modal`." (https://vercel.com/geist/drawer)
|
|
24
24
|
* Ours: on a desktop a blocking job is `Dialog` and context beside a record is `Sheet`; a catalogue
|
|
25
|
-
*
|
|
25
|
+
* is `CatalogDrawer` and a setup in steps is `FormDrawer`; both are the right-side sheet, not this one.
|
|
26
26
|
* @behaviour "Tap-outside and swipe-down dismiss by default; preserve both unless the form has dirty input." (https://vercel.com/geist/drawer)
|
|
27
27
|
* "Use `verticalScroll` so the drawer body scrolls inside its frame instead of the page behind it." (https://vercel.com/geist/drawer)
|
|
28
28
|
* "Cap content height with `customHeight` only when the default height clips the primary action; the action and `Cancel` must stay above the fold." (https://vercel.com/geist/drawer)
|
|
29
|
-
* Ours: `unsaved.dirty` holds back the swipe, Escape and a press outside
|
|
30
|
-
* runs. The body always scrolls inside the frame, so there is no `verticalScroll`; `height` is
|
|
29
|
+
* Ours: `unsaved.dirty` holds back the swipe, Escape, the system back gesture and a press outside
|
|
30
|
+
* while input is typed, and `unsaved.onDismissBlocked` runs. The body always scrolls inside the frame, so there is no `verticalScroll`; `height` is
|
|
31
31
|
* Geist's `customHeight`. It rises from the bottom edge and follows the finger, is at most 80% of
|
|
32
32
|
* the viewport tall, and is all neutral. Nested drawers stack.
|
|
33
33
|
* @words "`DrawerTitle` is a Title Case statement that names the entity (`Deployment Details`, `Filter Logs`)." (https://vercel.com/geist/drawer)
|
|
@@ -6,8 +6,8 @@ import type { LoadingWord } from "./button.js";
|
|
|
6
6
|
*
|
|
7
7
|
* @family Menus
|
|
8
8
|
* @when "Use Menu for a discoverable trigger that opens a list of actions on a single resource (a dots menu on a row, a dropdown on a primary entity)." (https://vercel.com/geist/menu) Ours: a menu no composition draws: a column chooser, a sort, a product's own choices in a submenu.
|
|
9
|
-
* @instead "For right-click or long-press on a row, use `ContextMenu`. For global commands behind `⌘K`, use `CommandMenu`. For two related primary actions, use a split button rather than burying the secondary action." (https://vercel.com/geist/menu) Ours: those are `ContextMenu` and `CommandDialog`; two related primary actions stand side by side as buttons. A record's or a page's commands are `ActionMenu` or `PageActions`' menu, from data. The account's rows are `AccountMenu`. A value to choose in a form is `Select`.
|
|
10
|
-
* @behaviour "Dropdown menu opened via button. Supports typeahead and keyboard navigation." (https://vercel.com/geist/menu) "Open on click, not hover; hover-open menus collide with screen readers and trackpad scrolls." (https://vercel.com/geist/menu) "Position auto-flips based on window bounds; don’t hardcode a side that clips on narrow viewports." (https://vercel.com/geist/menu) "Close on item activation, Escape, and outside-click. Don’t auto-close on a hover-out." (https://vercel.com/geist/menu) "Use `MenuItemLocked` for permission-gated actions so the lock icon and disabled state explain why the row is inert." (https://vercel.com/geist/menu) Ours: that is `locked` with its `reason`. A solid floating surface, 200 px wide at least, 10 px from its trigger. A labelled trigger may end in a chevron; an icon trigger has none. Safe commands come first, each with its icon, groups split by a divider, the destructive command last. Colour sits on that command alone: its text is the error colour at rest and its row takes the soft error fill when highlighted; the panel, the other rows, a section title and the divider stay neutral, and a suffix or lock is muted, 12 px after the label. A command that cannot run stays in place with muted text, never dimmed, and says why in a muted line under its label, which a tap on a phone reads as well as a pointer, since a tooltip opens for the mouse only; a destructive one is muted, not red. Every row is 36 px (44 on touch) with the pointer cursor, or the default one when it cannot be chosen, a row with a reason growing by its line, and a section title is a muted row of that height. The highlight is the row's fill alone: no text inside a row changes colour with it, and a row that cannot be chosen takes no highlight.
|
|
9
|
+
* @instead "For right-click or long-press on a row, use `ContextMenu`. For global commands behind `⌘K`, use `CommandMenu`. For two related primary actions, use a split button rather than burying the secondary action." (https://vercel.com/geist/menu) Ours: those are `ContextMenu` and `CommandDialog`; two related primary actions stand side by side as buttons. A record's or a page's commands are `ActionMenu` or `PageActions`' menu, from data. The account's rows are `AccountMenu`. These four draw their rows with `DropdownMenuCommand`; the `DropdownMenu` family is used directly only for a choice menu such as a sort, with `DropdownMenuLink` for a destination row. A value to choose in a form is `Select`.
|
|
10
|
+
* @behaviour "Dropdown menu opened via button. Supports typeahead and keyboard navigation." (https://vercel.com/geist/menu) "Open on click, not hover; hover-open menus collide with screen readers and trackpad scrolls." (https://vercel.com/geist/menu) "Position auto-flips based on window bounds; don’t hardcode a side that clips on narrow viewports." (https://vercel.com/geist/menu) "Close on item activation, Escape, and outside-click. Don’t auto-close on a hover-out." (https://vercel.com/geist/menu) "Use `MenuItemLocked` for permission-gated actions so the lock icon and disabled state explain why the row is inert." (https://vercel.com/geist/menu) Ours: that is `locked` with its `reason`. A solid floating surface, 200 px wide at least, 10 px from its trigger. A labelled trigger may end in a chevron; an icon trigger has none. Safe commands come first, each with its icon, groups split by a divider, the destructive command last. Colour sits on that command alone: its text is the error colour at rest and its row takes the soft error fill when highlighted; the panel, the other rows, a section title and the divider stay neutral, and a suffix or lock is muted, 12 px after the label. A command that cannot run stays in place with muted text, never dimmed, and says why in a muted line under its label, which a tap on a phone reads as well as a pointer, since a tooltip opens for the mouse only; a destructive one is muted, not red. Every row, of any kind, is 36 px in the default comfortable density (44 on touch; the compact density, `density="compact"`, tightens the padding to about 28 px on a fine pointer, and no menu in the product uses it) with `{rounded.sm}` corners and the pointer cursor, or the default one when it cannot be chosen, a row with a reason growing by its line, and a section title is a muted row of that height. The highlight is the row's fill alone: no text inside a row changes colour with it, and a row that cannot be chosen takes no highlight. A submenu goes one level deep at most (`one-submenu-level`), and never holds a destructive command.
|
|
11
11
|
* @words "Item children are Title Case `Verb + Noun` (`Rename Project`, `Duplicate Deployment`). Bare verbs like `Rename` or `Edit` are wrong outside obvious single-object context." (https://vercel.com/geist/menu) "End an item with `…` only when activating it opens a follow-up dialog (`Rename…`, `Transfer to Team…`)." (https://vercel.com/geist/menu) "Group destructive items at the bottom, separated by a divider, and keep the destructive copy as `Verb + Noun` (`Delete Project`, never bare `Delete`)." (https://vercel.com/geist/menu) "Section headers (`MenuSection title`) are Title Case, 1–2 words (`Workspace`, `Recent Projects`)." (https://vercel.com/geist/menu) "Cap a Menu around 10 items. Past that, group with `MenuSection` or move secondary actions to a settings page." (https://vercel.com/geist/menu) Ours: sentence case, not Title Case: "Remove mailbox", never a bare "Delete"; a section title is sentence case too. Italian runs a third longer; rows wrap, never truncate.
|
|
12
12
|
* @access "Up/Down arrows move focus through items, Home/End jump to first/last, Enter or Space activates." (https://vercel.com/geist/menu) "Typeahead jumps to the next item whose label starts with the typed character; keep the visible label first so typeahead matches what the user sees." (https://vercel.com/geist/menu) "Return focus to the trigger on close so keyboard users keep their place in the row." (https://vercel.com/geist/menu) Ours: `role="menu"` named by its trigger, items `menuitem`. Unlike Geist, which skips disabled rows, arrows land on a command that cannot run so its reason is read; it is still never highlighted and never runs. A command's icon is hidden; the value it acts on and its reason are its description. `DropdownMenuCommand` requires its `icon`; a command that cannot run takes `disabledReason`, and one a person may not run is `locked` with its `reason`, so nothing is greyed without saying why.
|
|
13
13
|
*/
|