cursedbelt 5.64.0 → 5.67.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/react/Toast.d.ts.map +1 -1
- package/dist/react/Toast.js +4 -1
- package/dist/react/Toast.js.map +1 -1
- package/dist/react/components/Accordion.d.ts.map +1 -1
- package/dist/react/components/Accordion.js +6 -1
- package/dist/react/components/Accordion.js.map +1 -1
- package/dist/react/components/Button.d.ts.map +1 -1
- package/dist/react/components/Button.js +9 -2
- package/dist/react/components/Button.js.map +1 -1
- package/dist/react/components/CardTapTarget.d.ts.map +1 -1
- package/dist/react/components/CardTapTarget.js +7 -1
- package/dist/react/components/CardTapTarget.js.map +1 -1
- package/dist/react/components/ChipFilterStrip.d.ts.map +1 -1
- package/dist/react/components/ChipFilterStrip.js +2 -1
- package/dist/react/components/ChipFilterStrip.js.map +1 -1
- package/dist/react/components/ColorField.js +1 -1
- package/dist/react/components/ColorField.js.map +1 -1
- package/dist/react/components/ComboboxField.js +1 -1
- package/dist/react/components/ComboboxField.js.map +1 -1
- package/dist/react/components/ConfirmDialog.d.ts.map +1 -1
- package/dist/react/components/ConfirmDialog.js +2 -1
- package/dist/react/components/ConfirmDialog.js.map +1 -1
- package/dist/react/components/Drawer.d.ts.map +1 -1
- package/dist/react/components/Drawer.js +2 -1
- package/dist/react/components/Drawer.js.map +1 -1
- package/dist/react/components/Lightbox.d.ts.map +1 -1
- package/dist/react/components/Lightbox.js +2 -1
- package/dist/react/components/Lightbox.js.map +1 -1
- package/dist/react/components/Modal.d.ts.map +1 -1
- package/dist/react/components/Modal.js +5 -3
- package/dist/react/components/Modal.js.map +1 -1
- package/dist/react/components/PromptDialog.d.ts.map +1 -1
- package/dist/react/components/PromptDialog.js +2 -1
- package/dist/react/components/PromptDialog.js.map +1 -1
- package/dist/react/components/SecretInput.js +1 -1
- package/dist/react/components/SecretInput.js.map +1 -1
- package/dist/react/components/SegmentedControl.d.ts.map +1 -1
- package/dist/react/components/SegmentedControl.js +2 -1
- package/dist/react/components/SegmentedControl.js.map +1 -1
- package/dist/react/components/Tabs.d.ts.map +1 -1
- package/dist/react/components/Tabs.js +68 -15
- package/dist/react/components/Tabs.js.map +1 -1
- package/dist/react/components/TagsInput.js +1 -1
- package/dist/react/components/TagsInput.js.map +1 -1
- package/dist/react/components/TooltipImpl.d.ts.map +1 -1
- package/dist/react/components/TooltipImpl.js +2 -1
- package/dist/react/components/TooltipImpl.js.map +1 -1
- package/dist/react/components/dialog.d.ts.map +1 -1
- package/dist/react/components/dialog.js +2 -1
- package/dist/react/components/dialog.js.map +1 -1
- package/dist/react/components/searchInput.css +4 -2
- package/dist/react/layoutEngine/LayoutConfigDialog.d.ts.map +1 -1
- package/dist/react/layoutEngine/LayoutConfigDialog.js +3 -1
- package/dist/react/layoutEngine/LayoutConfigDialog.js.map +1 -1
- package/dist/react/lib/field.d.ts +2 -2
- package/dist/react/lib/field.d.ts.map +1 -1
- package/dist/react/lib/field.js +9 -3
- package/dist/react/lib/field.js.map +1 -1
- package/dist/react/lib/floatingStyles.d.ts +10 -2
- package/dist/react/lib/floatingStyles.d.ts.map +1 -1
- package/dist/react/lib/floatingStyles.js +12 -7
- package/dist/react/lib/floatingStyles.js.map +1 -1
- package/dist/react/lib/overlayMotion.d.ts +37 -0
- package/dist/react/lib/overlayMotion.d.ts.map +1 -0
- package/dist/react/lib/overlayMotion.js +50 -0
- package/dist/react/lib/overlayMotion.js.map +1 -0
- package/dist/react/lib/press.d.ts +37 -0
- package/dist/react/lib/press.d.ts.map +1 -0
- package/dist/react/lib/press.js +41 -0
- package/dist/react/lib/press.js.map +1 -0
- package/dist/react/media-gallery/MediaGallery.d.ts +22 -1
- package/dist/react/media-gallery/MediaGallery.d.ts.map +1 -1
- package/dist/react/media-gallery/MediaGallery.js +13 -3
- package/dist/react/media-gallery/MediaGallery.js.map +1 -1
- package/dist/react/nav/PlaceBar.d.ts.map +1 -1
- package/dist/react/nav/PlaceBar.js +4 -3
- package/dist/react/nav/PlaceBar.js.map +1 -1
- package/dist/react/nav/TopBar.d.ts.map +1 -1
- package/dist/react/nav/TopBar.js +13 -2
- package/dist/react/nav/TopBar.js.map +1 -1
- package/dist/react/palette/CommandPalette.d.ts.map +1 -1
- package/dist/react/palette/CommandPalette.js +3 -2
- package/dist/react/palette/CommandPalette.js.map +1 -1
- package/dist/styles-areas/analytics.css +2 -2
- package/dist/styles-areas/core.css +73 -64
- package/dist/styles-areas/data-table.css +3 -3
- package/dist/styles-areas/fields.css +2 -2
- package/dist/styles-areas/media.css +4 -4
- package/dist/styles-areas/nav.css +18 -18
- package/dist/styles-areas/overlays.css +2 -2
- package/dist/styles-areas/palette.css +4 -5
- package/dist/styles-areas/place-bar.css +5 -5
- package/dist/styles-areas/sharing.css +4 -4
- package/dist/styles-areas/test-report.css +4 -4
- package/dist/styles-areas/wizard.css +2 -2
- package/dist/styles-areas/workbench.css +2 -2
- package/dist/styles-utilities.css +103 -20
- package/dist/theme.css +47 -0
- package/package.json +1 -1
- package/src/react/Toast.tsx +4 -1
- package/src/react/components/Accordion.tsx +8 -1
- package/src/react/components/Button.spec.tsx +16 -0
- package/src/react/components/Button.tsx +9 -2
- package/src/react/components/CardTapTarget.tsx +6 -1
- package/src/react/components/ChipFilterStrip.tsx +3 -1
- package/src/react/components/ColorField.tsx +1 -1
- package/src/react/components/ComboboxField.tsx +1 -1
- package/src/react/components/ConfirmDialog.tsx +2 -2
- package/src/react/components/Drawer.tsx +2 -0
- package/src/react/components/Lightbox.tsx +2 -2
- package/src/react/components/Modal.tsx +5 -4
- package/src/react/components/PromptDialog.tsx +2 -2
- package/src/react/components/SecretInput.tsx +1 -1
- package/src/react/components/SegmentedControl.tsx +3 -1
- package/src/react/components/Tabs.tsx +78 -5
- package/src/react/components/TagsInput.tsx +1 -1
- package/src/react/components/TooltipImpl.tsx +2 -0
- package/src/react/components/dialog.tsx +2 -2
- package/src/react/components/searchInput.css +4 -2
- package/src/react/layoutEngine/LayoutConfigDialog.tsx +3 -1
- package/src/react/lib/field.ts +9 -3
- package/src/react/lib/floatingStyles.ts +12 -8
- package/src/react/lib/overlayMotion.ts +58 -0
- package/src/react/lib/press.ts +43 -0
- package/src/react/media-gallery/MediaGallery.spec.tsx +65 -1
- package/src/react/media-gallery/MediaGallery.tsx +37 -2
- package/src/react/nav/PlaceBar.tsx +7 -3
- package/src/react/nav/TopBar.spec.tsx +34 -0
- package/src/react/nav/TopBar.tsx +22 -0
- package/src/react/palette/CommandPalette.tsx +3 -2
- package/src/styles-areas/analytics.css +2 -2
- package/src/styles-areas/core.css +73 -64
- package/src/styles-areas/data-table.css +3 -3
- package/src/styles-areas/fields.css +2 -2
- package/src/styles-areas/media.css +4 -4
- package/src/styles-areas/nav.css +18 -18
- package/src/styles-areas/overlays.css +2 -2
- package/src/styles-areas/palette.css +4 -5
- package/src/styles-areas/place-bar.css +5 -5
- package/src/styles-areas/sharing.css +4 -4
- package/src/styles-areas/test-report.css +4 -4
- package/src/styles-areas/wizard.css +2 -2
- package/src/styles-areas/workbench.css +2 -2
- package/src/styles-utilities.css +103 -20
- package/src/theme.css +47 -0
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* after an app's responsive variant (task 2124). An app that imports every area gets exactly
|
|
19
19
|
* what `cursedbelt/styles-utilities.css` emits — proved rule by rule in
|
|
20
20
|
* src/stylesAreas.spec.ts, which is also what fails when this file is stale.
|
|
21
|
-
*
|
|
21
|
+
* 142 candidate(s).
|
|
22
22
|
*
|
|
23
23
|
* Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
|
|
24
24
|
* `bun run build` runs. The map of what is in which area, and why the areas are
|
|
@@ -37,20 +37,20 @@
|
|
|
37
37
|
@source inline("data-[selected=true]:text-foreground data-[state=closed]:slide-out-to-bottom");
|
|
38
38
|
@source inline("data-[state=closed]:slide-out-to-left data-[state=closed]:slide-out-to-right");
|
|
39
39
|
@source inline("data-[state=open]:slide-in-from-bottom data-[state=open]:slide-in-from-left");
|
|
40
|
-
@source inline("data-[state=open]:slide-in-from-right
|
|
41
|
-
@source inline("
|
|
42
|
-
@source inline("group-hover/
|
|
43
|
-
@source inline("h-[var(--header-h
|
|
44
|
-
@source inline("hover:
|
|
45
|
-
@source inline("inset-
|
|
46
|
-
@source inline("lg:
|
|
47
|
-
@source inline("max-h-[var(--
|
|
48
|
-
@source inline("max-
|
|
49
|
-
@source inline("max-sm:
|
|
50
|
-
@source inline("
|
|
51
|
-
@source inline("
|
|
52
|
-
@source inline("
|
|
53
|
-
@source inline("
|
|
54
|
-
@source inline("
|
|
55
|
-
@source inline("sm:inline-
|
|
56
|
-
@source inline("w-[
|
|
40
|
+
@source inline("data-[state=open]:slide-in-from-right disabled:hover:scale-100 disabled:opacity-40");
|
|
41
|
+
@source inline("focus-within:opacity-100 g grid-cols-4 group-hover/navitem:opacity-100");
|
|
42
|
+
@source inline("group-hover/tile:opacity-100 group/navitem group/tile h-12 h-[var(--header-h)]");
|
|
43
|
+
@source inline("h-[var(--header-h-dense)] h-[var(--header-h-roomy)] h-dvh hover:border-foreground/20");
|
|
44
|
+
@source inline("hover:decoration-border hover:scale-110 hover:underline-offset-4 inset-x-2 inset-x-3 inset-y-1");
|
|
45
|
+
@source inline("inset-y-1.5 items-stretch justify-around leading-4 left-3 lg:flex lg:flex-col lg:hidden");
|
|
46
|
+
@source inline("lg:shrink-0 list-none max-h-72 max-h-[inherit] max-h-[var(--palette-max-h)]");
|
|
47
|
+
@source inline("max-h-[var(--sheet-h-lg)] max-h-[var(--sheet-h-md)] max-h-[var(--sheet-h-sm)] max-md:-right-0.5");
|
|
48
|
+
@source inline("max-md:-top-0.5 max-md:absolute max-md:hidden max-sm:flex-none max-sm:justify-center max-sm:px-0");
|
|
49
|
+
@source inline("max-sm:w-10 max-w max-w-48 max-w-64 max-w-80 max-w-sm md:flex md:flex-col md:gap-4 md:hidden");
|
|
50
|
+
@source inline("md:pointer-coarse:w-auto md:px-3 md:px-6 md:shrink-0 min-h-10 min-h-12 min-h-dvh min-w-3.5");
|
|
51
|
+
@source inline("min-w-8 min-w-9 mix-blend-difference mt-auto mx-1 no-underline opacity-55 opacity-80");
|
|
52
|
+
@source inline("pb-[env(safe-area-inset-bottom,0px)] pl-11 pl-9 place-items-center");
|
|
53
|
+
@source inline("placeholder:text-muted-foreground pr-3 pr-9 pt-0 pt-1 px-0.5 py-8 right-1 rotate-180");
|
|
54
|
+
@source inline("rounded-l-xl rounded-r-xl rounded-t-xl shadow-lg size-7 size-9 sm:inline sm:inline-block");
|
|
55
|
+
@source inline("sm:inline-flex space-y-0.5 space-y-2 top-[var(--palette-top)] w-52 w-56 w-60 w-[calc(100%-2rem)]");
|
|
56
|
+
@source inline("w-[var(--rail-w)] w-[var(--rail-w-collapsed)] w-max");
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* after an app's responsive variant (task 2124). An app that imports every area gets exactly
|
|
19
19
|
* what `cursedbelt/styles-utilities.css` emits — proved rule by rule in
|
|
20
20
|
* src/stylesAreas.spec.ts, which is also what fails when this file is stale.
|
|
21
|
-
*
|
|
21
|
+
* 23 candidate(s).
|
|
22
22
|
*
|
|
23
23
|
* Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
|
|
24
24
|
* `bun run build` runs. The map of what is in which area, and why the areas are
|
|
@@ -28,6 +28,6 @@
|
|
|
28
28
|
@source inline("data-[state=closed]:slide-out-to-bottom data-[state=closed]:slide-out-to-left");
|
|
29
29
|
@source inline("data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-bottom");
|
|
30
30
|
@source inline("data-[state=open]:slide-in-from-left data-[state=open]:slide-in-from-right hover:border-border");
|
|
31
|
-
@source inline("
|
|
31
|
+
@source inline("max-h-[var(--radix-popover-content-available-height)] max-h-[var(--sheet-h-lg)]");
|
|
32
32
|
@source inline("max-h-[var(--sheet-h-md)] max-h-[var(--sheet-h-sm)] max-w-[var(--overlay-max-w)] max-w-sm");
|
|
33
33
|
@source inline("rounded-l-xl rounded-r-xl rounded-t-xl w-64");
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* after an app's responsive variant (task 2124). An app that imports every area gets exactly
|
|
19
19
|
* what `cursedbelt/styles-utilities.css` emits — proved rule by rule in
|
|
20
20
|
* src/stylesAreas.spec.ts, which is also what fails when this file is stale.
|
|
21
|
-
*
|
|
21
|
+
* 23 candidate(s).
|
|
22
22
|
*
|
|
23
23
|
* Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
|
|
24
24
|
* `bun run build` runs. The map of what is in which area, and why the areas are
|
|
@@ -29,7 +29,6 @@
|
|
|
29
29
|
@source inline("[&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:tracking-wide");
|
|
30
30
|
@source inline("[&_[cmdk-group-heading]]:uppercase [&_svg]:size-3.5 bg-accent/15 border-dashed");
|
|
31
31
|
@source inline("data-[disabled=true]:opacity-50 data-[disabled=true]:pointer-events-none");
|
|
32
|
-
@source inline("data-[selected=true]:bg-muted data-[selected=true]:text-foreground");
|
|
33
|
-
@source inline("
|
|
34
|
-
@source inline("
|
|
35
|
-
@source inline("w-[calc(100%-2rem)]");
|
|
32
|
+
@source inline("data-[selected=true]:bg-muted data-[selected=true]:text-foreground h-12");
|
|
33
|
+
@source inline("max-h-[var(--palette-max-h)] mx-1 place-items-center placeholder:text-muted-foreground py-8");
|
|
34
|
+
@source inline("sm:inline-block top-[var(--palette-top)] w-[calc(100%-2rem)]");
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* after an app's responsive variant (task 2124). An app that imports every area gets exactly
|
|
19
19
|
* what `cursedbelt/styles-utilities.css` emits — proved rule by rule in
|
|
20
20
|
* src/stylesAreas.spec.ts, which is also what fails when this file is stale.
|
|
21
|
-
*
|
|
21
|
+
* 30 candidate(s).
|
|
22
22
|
*
|
|
23
23
|
* Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
|
|
24
24
|
* `bun run build` runs. The map of what is in which area, and why the areas are
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
@source inline("-mt-5 -top-1 bg-accent/15 border-l border-r data-[state=closed]:slide-out-to-bottom");
|
|
28
28
|
@source inline("data-[state=closed]:slide-out-to-left data-[state=closed]:slide-out-to-right");
|
|
29
29
|
@source inline("data-[state=open]:slide-in-from-bottom data-[state=open]:slide-in-from-left");
|
|
30
|
-
@source inline("data-[state=open]:slide-in-from-right inset-x-3 items-stretch justify-around leading-4
|
|
31
|
-
@source inline("
|
|
32
|
-
@source inline("min-
|
|
33
|
-
@source inline("
|
|
30
|
+
@source inline("data-[state=open]:slide-in-from-right inset-x-3 items-stretch justify-around leading-4 list-none");
|
|
31
|
+
@source inline("max-h-[var(--sheet-h-lg)] max-h-[var(--sheet-h-md)] max-h-[var(--sheet-h-sm)] max-w-sm min-h-12");
|
|
32
|
+
@source inline("min-w-3.5 no-underline place-items-center pt-0 px-0.5 rounded-l-xl rounded-r-xl rounded-t-xl");
|
|
33
|
+
@source inline("shadow-lg");
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* after an app's responsive variant (task 2124). An app that imports every area gets exactly
|
|
19
19
|
* what `cursedbelt/styles-utilities.css` emits — proved rule by rule in
|
|
20
20
|
* src/stylesAreas.spec.ts, which is also what fails when this file is stale.
|
|
21
|
-
*
|
|
21
|
+
* 29 candidate(s).
|
|
22
22
|
*
|
|
23
23
|
* Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
|
|
24
24
|
* `bun run build` runs. The map of what is in which area, and why the areas are
|
|
@@ -27,6 +27,6 @@
|
|
|
27
27
|
@source inline("bg-accent/15 border-[var(--border)] border-l border-r data-[state=closed]:slide-out-to-bottom");
|
|
28
28
|
@source inline("data-[state=closed]:slide-out-to-left data-[state=closed]:slide-out-to-right");
|
|
29
29
|
@source inline("data-[state=open]:slide-in-from-bottom data-[state=open]:slide-in-from-left");
|
|
30
|
-
@source inline("data-[state=open]:slide-in-from-right disabled:opacity-100 hover:opacity-90 left-
|
|
31
|
-
@source inline("max-h-
|
|
32
|
-
@source inline("
|
|
30
|
+
@source inline("data-[state=open]:slide-in-from-right disabled:opacity-100 hover:opacity-90 left-3 max-h-56");
|
|
31
|
+
@source inline("max-h-[var(--sheet-h-lg)] max-h-[var(--sheet-h-md)] max-h-[var(--sheet-h-sm)] max-w-sm min-w-48");
|
|
32
|
+
@source inline("ml-2 mt-4 pl-9 right-3 rounded-l-xl rounded-r-xl rounded-t-xl size-9 space-y-4 w-32");
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* after an app's responsive variant (task 2124). An app that imports every area gets exactly
|
|
19
19
|
* what `cursedbelt/styles-utilities.css` emits — proved rule by rule in
|
|
20
20
|
* src/stylesAreas.spec.ts, which is also what fails when this file is stale.
|
|
21
|
-
*
|
|
21
|
+
* 23 candidate(s).
|
|
22
22
|
*
|
|
23
23
|
* Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
|
|
24
24
|
* `bun run build` runs. The map of what is in which area, and why the areas are
|
|
@@ -27,6 +27,6 @@
|
|
|
27
27
|
@source inline("border-l border-r data-[state=closed]:slide-out-to-bottom data-[state=closed]:slide-out-to-left");
|
|
28
28
|
@source inline("data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-bottom");
|
|
29
29
|
@source inline("data-[state=open]:slide-in-from-left data-[state=open]:slide-in-from-right h-80");
|
|
30
|
-
@source inline("hover:bg-muted/60 hover:no-underline last:border-0
|
|
31
|
-
@source inline("max-h-[var(--sheet-h-
|
|
32
|
-
@source inline("
|
|
30
|
+
@source inline("hover:bg-muted/60 hover:no-underline last:border-0 max-h-72 max-h-96 max-h-[var(--sheet-h-lg)]");
|
|
31
|
+
@source inline("max-h-[var(--sheet-h-md)] max-h-[var(--sheet-h-sm)] max-w-sm no-underline rounded-l-xl");
|
|
32
|
+
@source inline("rounded-r-xl rounded-t-xl w-2");
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* after an app's responsive variant (task 2124). An app that imports every area gets exactly
|
|
19
19
|
* what `cursedbelt/styles-utilities.css` emits — proved rule by rule in
|
|
20
20
|
* src/stylesAreas.spec.ts, which is also what fails when this file is stale.
|
|
21
|
-
*
|
|
21
|
+
* 57 candidate(s).
|
|
22
22
|
*
|
|
23
23
|
* Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
|
|
24
24
|
* `bun run build` runs. The map of what is in which area, and why the areas are
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
@source inline("data-[state=open]:slide-in-from-right disabled:bg-transparent disabled:opacity-100 duration-100");
|
|
34
34
|
@source inline("focus-visible:ring-field-ring/40 focus-within:border-field-ring focus-within:ring-2");
|
|
35
35
|
@source inline("focus-within:ring-field-ring/30 h-105 has-[[aria-invalid=true]]:border-field-error");
|
|
36
|
-
@source inline("hover:border-field-ring hover:text-warning
|
|
36
|
+
@source inline("hover:border-field-ring hover:text-warning max-h-64 max-h-[var(--sheet-h-lg)]");
|
|
37
37
|
@source inline("max-h-[var(--sheet-h-md)] max-h-[var(--sheet-h-sm)] max-w-sm min-h-20 min-w-24");
|
|
38
38
|
@source inline("min-w-[var(--anchor-width)] mr-1.5 mr-2 pl-1.5 pl-2 pr-1 pr-16 pr-3 resize-none resize-y");
|
|
39
39
|
@source inline("ring-field-error/30 rounded-l-xl rounded-r-xl rounded-t-xl self-stretch size-7 sm:inline");
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* after an app's responsive variant (task 2124). An app that imports every area gets exactly
|
|
19
19
|
* what `cursedbelt/styles-utilities.css` emits — proved rule by rule in
|
|
20
20
|
* src/stylesAreas.spec.ts, which is also what fails when this file is stale.
|
|
21
|
-
*
|
|
21
|
+
* 107 candidate(s).
|
|
22
22
|
*
|
|
23
23
|
* Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
|
|
24
24
|
* `bun run build` runs. The map of what is in which area, and why the areas are
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
@source inline("data-[state=open]:slide-in-from-bottom data-[state=open]:slide-in-from-left");
|
|
33
33
|
@source inline("data-[state=open]:slide-in-from-right disabled:opacity-0 duration-150 first:pt-1 flex-row");
|
|
34
34
|
@source inline("group-hover:disabled:opacity-50 h-105 h-40 hover:bg-card-overlay hover:bg-muted-foreground/10");
|
|
35
|
-
@source inline("hover:bg-muted/80 hover:border-field-ring hover:shadow-popover italic left-
|
|
35
|
+
@source inline("hover:bg-muted/80 hover:border-field-ring hover:shadow-popover italic left-2.5");
|
|
36
36
|
@source inline("max-h-[var(--sheet-h-lg)] max-h-[var(--sheet-h-md)] max-h-[var(--sheet-h-sm)] max-h-full");
|
|
37
37
|
@source inline("max-w-sm min-h min-h-20 min-h-8 min-h-9 min-h-dvh min-h-full min-w-20 min-w-40 opacity-100");
|
|
38
38
|
@source inline("pb-0.5 pb-[max(env(safe-area-inset-bottom,0px),0.5rem)] peer-focus peer-focus:outline-none");
|
|
@@ -3344,6 +3344,11 @@
|
|
|
3344
3344
|
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
|
3345
3345
|
transition-duration: var(--tw-duration, var(--default-transition-duration));
|
|
3346
3346
|
}
|
|
3347
|
+
.transition-\[color\,background-color\,border-color\,box-shadow\,scale\] {
|
|
3348
|
+
transition-property: color,background-color,border-color,box-shadow,scale;
|
|
3349
|
+
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
|
3350
|
+
transition-duration: var(--tw-duration, var(--default-transition-duration));
|
|
3351
|
+
}
|
|
3347
3352
|
.transition-\[opacity\,transform\] {
|
|
3348
3353
|
transition-property: opacity,transform;
|
|
3349
3354
|
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
|
@@ -3359,6 +3364,11 @@
|
|
|
3359
3364
|
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
|
3360
3365
|
transition-duration: var(--tw-duration, var(--default-transition-duration));
|
|
3361
3366
|
}
|
|
3367
|
+
.transition-\[transform\,width\] {
|
|
3368
|
+
transition-property: transform,width;
|
|
3369
|
+
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
|
3370
|
+
transition-duration: var(--tw-duration, var(--default-transition-duration));
|
|
3371
|
+
}
|
|
3362
3372
|
.transition-\[width\] {
|
|
3363
3373
|
transition-property: width;
|
|
3364
3374
|
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
|
@@ -3400,14 +3410,30 @@
|
|
|
3400
3410
|
--tw-duration: 300ms;
|
|
3401
3411
|
transition-duration: 300ms;
|
|
3402
3412
|
}
|
|
3413
|
+
.duration-\[var\(--duration-base\)\] {
|
|
3414
|
+
--tw-duration: var(--duration-base);
|
|
3415
|
+
transition-duration: var(--duration-base);
|
|
3416
|
+
}
|
|
3403
3417
|
.duration-\[var\(--duration-fast\)\] {
|
|
3404
3418
|
--tw-duration: var(--duration-fast);
|
|
3405
3419
|
transition-duration: var(--duration-fast);
|
|
3406
3420
|
}
|
|
3421
|
+
.duration-\[var\(--duration-slow\)\] {
|
|
3422
|
+
--tw-duration: var(--duration-slow);
|
|
3423
|
+
transition-duration: var(--duration-slow);
|
|
3424
|
+
}
|
|
3425
|
+
.duration-\[var\(--duration-slow\)\]\! {
|
|
3426
|
+
--tw-duration: var(--duration-slow) !important;
|
|
3427
|
+
transition-duration: var(--duration-slow) !important;
|
|
3428
|
+
}
|
|
3407
3429
|
.ease-\[var\(--ease-out\)\] {
|
|
3408
3430
|
--tw-ease: var(--ease-out);
|
|
3409
3431
|
transition-timing-function: var(--ease-out);
|
|
3410
3432
|
}
|
|
3433
|
+
.ease-\[var\(--ease-out\)\]\! {
|
|
3434
|
+
--tw-ease: var(--ease-out) !important;
|
|
3435
|
+
transition-timing-function: var(--ease-out) !important;
|
|
3436
|
+
}
|
|
3411
3437
|
.ease-in-out {
|
|
3412
3438
|
--tw-ease: var(--ease-in-out);
|
|
3413
3439
|
transition-timing-function: var(--ease-in-out);
|
|
@@ -4026,6 +4052,18 @@
|
|
|
4026
4052
|
--tw-outline-style: none;
|
|
4027
4053
|
outline-style: none;
|
|
4028
4054
|
}
|
|
4055
|
+
.active\:scale-100:active {
|
|
4056
|
+
--tw-scale-x: 100%;
|
|
4057
|
+
--tw-scale-y: 100%;
|
|
4058
|
+
--tw-scale-z: 100%;
|
|
4059
|
+
scale: var(--tw-scale-x) var(--tw-scale-y);
|
|
4060
|
+
}
|
|
4061
|
+
.active\:scale-\[var\(--press-scale\)\]:active {
|
|
4062
|
+
scale: var(--press-scale);
|
|
4063
|
+
}
|
|
4064
|
+
.active\:scale-\[var\(--press-scale-surface\)\]:active {
|
|
4065
|
+
scale: var(--press-scale-surface);
|
|
4066
|
+
}
|
|
4029
4067
|
.active\:cursor-grabbing:active {
|
|
4030
4068
|
cursor: grabbing;
|
|
4031
4069
|
}
|
|
@@ -4082,6 +4120,12 @@
|
|
|
4082
4120
|
color: var(--muted-foreground);
|
|
4083
4121
|
}
|
|
4084
4122
|
}
|
|
4123
|
+
.disabled\:active\:scale-100:disabled:active {
|
|
4124
|
+
--tw-scale-x: 100%;
|
|
4125
|
+
--tw-scale-y: 100%;
|
|
4126
|
+
--tw-scale-z: 100%;
|
|
4127
|
+
scale: var(--tw-scale-x) var(--tw-scale-y);
|
|
4128
|
+
}
|
|
4085
4129
|
.has-\[\[aria-invalid\=true\]\]\:border-field-error:has(:is([aria-invalid=true])) {
|
|
4086
4130
|
border-color: var(--field-error);
|
|
4087
4131
|
}
|
|
@@ -4113,6 +4157,12 @@
|
|
|
4113
4157
|
background-color: transparent;
|
|
4114
4158
|
}
|
|
4115
4159
|
}
|
|
4160
|
+
.aria-disabled\:active\:scale-100[aria-disabled="true"]:active {
|
|
4161
|
+
--tw-scale-x: 100%;
|
|
4162
|
+
--tw-scale-y: 100%;
|
|
4163
|
+
--tw-scale-z: 100%;
|
|
4164
|
+
scale: var(--tw-scale-x) var(--tw-scale-y);
|
|
4165
|
+
}
|
|
4116
4166
|
.aria-pressed\:border[aria-pressed="true"] {
|
|
4117
4167
|
border-style: var(--tw-border-style);
|
|
4118
4168
|
border-width: 1px;
|
|
@@ -4215,15 +4265,27 @@
|
|
|
4215
4265
|
.data-\[selected\=true\]\:text-foreground[data-selected="true"] {
|
|
4216
4266
|
color: var(--foreground);
|
|
4217
4267
|
}
|
|
4268
|
+
.data-\[side\=bottom\]\:slide-in-from-top-1[data-side="bottom"] {
|
|
4269
|
+
--tw-enter-translate-y: calc(1*var(--spacing)*-1);
|
|
4270
|
+
}
|
|
4218
4271
|
.data-\[side\=bottom\]\:slide-in-from-top-2[data-side="bottom"] {
|
|
4219
4272
|
--tw-enter-translate-y: calc(2*var(--spacing)*-1);
|
|
4220
4273
|
}
|
|
4274
|
+
.data-\[side\=left\]\:slide-in-from-right-1[data-side="left"] {
|
|
4275
|
+
--tw-enter-translate-x: calc(1*var(--spacing));
|
|
4276
|
+
}
|
|
4221
4277
|
.data-\[side\=left\]\:slide-in-from-right-2[data-side="left"] {
|
|
4222
4278
|
--tw-enter-translate-x: calc(2*var(--spacing));
|
|
4223
4279
|
}
|
|
4280
|
+
.data-\[side\=right\]\:slide-in-from-left-1[data-side="right"] {
|
|
4281
|
+
--tw-enter-translate-x: calc(1*var(--spacing)*-1);
|
|
4282
|
+
}
|
|
4224
4283
|
.data-\[side\=right\]\:slide-in-from-left-2[data-side="right"] {
|
|
4225
4284
|
--tw-enter-translate-x: calc(2*var(--spacing)*-1);
|
|
4226
4285
|
}
|
|
4286
|
+
.data-\[side\=top\]\:slide-in-from-bottom-1[data-side="top"] {
|
|
4287
|
+
--tw-enter-translate-y: calc(1*var(--spacing));
|
|
4288
|
+
}
|
|
4227
4289
|
.data-\[side\=top\]\:slide-in-from-bottom-2[data-side="top"] {
|
|
4228
4290
|
--tw-enter-translate-y: calc(2*var(--spacing));
|
|
4229
4291
|
}
|
|
@@ -4310,10 +4372,6 @@
|
|
|
4310
4372
|
--tw-exit-opacity: calc(0/100);
|
|
4311
4373
|
--tw-exit-opacity: 0;
|
|
4312
4374
|
}
|
|
4313
|
-
.data-\[state\=closed\]\:zoom-out-95[data-state="closed"] {
|
|
4314
|
-
--tw-exit-scale: calc(95*1%);
|
|
4315
|
-
--tw-exit-scale: .95;
|
|
4316
|
-
}
|
|
4317
4375
|
.data-\[state\=closed\]\:slide-out-to-bottom[data-state="closed"] {
|
|
4318
4376
|
--tw-exit-translate-y: 100%;
|
|
4319
4377
|
}
|
|
@@ -4323,6 +4381,19 @@
|
|
|
4323
4381
|
.data-\[state\=closed\]\:slide-out-to-right[data-state="closed"] {
|
|
4324
4382
|
--tw-exit-translate-x: 100%;
|
|
4325
4383
|
}
|
|
4384
|
+
.data-\[state\=closed\]\:zoom-out-\[0\.985\][data-state="closed"] {
|
|
4385
|
+
--tw-exit-scale: 0.985;
|
|
4386
|
+
}
|
|
4387
|
+
.data-\[state\=delayed-open\]\:animate-in[data-state="delayed-open"] {
|
|
4388
|
+
animation: enter var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none);
|
|
4389
|
+
}
|
|
4390
|
+
.data-\[state\=delayed-open\]\:fade-in-0[data-state="delayed-open"] {
|
|
4391
|
+
--tw-enter-opacity: calc(0/100);
|
|
4392
|
+
--tw-enter-opacity: 0;
|
|
4393
|
+
}
|
|
4394
|
+
.data-\[state\=delayed-open\]\:zoom-in-\[0\.985\][data-state="delayed-open"] {
|
|
4395
|
+
--tw-enter-scale: 0.985;
|
|
4396
|
+
}
|
|
4326
4397
|
.data-\[state\=indeterminate\]\:border-accent-solid[data-state="indeterminate"] {
|
|
4327
4398
|
border-color: var(--accent-solid);
|
|
4328
4399
|
}
|
|
@@ -4342,21 +4413,20 @@
|
|
|
4342
4413
|
--tw-enter-opacity: calc(0/100);
|
|
4343
4414
|
--tw-enter-opacity: 0;
|
|
4344
4415
|
}
|
|
4345
|
-
.data-\[state\=open\]\:zoom-in-95[data-state="open"] {
|
|
4346
|
-
--tw-enter-scale: calc(95*1%);
|
|
4347
|
-
--tw-enter-scale: .95;
|
|
4348
|
-
}
|
|
4349
4416
|
.data-\[state\=open\]\:slide-in-from-bottom[data-state="open"] {
|
|
4350
4417
|
--tw-enter-translate-y: 100%;
|
|
4351
4418
|
}
|
|
4419
|
+
.data-\[state\=open\]\:slide-in-from-bottom-2[data-state="open"] {
|
|
4420
|
+
--tw-enter-translate-y: calc(2*var(--spacing));
|
|
4421
|
+
}
|
|
4352
4422
|
.data-\[state\=open\]\:slide-in-from-left[data-state="open"] {
|
|
4353
4423
|
--tw-enter-translate-x: -100%;
|
|
4354
4424
|
}
|
|
4355
4425
|
.data-\[state\=open\]\:slide-in-from-right[data-state="open"] {
|
|
4356
4426
|
--tw-enter-translate-x: 100%;
|
|
4357
4427
|
}
|
|
4358
|
-
.data-\[state\=open\]\:
|
|
4359
|
-
--tw-enter-
|
|
4428
|
+
.data-\[state\=open\]\:zoom-in-\[0\.985\][data-state="open"] {
|
|
4429
|
+
--tw-enter-scale: 0.985;
|
|
4360
4430
|
}
|
|
4361
4431
|
.data-\[state\=unchecked\]\:translate-x-0[data-state="unchecked"] {
|
|
4362
4432
|
--tw-translate-x: 0px;
|
|
@@ -4369,6 +4439,19 @@
|
|
|
4369
4439
|
.motion-reduce\:animate-none {
|
|
4370
4440
|
animation: none;
|
|
4371
4441
|
}
|
|
4442
|
+
.motion-reduce\:transition-none {
|
|
4443
|
+
transition-property: none;
|
|
4444
|
+
}
|
|
4445
|
+
.motion-reduce\:duration-0 {
|
|
4446
|
+
--tw-duration: 0ms;
|
|
4447
|
+
transition-duration: 0ms;
|
|
4448
|
+
}
|
|
4449
|
+
.motion-reduce\:active\:scale-100:active {
|
|
4450
|
+
--tw-scale-x: 100%;
|
|
4451
|
+
--tw-scale-y: 100%;
|
|
4452
|
+
--tw-scale-z: 100%;
|
|
4453
|
+
scale: var(--tw-scale-x) var(--tw-scale-y);
|
|
4454
|
+
}
|
|
4372
4455
|
}
|
|
4373
4456
|
@media (width < 48rem) {
|
|
4374
4457
|
.max-md\:absolute {
|
|
@@ -4621,14 +4704,6 @@
|
|
|
4621
4704
|
font-size: var(--text-xs);
|
|
4622
4705
|
line-height: var(--tw-leading, var(--text-xs--line-height));
|
|
4623
4706
|
}
|
|
4624
|
-
.sm\:data-\[state\=closed\]\:zoom-out-95[data-state="closed"] {
|
|
4625
|
-
--tw-exit-scale: calc(95*1%);
|
|
4626
|
-
--tw-exit-scale: .95;
|
|
4627
|
-
}
|
|
4628
|
-
.sm\:data-\[state\=open\]\:zoom-in-95[data-state="open"] {
|
|
4629
|
-
--tw-enter-scale: calc(95*1%);
|
|
4630
|
-
--tw-enter-scale: .95;
|
|
4631
|
-
}
|
|
4632
4707
|
}
|
|
4633
4708
|
@media (width >= 48rem) {
|
|
4634
4709
|
.md\:flex {
|
|
@@ -5071,6 +5146,14 @@
|
|
|
5071
5146
|
}
|
|
5072
5147
|
}
|
|
5073
5148
|
}
|
|
5149
|
+
@media (width >= 40rem) {
|
|
5150
|
+
@media (pointer: fine) {
|
|
5151
|
+
.sm\:pointer-fine\:text-sm {
|
|
5152
|
+
font-size: var(--text-sm);
|
|
5153
|
+
line-height: var(--tw-leading, var(--text-sm--line-height));
|
|
5154
|
+
}
|
|
5155
|
+
}
|
|
5156
|
+
}
|
|
5074
5157
|
.\[\&_\.alert-icon\]\:text-accent .alert-icon {
|
|
5075
5158
|
color: var(--accent);
|
|
5076
5159
|
}
|
|
@@ -5768,11 +5851,11 @@
|
|
|
5768
5851
|
/*
|
|
5769
5852
|
* Theme variables cursedbelt's components read BY NAME (`var(--color-card)` in a style prop).
|
|
5770
5853
|
* Tailwind emits a theme variable only when the app's own pass sees it used, and a `var()` here is
|
|
5771
|
-
* that use — `@source inline` cannot mark one.
|
|
5854
|
+
* that use — `@source inline` cannot mark one. 13 variable(s), derived by
|
|
5772
5855
|
* scripts/generateUtilityStyles.ts → themeVariablesReadByName(). Nothing reads this property.
|
|
5773
5856
|
*/
|
|
5774
5857
|
@layer theme {
|
|
5775
5858
|
:root, :host {
|
|
5776
|
-
--cb-theme-read-by-name: var(--color-accent) var(--color-border) var(--color-card) var(--color-muted) var(--color-popover) var(--duration-base) var(--ease-out) var(--spacing) var(--text-caption) var(--text-sm);
|
|
5859
|
+
--cb-theme-read-by-name: var(--color-accent) var(--color-border) var(--color-card) var(--color-muted) var(--color-popover) var(--duration-base) var(--duration-slow) var(--ease-out) var(--press-scale) var(--press-scale-surface) var(--spacing) var(--text-caption) var(--text-sm);
|
|
5777
5860
|
}
|
|
5778
5861
|
}
|
package/dist/theme.css
CHANGED
|
@@ -896,6 +896,47 @@ body {
|
|
|
896
896
|
color: var(--foreground);
|
|
897
897
|
}
|
|
898
898
|
|
|
899
|
+
/*
|
|
900
|
+
* ───────────── Scrollbars: a thin capsule tinted to the pane (forge task 2912) ─────
|
|
901
|
+
*
|
|
902
|
+
* The browser's stock scrollbar is a grey trough with a grey slab in it — on Windows and
|
|
903
|
+
* Linux 15-17px of chrome down the side of every scrolling list, in the OS's colours, not
|
|
904
|
+
* the app's. Linear and Obsidian draw a thin capsule that tints toward the pane it sits on;
|
|
905
|
+
* the owner's brief (`owner-drafting-area/linear-art.md/app.css`) does the same, and so does
|
|
906
|
+
* every app that takes this stylesheet.
|
|
907
|
+
*
|
|
908
|
+
* `--scrollbar-thumb` is the token: unset, the thumb is the pane's own `--foreground` at 22%,
|
|
909
|
+
* resolved per element — so it follows `.dark`, the aurora and every look with no per-scope
|
|
910
|
+
* literal. A scope that wants another tint sets the token. `scrollbar-width`/`scrollbar-color`
|
|
911
|
+
* are the standard (Firefox, Chrome 121+, Safari 18.2+); the `::-webkit-scrollbar` rules are
|
|
912
|
+
* for the Safari that predates them, and Chrome ignores them once the standard pair is set.
|
|
913
|
+
* A Mac's overlay scrollbars keep their own behaviour — only their colour is ours.
|
|
914
|
+
*
|
|
915
|
+
* 🔴 `@layer base`, not bare: this file is unlayered, and an unlayered rule beats every
|
|
916
|
+
* layered one whatever its specificity — so a bare `*` here would have put a thumb back on
|
|
917
|
+
* every strip that hides its bar with the `[scrollbar-width:none]` utility (ChipFilterStrip,
|
|
918
|
+
* TagStrip, TopBar, SectionNav).
|
|
919
|
+
*/
|
|
920
|
+
@layer base {
|
|
921
|
+
* {
|
|
922
|
+
scrollbar-width: thin;
|
|
923
|
+
scrollbar-color: var(--scrollbar-thumb, color-mix(in oklab, var(--foreground) 22%, transparent)) transparent;
|
|
924
|
+
}
|
|
925
|
+
::-webkit-scrollbar {
|
|
926
|
+
width: 8px;
|
|
927
|
+
height: 8px;
|
|
928
|
+
}
|
|
929
|
+
::-webkit-scrollbar-track {
|
|
930
|
+
background: transparent;
|
|
931
|
+
}
|
|
932
|
+
::-webkit-scrollbar-thumb {
|
|
933
|
+
background: var(--scrollbar-thumb, color-mix(in oklab, var(--foreground) 22%, transparent));
|
|
934
|
+
border: 2px solid transparent;
|
|
935
|
+
border-radius: 999px;
|
|
936
|
+
background-clip: content-box;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
|
|
899
940
|
/*
|
|
900
941
|
* ───────────── The native <select>'s own list, which the PAGE cannot reach ────
|
|
901
942
|
*
|
|
@@ -1099,6 +1140,12 @@ option:disabled {
|
|
|
1099
1140
|
--duration-fast: 120ms; /* hover / press */
|
|
1100
1141
|
--duration-base: 200ms; /* popover */
|
|
1101
1142
|
--duration-slow: 300ms; /* modal */
|
|
1143
|
+
/* How far a control dips while it is held (Button: `active:scale-[var(--press-scale)]`). One
|
|
1144
|
+
token so every pressable surface answers a finger the same amount; 1 turns it off. */
|
|
1145
|
+
--press-scale: 0.97;
|
|
1146
|
+
/* The same answer for a whole card or row (`CardTapTarget`): a dip is proportional to size, so
|
|
1147
|
+
0.97 of a 400px card moves 12px and reads as a lurch. lib/press.ts has the contract. */
|
|
1148
|
+
--press-scale-surface: 0.99;
|
|
1102
1149
|
|
|
1103
1150
|
/* Fluid typography — headings only (fluid body text causes line-length drift).
|
|
1104
1151
|
Exposed as text-h1 / text-h2 / text-h3 font-size utilities. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cursedbelt",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.67.0",
|
|
4
4
|
"license": "ISC",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "The React design system of the cursedbelt split — components, styles, theme. cursedbelt-core below it; server tier in cursedbelt-server.",
|
package/src/react/Toast.tsx
CHANGED
|
@@ -82,7 +82,10 @@ export function Toaster({ style, ...props }: ToasterProps) {
|
|
|
82
82
|
closeButton
|
|
83
83
|
toastOptions={{
|
|
84
84
|
classNames: {
|
|
85
|
-
|
|
85
|
+
// The overlay curve and the slow speed (`lib/overlayMotion.ts`, forge task 2912) in place
|
|
86
|
+
// of sonner's 400ms `ease`. `!` because sonner's own `[data-sonner-toast]` rule sets the
|
|
87
|
+
// transition shorthand after this stylesheet; its reduced-motion rule still turns it off.
|
|
88
|
+
toast: 'rounded-lg border border-border bg-popover text-foreground shadow-overlay duration-[var(--duration-slow)]! ease-[var(--ease-out)]!',
|
|
86
89
|
title: 'text-sm font-medium',
|
|
87
90
|
// `!` because sonner colours these two with element rules of its own (`#3f3f3f` for a
|
|
88
91
|
// description, its grey scale for the close button) that no variable reaches.
|
|
@@ -2,6 +2,7 @@ import * as RadixAccordion from '@radix-ui/react-accordion';
|
|
|
2
2
|
import { ChevronRight } from 'lucide-react';
|
|
3
3
|
import type { ReactNode } from 'react';
|
|
4
4
|
import { cn } from '../lib/cn.js';
|
|
5
|
+
import { TAP_TARGET_HEIGHT } from '../lib/tapTarget.js';
|
|
5
6
|
|
|
6
7
|
export interface AccordionItem {
|
|
7
8
|
value: string;
|
|
@@ -67,7 +68,13 @@ export function Accordion({
|
|
|
67
68
|
<RadixAccordion.Header>
|
|
68
69
|
{/* Disabled = muted ink, as SelectableRow: half-opacity faded the chevron and the
|
|
69
70
|
divider-adjacent text into the surface (forge task 2594). */}
|
|
70
|
-
<RadixAccordion.Trigger
|
|
71
|
+
<RadixAccordion.Trigger
|
|
72
|
+
// `TAP_TARGET_HEIGHT`: a 41px header on a phone (family's Children/Siblings, forge task 2913) is under the 44pt floor — DESIGN.md §5.
|
|
73
|
+
className={cn(
|
|
74
|
+
'group flex w-full items-center justify-start gap-2 py-3 text-left text-sm font-medium text-foreground transition-colors hover:text-accent disabled:cursor-not-allowed disabled:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
|
|
75
|
+
TAP_TARGET_HEIGHT,
|
|
76
|
+
)}
|
|
77
|
+
>
|
|
71
78
|
{/* The arrow leads (FRM-18), and the trigger takes the rest of the row. */}
|
|
72
79
|
<ChevronRight aria-hidden className='size-4 shrink-0 text-muted-foreground transition-transform duration-200 group-data-[state=open]:rotate-90' />
|
|
73
80
|
<span className='min-w-0 flex-1'>{item.trigger}</span>
|
|
@@ -172,6 +172,22 @@ describe('Button', () => {
|
|
|
172
172
|
expect(getByRole('button').getAttribute('aria-disabled')).toBeNull();
|
|
173
173
|
});
|
|
174
174
|
|
|
175
|
+
test('🔴 a press is answered: the control dips to --press-scale while held, eased, and a link never does', () => {
|
|
176
|
+
const cls = render(<Button tooltip='B'>B</Button>).getByRole('button').className;
|
|
177
|
+
expect(cls).toContain('active:scale-[var(--press-scale)]');
|
|
178
|
+
// The dip eases in and out like the colours do — `scale` (the property Tailwind v4's
|
|
179
|
+
// `scale-*` writes, not `transform`) is in the transition list.
|
|
180
|
+
expect(cls).toMatch(/transition-\[[^\]]*\bscale\b[^\]]*\]/);
|
|
181
|
+
// Nothing happened on a refused press, so nothing dips; reduced motion turns it off.
|
|
182
|
+
expect(cls).toContain('aria-disabled:active:scale-100');
|
|
183
|
+
expect(cls).toContain('motion-reduce:active:scale-100');
|
|
184
|
+
cleanup();
|
|
185
|
+
const link = render(<Button tooltip='L' variant='link'>L</Button>).getByRole('button').className.split(/\s+/);
|
|
186
|
+
// tailwind-merge keeps the later `active:scale-100` and drops the base dip for a link.
|
|
187
|
+
expect(link).toContain('active:scale-100');
|
|
188
|
+
expect(link).not.toContain('active:scale-[var(--press-scale)]');
|
|
189
|
+
});
|
|
190
|
+
|
|
175
191
|
test('a pressed toggle and a refused control are drawn by the variant classes', () => {
|
|
176
192
|
const cls = render(<Button tooltip='B'>B</Button>).getByRole('button').className;
|
|
177
193
|
expect(cls).toContain('aria-pressed:border-accent');
|
|
@@ -14,6 +14,7 @@ import { cn } from '../lib/cn.js';
|
|
|
14
14
|
import { Tooltip, type TooltipMobile, type TooltipPlacement } from './Tooltip.js';
|
|
15
15
|
import { TAP_TARGET_HEIGHT } from '../lib/tapTarget.js';
|
|
16
16
|
import { RAW_BUTTON } from '../lib/cn.js';
|
|
17
|
+
import { PRESS } from '../lib/press.js';
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* The single source of truth for every interactive element that triggers an action.
|
|
@@ -32,7 +33,9 @@ import { RAW_BUTTON } from '../lib/cn.js';
|
|
|
32
33
|
export const buttonVariants = cva(
|
|
33
34
|
[
|
|
34
35
|
'relative inline-flex items-center justify-center gap-2 rounded-md font-medium',
|
|
35
|
-
|
|
36
|
+
// 🔴 TACTILE (forge task family-app-ux-overhaul, 2026-10-06): a press is answered — eased
|
|
37
|
+
// colours and a `--press-scale` dip while held. The contract and who is exempt: `lib/press.ts`.
|
|
38
|
+
PRESS,
|
|
36
39
|
TAP_TARGET_HEIGHT, // ≥44px touch target on coarse pointers
|
|
37
40
|
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:ring-offset-background',
|
|
38
41
|
// Disabled = muted surface + faded + inert (never color-alone): clearly off, not a low-contrast haze.
|
|
@@ -129,7 +132,11 @@ export const buttonVariants = cva(
|
|
|
129
132
|
// before the size's `px-3`/`px-4` and fixed height, so the size won the merge and every link
|
|
130
133
|
// button — sized or on the `md` default — drew a padded box: TotpEntry's "Use a recovery code
|
|
131
134
|
// instead" sat 12px in from the column every other row starts on.
|
|
132
|
-
compoundVariants: [
|
|
135
|
+
compoundVariants: [
|
|
136
|
+
{ variant: 'link', size: ['sm', 'md', 'lg'], class: 'h-auto px-0 py-0' },
|
|
137
|
+
// A link is text inside a sentence: it underlines on hover and does not dip on press.
|
|
138
|
+
{ variant: 'link', class: 'active:scale-100' },
|
|
139
|
+
],
|
|
133
140
|
defaultVariants: { variant: 'secondary', size: 'md' },
|
|
134
141
|
},
|
|
135
142
|
);
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type ReactNode, useRef } from 'react';
|
|
2
2
|
import { cn } from '../lib/cn.js';
|
|
3
|
+
import { PRESS_SURFACE } from '../lib/press.js';
|
|
4
|
+
import { TAP_TARGET_HEIGHT } from '../lib/tapTarget.js';
|
|
3
5
|
import { hasSelectionWithin } from '../lib/textSelection.js';
|
|
4
6
|
|
|
5
7
|
export interface CardTapTargetProps {
|
|
@@ -67,7 +69,10 @@ export const CardTapTarget = ({
|
|
|
67
69
|
onClick();
|
|
68
70
|
}
|
|
69
71
|
}}
|
|
70
|
-
|
|
72
|
+
// `TAP_TARGET_HEIGHT`: a tappable row on a phone answers to a thumb — family's 35px value
|
|
73
|
+
// rows (`.ft-row`, forge task 2913) were under the 44pt floor. DESIGN.md §5.
|
|
74
|
+
// `PRESS_SURFACE`: the card answers a press with a dip sized for a surface (forge task 2912).
|
|
75
|
+
className={cn('cursor-pointer touch-manipulation text-left', TAP_TARGET_HEIGHT, PRESS_SURFACE, className)}
|
|
71
76
|
{...rest}
|
|
72
77
|
>
|
|
73
78
|
{children}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
import { cn, RAW_BUTTON } from '../lib/cn.js';
|
|
3
|
+
import { PRESS } from '../lib/press.js';
|
|
3
4
|
import { ScrollArea } from './ScrollArea.js';
|
|
4
5
|
|
|
5
6
|
export interface ChipOption {
|
|
@@ -122,7 +123,8 @@ function Chip({ active, onClick, children }: ChipProps) {
|
|
|
122
123
|
RAW_BUTTON,
|
|
123
124
|
// 44 px min tap target height via py + min-h (STANDARDS §4a). px-4 keeps every
|
|
124
125
|
// pill's internal padding identical regardless of label length.
|
|
125
|
-
'inline-flex min-h-11 shrink-0 cursor-pointer items-center rounded-full px-4 text-sm font-medium
|
|
126
|
+
'inline-flex min-h-11 shrink-0 cursor-pointer items-center rounded-full px-4 text-sm font-medium',
|
|
127
|
+
PRESS,
|
|
126
128
|
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
|
|
127
129
|
// Soft active state — an accent tint + accent text (the standardized active
|
|
128
130
|
// treatment shared with nav items and the `accent` Badge tone), not a stark
|