@bearmenu/ui 0.8.25 → 0.8.27
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/{chunk-VEGFQSZA.js → chunk-F3XK34DV.js} +8 -0
- package/dist/chunk-L3CDXVEP.js +56 -0
- package/dist/{chunk-CZK2MRS2.js → chunk-VEFKZIK6.js} +13 -3
- package/dist/components/badge.d.ts +1 -1
- package/dist/components/banner.d.ts +36 -0
- package/dist/components/banner.js +29 -0
- package/dist/components/button.d.ts +1 -1
- package/dist/components/card.d.ts +2 -2
- package/dist/components/checkbox.d.ts +9 -2
- package/dist/components/checkbox.js +1 -1
- package/dist/components/command.d.ts +15 -15
- package/dist/components/currency-input.js +1 -1
- package/dist/components/date-input.js +1 -1
- package/dist/components/event-detail-panel.js +1 -1
- package/dist/components/event-index-row.js +1 -1
- package/dist/components/event-list-row-wide.js +1 -1
- package/dist/components/event-list-row.js +1 -1
- package/dist/components/field.d.ts +15 -1
- package/dist/components/field.js +64 -21
- package/dist/components/input.d.ts +1 -0
- package/dist/components/input.js +1 -1
- package/dist/components/item.d.ts +2 -2
- package/dist/components/kitchen-dossier.js +1 -1
- package/dist/components/multi-select-combobox.js +1 -1
- package/dist/components/multi-select-menu.js +1 -1
- package/dist/components/place-card.js +1 -1
- package/dist/components/spinner.d.ts +2 -2
- package/dist/components/tag.d.ts +2 -2
- package/dist/components/text.d.ts +3 -3
- package/dist/components/textarea.d.ts +10 -3
- package/dist/components/textarea.js +21 -6
- package/dist/components/toggle-group.js +5 -5
- package/dist/components/toggle.d.ts +1 -1
- package/dist/components/toggle.js +1 -1
- package/package.json +207 -23
- package/src/components/banner.stories.tsx +36 -0
- package/src/components/banner.tsx +58 -0
- package/src/components/booking-details-primitives.test.tsx +75 -0
- package/src/components/checkbox.tsx +49 -23
- package/src/components/field.stories.tsx +51 -1
- package/src/components/field.tsx +70 -9
- package/src/components/input.tsx +13 -2
- package/src/components/textarea.tsx +25 -7
- package/src/components/toggle-group.tsx +4 -4
- package/src/components/toggle.tsx +8 -0
- package/dist/chunk-NMEVJT5Q.js +0 -26
|
@@ -4,11 +4,11 @@ import { VariantProps } from 'class-variance-authority';
|
|
|
4
4
|
|
|
5
5
|
declare const spinnerVariants: (props?: ({
|
|
6
6
|
size?: "default" | "xs" | "sm" | "lg" | "xl" | null | undefined;
|
|
7
|
-
tone?: "
|
|
7
|
+
tone?: "default" | "destructive" | "inherit" | "primary" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
declare const Spinner: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLSpanElement> & VariantProps<(props?: ({
|
|
10
10
|
size?: "default" | "xs" | "sm" | "lg" | "xl" | null | undefined;
|
|
11
|
-
tone?: "
|
|
11
|
+
tone?: "default" | "destructive" | "inherit" | "primary" | null | undefined;
|
|
12
12
|
} & class_variance_authority_types.ClassProp) | undefined) => string> & {
|
|
13
13
|
/** Visually-hidden label for screen readers. Defaults to "Loading". */
|
|
14
14
|
label?: string;
|
package/dist/components/tag.d.ts
CHANGED
|
@@ -3,11 +3,11 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const tagVariants: (props?: ({
|
|
6
|
-
variant?: "default" | "destructive" | "
|
|
6
|
+
variant?: "default" | "destructive" | "warning" | "success" | "primary" | "outline" | "quiet" | null | undefined;
|
|
7
7
|
size?: "default" | "sm" | "lg" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
declare const Tag: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLSpanElement> & VariantProps<(props?: ({
|
|
10
|
-
variant?: "default" | "destructive" | "
|
|
10
|
+
variant?: "default" | "destructive" | "warning" | "success" | "primary" | "outline" | "quiet" | null | undefined;
|
|
11
11
|
size?: "default" | "sm" | "lg" | null | undefined;
|
|
12
12
|
} & class_variance_authority_types.ClassProp) | undefined) => string> & {
|
|
13
13
|
onRemove?: () => void;
|
|
@@ -22,9 +22,9 @@ import { VariantProps } from 'class-variance-authority';
|
|
|
22
22
|
* Weights are 400 / 600 / 700. 500 is not in the system.
|
|
23
23
|
*/
|
|
24
24
|
declare const textVariants: (props?: ({
|
|
25
|
-
variant?: "
|
|
26
|
-
color?: "
|
|
27
|
-
weight?: "bold" | "
|
|
25
|
+
variant?: "small" | "display" | "h1" | "h2" | "h3" | "h4" | "body-lg" | "body" | "body-sm" | "caption" | "label" | "overline" | null | undefined;
|
|
26
|
+
color?: "default" | "destructive" | "inherit" | "muted" | "primary" | "primary-foreground" | null | undefined;
|
|
27
|
+
weight?: "bold" | "normal" | "medium" | "semibold" | null | undefined;
|
|
28
28
|
leading?: "none" | "normal" | "tight" | "snug" | "relaxed" | "loose" | null | undefined;
|
|
29
29
|
tracking?: "normal" | "tight" | "wide" | "wider" | null | undefined;
|
|
30
30
|
wrap?: "balance" | "pretty" | "nowrap" | null | undefined;
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
1
2
|
import * as React from 'react';
|
|
3
|
+
import { VariantProps } from 'class-variance-authority';
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
+
declare const textareaVariants: (props?: ({
|
|
6
|
+
appearance?: "default" | "booking" | null | undefined;
|
|
7
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
8
|
+
type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement> & VariantProps<typeof textareaVariants>;
|
|
9
|
+
declare const Textarea: React.ForwardRefExoticComponent<React.TextareaHTMLAttributes<HTMLTextAreaElement> & VariantProps<(props?: ({
|
|
10
|
+
appearance?: "default" | "booking" | null | undefined;
|
|
11
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string> & React.RefAttributes<HTMLTextAreaElement>>;
|
|
5
12
|
|
|
6
|
-
export { Textarea, type TextareaProps };
|
|
13
|
+
export { Textarea, type TextareaProps, textareaVariants };
|
|
@@ -1,19 +1,34 @@
|
|
|
1
1
|
import { cn } from '../chunk-FEK5XGZW.js';
|
|
2
2
|
import { __objRest, __spreadValues } from '../chunk-MMUBH76A.js';
|
|
3
3
|
import * as React from 'react';
|
|
4
|
+
import { cva } from 'class-variance-authority';
|
|
4
5
|
import { jsx } from 'react/jsx-runtime';
|
|
5
6
|
|
|
7
|
+
var textareaVariants = cva(
|
|
8
|
+
"flex min-h-20 w-full rounded-xl border border-border bg-input/50 px-4 py-3 text-base transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background focus-visible:bg-input disabled:cursor-not-allowed disabled:opacity-50 resize-y aria-invalid:border-destructive aria-invalid:focus-visible:ring-destructive/40",
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
/**
|
|
12
|
+
* The booking flow's note field (booking flow.html, `.in.ta`): the
|
|
13
|
+
* `Input` booking appearance's ground, radius and type, 66px tall with
|
|
14
|
+
* a 12px × 13px inset, and no drag handle — the design draws none.
|
|
15
|
+
*/
|
|
16
|
+
appearance: {
|
|
17
|
+
default: "",
|
|
18
|
+
booking: "min-h-[66px] resize-none rounded-[11px] bg-card px-[13px] py-3 text-[14px] leading-[1.4] focus-visible:bg-card aria-invalid:border-[oklch(0.52_0.16_25)] dark:aria-invalid:border-destructive"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
defaultVariants: { appearance: "default" }
|
|
22
|
+
}
|
|
23
|
+
);
|
|
6
24
|
var Textarea = React.forwardRef(
|
|
7
25
|
(_a, ref) => {
|
|
8
|
-
var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
|
|
26
|
+
var _b = _a, { className, appearance } = _b, props = __objRest(_b, ["className", "appearance"]);
|
|
9
27
|
return /* @__PURE__ */ jsx(
|
|
10
28
|
"textarea",
|
|
11
29
|
__spreadValues({
|
|
12
30
|
"data-slot": "textarea",
|
|
13
|
-
className: cn(
|
|
14
|
-
"flex min-h-20 w-full rounded-xl border border-border bg-input/50 px-4 py-3 text-base transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background focus-visible:bg-input disabled:cursor-not-allowed disabled:opacity-50 resize-y aria-invalid:border-destructive aria-invalid:focus-visible:ring-destructive/40",
|
|
15
|
-
className
|
|
16
|
-
),
|
|
31
|
+
className: cn(textareaVariants({ appearance }), className),
|
|
17
32
|
ref
|
|
18
33
|
}, props)
|
|
19
34
|
);
|
|
@@ -21,4 +36,4 @@ var Textarea = React.forwardRef(
|
|
|
21
36
|
);
|
|
22
37
|
Textarea.displayName = "Textarea";
|
|
23
38
|
|
|
24
|
-
export { Textarea };
|
|
39
|
+
export { Textarea, textareaVariants };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { toggleVariants } from '../chunk-
|
|
1
|
+
import { toggleVariants } from '../chunk-F3XK34DV.js';
|
|
2
2
|
import { cn } from '../chunk-FEK5XGZW.js';
|
|
3
3
|
import { __objRest, __spreadProps, __spreadValues } from '../chunk-MMUBH76A.js';
|
|
4
4
|
import * as React from 'react';
|
|
@@ -72,11 +72,11 @@ function ToggleGroupItem(_a) {
|
|
|
72
72
|
}),
|
|
73
73
|
"min-w-0 flex-1 shrink-0 shadow-none focus:z-10 focus-visible:z-10 data-[variant=outline]:border-l-0 data-[variant=outline]:first:border-l",
|
|
74
74
|
resolved === "segmented" ? "rounded-full px-0 data-[state=on]:shadow-[var(--shadow-card)]" : (
|
|
75
|
-
// Tabs and chips size
|
|
76
|
-
//
|
|
77
|
-
resolved === "tab" ? "
|
|
75
|
+
// Tabs and chips size themselves (`toggleVariants`' compounds);
|
|
76
|
+
// the item's own rounding must not square them off.
|
|
77
|
+
resolved === "tab" ? "rounded-full" : resolved === "chip" ? (
|
|
78
78
|
// A chip keeps its own width, so the row can wrap.
|
|
79
|
-
"
|
|
79
|
+
"flex-none rounded-full"
|
|
80
80
|
) : "rounded-none first:rounded-l-md last:rounded-r-md"
|
|
81
81
|
),
|
|
82
82
|
className
|
|
@@ -5,7 +5,7 @@ import * as TogglePrimitive from '@radix-ui/react-toggle';
|
|
|
5
5
|
import { VariantProps } from 'class-variance-authority';
|
|
6
6
|
|
|
7
7
|
declare const toggleVariants: (props?: ({
|
|
8
|
-
variant?: "
|
|
8
|
+
variant?: "default" | "tab" | "outline" | "chip" | "segmented" | null | undefined;
|
|
9
9
|
size?: "default" | "sm" | "lg" | null | undefined;
|
|
10
10
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
11
11
|
declare function Toggle({ className, variant, size, ...props }: React.ComponentProps<typeof TogglePrimitive.Root> & VariantProps<typeof toggleVariants>): react_jsx_runtime.JSX.Element;
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bearmenu/ui",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.27",
|
|
4
|
+
"packageManager": "pnpm@10.28.1",
|
|
4
5
|
"description": "BearMenu design system — shared UI tokens, primitives, and components",
|
|
5
6
|
"license": "UNLICENSED",
|
|
6
7
|
"repository": {
|
|
@@ -16,20 +17,213 @@
|
|
|
16
17
|
"src"
|
|
17
18
|
],
|
|
18
19
|
"exports": {
|
|
20
|
+
"./components/accordion": "./src/components/accordion.tsx",
|
|
21
|
+
"./components/alert": "./src/components/alert.tsx",
|
|
22
|
+
"./components/alert-dialog": "./src/components/alert-dialog.tsx",
|
|
23
|
+
"./components/aspect-ratio": "./src/components/aspect-ratio.tsx",
|
|
24
|
+
"./components/avatar": "./src/components/avatar.tsx",
|
|
25
|
+
"./components/badge": "./src/components/badge.tsx",
|
|
26
|
+
"./components/banner": "./src/components/banner.tsx",
|
|
27
|
+
"./components/booking-row": "./src/components/booking-row.tsx",
|
|
28
|
+
"./components/booking-summary-card": "./src/components/booking-summary-card.tsx",
|
|
29
|
+
"./components/breadcrumb": "./src/components/breadcrumb.tsx",
|
|
30
|
+
"./components/button": "./src/components/button.tsx",
|
|
31
|
+
"./components/button-group": "./src/components/button-group.tsx",
|
|
32
|
+
"./components/calendar": "./src/components/calendar.tsx",
|
|
33
|
+
"./components/card": "./src/components/card.tsx",
|
|
34
|
+
"./components/carousel": "./src/components/carousel.tsx",
|
|
35
|
+
"./components/category-deck": "./src/components/category-deck.tsx",
|
|
36
|
+
"./components/checkbox": "./src/components/checkbox.tsx",
|
|
37
|
+
"./components/circular-progress": "./src/components/circular-progress.tsx",
|
|
38
|
+
"./components/coach-marks": "./src/components/coach-marks.tsx",
|
|
39
|
+
"./components/collapsible": "./src/components/collapsible.tsx",
|
|
40
|
+
"./components/combobox": "./src/components/combobox.tsx",
|
|
41
|
+
"./components/command": "./src/components/command.tsx",
|
|
42
|
+
"./components/concept-card": "./src/components/concept-card.tsx",
|
|
43
|
+
"./components/concept-compare": "./src/components/concept-compare.tsx",
|
|
44
|
+
"./components/concept-compare-rail": "./src/components/concept-compare-rail.tsx",
|
|
45
|
+
"./components/concept-convergence": "./src/components/concept-convergence.tsx",
|
|
46
|
+
"./components/convergence": "./src/components/convergence.tsx",
|
|
47
|
+
"./components/coverflow": "./src/components/coverflow.tsx",
|
|
48
|
+
"./components/currency-input": "./src/components/currency-input.tsx",
|
|
49
|
+
"./components/date-input": "./src/components/date-input.tsx",
|
|
50
|
+
"./components/day-rail-chip": "./src/components/day-rail-chip.tsx",
|
|
51
|
+
"./components/description-list": "./src/components/description-list.tsx",
|
|
52
|
+
"./components/dialog": "./src/components/dialog.tsx",
|
|
53
|
+
"./components/doorway-tiles": "./src/components/doorway-tiles.tsx",
|
|
54
|
+
"./components/drawer": "./src/components/drawer.tsx",
|
|
55
|
+
"./components/drift-rail": "./src/components/drift-rail.tsx",
|
|
56
|
+
"./components/dropdown-menu": "./src/components/dropdown-menu.tsx",
|
|
57
|
+
"./components/empty-state": "./src/components/empty-state.tsx",
|
|
58
|
+
"./components/event-card": "./src/components/event-card.tsx",
|
|
59
|
+
"./components/event-compact-row": "./src/components/event-compact-row.tsx",
|
|
60
|
+
"./components/event-day-header": "./src/components/event-day-header.tsx",
|
|
61
|
+
"./components/event-day-separator": "./src/components/event-day-separator.tsx",
|
|
62
|
+
"./components/event-detail-panel": "./src/components/event-detail-panel.tsx",
|
|
63
|
+
"./components/event-hub-hero": "./src/components/event-hub-hero.tsx",
|
|
64
|
+
"./components/event-index-row": "./src/components/event-index-row.tsx",
|
|
65
|
+
"./components/event-list-row": "./src/components/event-list-row.tsx",
|
|
66
|
+
"./components/event-list-row-wide": "./src/components/event-list-row-wide.tsx",
|
|
67
|
+
"./components/event-poster-fallback": "./src/components/event-poster-fallback.tsx",
|
|
68
|
+
"./components/event-tonight-strip": "./src/components/event-tonight-strip.tsx",
|
|
69
|
+
"./components/event-types": "./src/components/event-types.ts",
|
|
70
|
+
"./components/events-empty-state": "./src/components/events-empty-state.tsx",
|
|
71
|
+
"./components/explainer-steps": "./src/components/explainer-steps.tsx",
|
|
72
|
+
"./components/facet-group": "./src/components/facet-group.tsx",
|
|
73
|
+
"./components/featured-rail-item": "./src/components/featured-rail-item.tsx",
|
|
74
|
+
"./components/field": "./src/components/field.tsx",
|
|
75
|
+
"./components/filter-category-row": "./src/components/filter-category-row.tsx",
|
|
76
|
+
"./components/form": "./src/components/form.tsx",
|
|
77
|
+
"./components/glass-ground": "./src/components/glass-ground.tsx",
|
|
78
|
+
"./components/grade-atom": "./src/components/grade-atom.tsx",
|
|
79
|
+
"./components/haptic-switch": "./src/components/haptic-switch.tsx",
|
|
80
|
+
"./components/hold-countdown": "./src/components/hold-countdown.tsx",
|
|
81
|
+
"./components/hub-surface": "./src/components/hub-surface.tsx",
|
|
82
|
+
"./components/hue-chip": "./src/components/hue-chip.tsx",
|
|
83
|
+
"./components/icon": "./src/components/icon.tsx",
|
|
84
|
+
"./components/input": "./src/components/input.tsx",
|
|
85
|
+
"./components/input-group": "./src/components/input-group.tsx",
|
|
86
|
+
"./components/input-otp": "./src/components/input-otp.tsx",
|
|
87
|
+
"./components/item": "./src/components/item.tsx",
|
|
88
|
+
"./components/kbd": "./src/components/kbd.tsx",
|
|
89
|
+
"./components/label": "./src/components/label.tsx",
|
|
90
|
+
"./components/kitchen-dossier": "./src/components/kitchen-dossier.tsx",
|
|
91
|
+
"./components/lazy-markdown": "./src/components/lazy-markdown.tsx",
|
|
92
|
+
"./components/link-button": "./src/components/link-button.tsx",
|
|
93
|
+
"./components/markdown-renderer": "./src/components/markdown-renderer.tsx",
|
|
94
|
+
"./components/menu-dead-end": "./src/components/menu-dead-end.tsx",
|
|
95
|
+
"./components/menu-family-block": "./src/components/menu-family-block.tsx",
|
|
96
|
+
"./components/menu-family-card": "./src/components/menu-family-card.tsx",
|
|
97
|
+
"./components/menu-field": "./src/components/menu-field.tsx",
|
|
98
|
+
"./components/menu-filter-chips": "./src/components/menu-filter-chips.tsx",
|
|
99
|
+
"./components/menu-group-rows": "./src/components/menu-group-rows.tsx",
|
|
100
|
+
"./components/menu-hub-hero": "./src/components/menu-hub-hero.tsx",
|
|
101
|
+
"./components/menu-index-header": "./src/components/menu-index-header.tsx",
|
|
102
|
+
"./components/menu-index-list": "./src/components/menu-index-list.tsx",
|
|
103
|
+
"./components/menu-intent-hero": "./src/components/menu-intent-hero.tsx",
|
|
104
|
+
"./components/menu-item": "./src/components/menu-item.tsx",
|
|
105
|
+
"./components/menu-kitchen-list": "./src/components/menu-kitchen-list.tsx",
|
|
106
|
+
"./components/menu-mocks": "./src/components/menu-mocks.ts",
|
|
107
|
+
"./components/menu-types": "./src/components/menu-types.ts",
|
|
108
|
+
"./components/motion-icon": "./src/components/motion-icon.tsx",
|
|
109
|
+
"./components/motion-icon-actions": "./src/components/motion-icon-actions.tsx",
|
|
110
|
+
"./components/motion-icon-controls": "./src/components/motion-icon-controls.tsx",
|
|
111
|
+
"./components/motion-icon-set": "./src/components/motion-icon-set.tsx",
|
|
112
|
+
"./components/multi-select-combobox": "./src/components/multi-select-combobox.tsx",
|
|
113
|
+
"./components/multi-select-menu": "./src/components/multi-select-menu.tsx",
|
|
114
|
+
"./components/native-select": "./src/components/native-select.tsx",
|
|
115
|
+
"./components/open-now-list": "./src/components/open-now-list.tsx",
|
|
116
|
+
"./components/pagination": "./src/components/pagination.tsx",
|
|
117
|
+
"./components/party-counter": "./src/components/party-counter.tsx",
|
|
118
|
+
"./components/phone-frame": "./src/components/phone-frame.tsx",
|
|
119
|
+
"./components/photo-ground": "./src/components/photo-ground.tsx",
|
|
120
|
+
"./components/place-about-tab": "./src/components/place-about-tab.tsx",
|
|
121
|
+
"./components/place-card": "./src/components/place-card.tsx",
|
|
122
|
+
"./components/place-details-mobile": "./src/components/place-details-mobile.tsx",
|
|
123
|
+
"./components/place-schedule-week": "./src/components/place-schedule-week.tsx",
|
|
124
|
+
"./components/place-types": "./src/components/place-types.ts",
|
|
125
|
+
"./components/popover": "./src/components/popover.tsx",
|
|
126
|
+
"./components/poster-stack": "./src/components/poster-stack.tsx",
|
|
127
|
+
"./components/poster-tape": "./src/components/poster-tape.tsx",
|
|
128
|
+
"./components/poster-wall": "./src/components/poster-wall.tsx",
|
|
129
|
+
"./components/progress": "./src/components/progress.tsx",
|
|
130
|
+
"./components/qa-block": "./src/components/qa-block.tsx",
|
|
131
|
+
"./components/quiet-stretch": "./src/components/quiet-stretch.tsx",
|
|
132
|
+
"./components/radio-group": "./src/components/radio-group.tsx",
|
|
133
|
+
"./components/rating": "./src/components/rating.tsx",
|
|
134
|
+
"./components/scroll-area": "./src/components/scroll-area.tsx",
|
|
135
|
+
"./components/scroll-fade": "./src/components/scroll-fade.tsx",
|
|
136
|
+
"./components/search-bar": "./src/components/search-bar.tsx",
|
|
137
|
+
"./components/searchable-select": "./src/components/searchable-select.tsx",
|
|
138
|
+
"./components/section-header": "./src/components/section-header.tsx",
|
|
139
|
+
"./components/segmented-nav": "./src/components/segmented-nav.tsx",
|
|
140
|
+
"./components/select": "./src/components/select.tsx",
|
|
141
|
+
"./components/selection-bar": "./src/components/selection-bar.tsx",
|
|
142
|
+
"./components/separator": "./src/components/separator.tsx",
|
|
143
|
+
"./components/sheet": "./src/components/sheet.tsx",
|
|
144
|
+
"./components/signature-chip": "./src/components/signature-chip.tsx",
|
|
145
|
+
"./components/skeleton": "./src/components/skeleton.tsx",
|
|
146
|
+
"./components/skeleton-card": "./src/components/skeleton-card.tsx",
|
|
147
|
+
"./components/slider": "./src/components/slider.tsx",
|
|
148
|
+
"./components/sliding-panels": "./src/components/sliding-panels.tsx",
|
|
149
|
+
"./components/sonner": "./src/components/sonner.tsx",
|
|
150
|
+
"./components/sort-option-list": "./src/components/sort-option-list.tsx",
|
|
151
|
+
"./components/spinner": "./src/components/spinner.tsx",
|
|
152
|
+
"./components/stat-banner": "./src/components/stat-banner.tsx",
|
|
153
|
+
"./components/stepper": "./src/components/stepper.tsx",
|
|
154
|
+
"./components/sticky-container": "./src/components/sticky-container.tsx",
|
|
155
|
+
"./components/story": "./src/components/story.tsx",
|
|
156
|
+
"./components/switch": "./src/components/switch.tsx",
|
|
157
|
+
"./components/table": "./src/components/table.tsx",
|
|
158
|
+
"./components/tabs": "./src/components/tabs.tsx",
|
|
159
|
+
"./components/tag": "./src/components/tag.tsx",
|
|
160
|
+
"./components/tag-group": "./src/components/tag-group.tsx",
|
|
161
|
+
"./components/text": "./src/components/text.tsx",
|
|
162
|
+
"./components/textarea": "./src/components/textarea.tsx",
|
|
163
|
+
"./components/time-slot": "./src/components/time-slot.tsx",
|
|
164
|
+
"./components/timeline-day": "./src/components/timeline-day.tsx",
|
|
165
|
+
"./components/timeline-hour": "./src/components/timeline-hour.tsx",
|
|
166
|
+
"./components/timeline-hour-puck": "./src/components/timeline-hour-puck.tsx",
|
|
167
|
+
"./components/toggle": "./src/components/toggle.tsx",
|
|
168
|
+
"./components/toggle-group": "./src/components/toggle-group.tsx",
|
|
169
|
+
"./components/tooltip": "./src/components/tooltip.tsx",
|
|
170
|
+
"./components/top-comparison": "./src/components/top-comparison.tsx",
|
|
171
|
+
"./components/top-cross-link": "./src/components/top-cross-link.tsx",
|
|
172
|
+
"./components/top-ranking-entry": "./src/components/top-ranking-entry.tsx",
|
|
173
|
+
"./components/top-ranking-hero": "./src/components/top-ranking-hero.tsx",
|
|
174
|
+
"./components/top-ranking-legend": "./src/components/top-ranking-legend.tsx",
|
|
175
|
+
"./components/top-types": "./src/components/top-types.ts",
|
|
176
|
+
"./components/use-mobile": "./src/components/use-mobile.tsx",
|
|
177
|
+
"./components/venue-events-block": "./src/components/venue-events-block.tsx",
|
|
178
|
+
"./components/venue-grade-dimensions": "./src/components/venue-grade-dimensions.tsx",
|
|
179
|
+
"./components/venue-quotes": "./src/components/venue-quotes.tsx",
|
|
180
|
+
"./components/venue-wall": "./src/components/venue-wall.tsx",
|
|
181
|
+
"./components/weekday-chip": "./src/components/weekday-chip.tsx",
|
|
182
|
+
"./components/weekday-theme-banner": "./src/components/weekday-theme-banner.tsx",
|
|
183
|
+
"./components/weekend-panel": "./src/components/weekend-panel.tsx",
|
|
19
184
|
"./globals.css": "./src/globals.css",
|
|
20
|
-
"./
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
"./hooks
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"./lib
|
|
29
|
-
|
|
30
|
-
|
|
185
|
+
"./hooks/use-drag-swipe": "./src/hooks/use-drag-swipe.ts",
|
|
186
|
+
"./hooks/use-haptic": "./src/hooks/use-haptic.ts",
|
|
187
|
+
"./hooks/use-media-query": "./src/hooks/use-media-query.ts",
|
|
188
|
+
"./hooks/use-mobile": "./src/hooks/use-mobile.ts",
|
|
189
|
+
"./hooks/use-mounted-theme": "./src/hooks/use-mounted-theme.ts",
|
|
190
|
+
"./hooks/use-sticky": "./src/hooks/use-sticky.ts",
|
|
191
|
+
"./lib/card-hover": "./src/lib/card-hover.ts",
|
|
192
|
+
"./lib/grade": "./src/lib/grade.ts",
|
|
193
|
+
"./lib/icon-depth": "./src/lib/icon-depth.ts",
|
|
194
|
+
"./lib/icon-registry": "./src/lib/icon-registry.ts",
|
|
195
|
+
"./lib/motion": "./src/lib/motion.ts",
|
|
196
|
+
"./lib/overlay-pill": "./src/lib/overlay-pill.ts",
|
|
197
|
+
"./lib/utils": "./src/lib/utils.ts"
|
|
198
|
+
},
|
|
199
|
+
"publishConfig": {
|
|
200
|
+
"exports": {
|
|
201
|
+
"./globals.css": "./src/globals.css",
|
|
202
|
+
"./components/*": {
|
|
203
|
+
"types": "./dist/components/*.d.ts",
|
|
204
|
+
"import": "./dist/components/*.js"
|
|
205
|
+
},
|
|
206
|
+
"./hooks/*": {
|
|
207
|
+
"types": "./dist/hooks/*.d.ts",
|
|
208
|
+
"import": "./dist/hooks/*.js"
|
|
209
|
+
},
|
|
210
|
+
"./lib/*": {
|
|
211
|
+
"types": "./dist/lib/*.d.ts",
|
|
212
|
+
"import": "./dist/lib/*.js"
|
|
213
|
+
}
|
|
31
214
|
}
|
|
32
215
|
},
|
|
216
|
+
"scripts": {
|
|
217
|
+
"storybook": "storybook dev -p 6006",
|
|
218
|
+
"build-storybook": "storybook build",
|
|
219
|
+
"build": "tsup",
|
|
220
|
+
"dev": "tsup --watch",
|
|
221
|
+
"typecheck": "tsc --noEmit",
|
|
222
|
+
"test": "vitest run",
|
|
223
|
+
"test:watch": "vitest",
|
|
224
|
+
"clean": "rm -rf dist",
|
|
225
|
+
"prepublishOnly": "pnpm run build"
|
|
226
|
+
},
|
|
33
227
|
"peerDependencies": {
|
|
34
228
|
"@hookform/resolvers": "^3.0.0 || ^5.0.0",
|
|
35
229
|
"@radix-ui/react-accordion": "*",
|
|
@@ -138,15 +332,5 @@
|
|
|
138
332
|
"vaul": "^1.1.2",
|
|
139
333
|
"vitest": "^4.1.5",
|
|
140
334
|
"zod": "^3.25.67"
|
|
141
|
-
},
|
|
142
|
-
"scripts": {
|
|
143
|
-
"storybook": "storybook dev -p 6006",
|
|
144
|
-
"build-storybook": "storybook build",
|
|
145
|
-
"build": "tsup",
|
|
146
|
-
"dev": "tsup --watch",
|
|
147
|
-
"typecheck": "tsc --noEmit",
|
|
148
|
-
"test": "vitest run",
|
|
149
|
-
"test:watch": "vitest",
|
|
150
|
-
"clean": "rm -rf dist"
|
|
151
335
|
}
|
|
152
|
-
}
|
|
336
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { TriangleAlert } from "lucide-react";
|
|
3
|
+
import { Banner } from "./banner";
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof Banner> = {
|
|
6
|
+
title: "Booking/Banner",
|
|
7
|
+
component: Banner,
|
|
8
|
+
tags: ["autodocs"],
|
|
9
|
+
parameters: {
|
|
10
|
+
docs: {
|
|
11
|
+
description: {
|
|
12
|
+
component:
|
|
13
|
+
"A short inline note inside a flow: the booking flow's 'time just went', 'no table was booked', 'this venue does not take bookings'. Borderless, unlike Alert.",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
decorators: [(Story) => <div className="w-[335px]">{Story()}</div>],
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default meta;
|
|
21
|
+
type Story = StoryObj<typeof Banner>;
|
|
22
|
+
|
|
23
|
+
/** S5: the time went while the guest was typing. */
|
|
24
|
+
export const Warning: Story = {
|
|
25
|
+
args: {
|
|
26
|
+
tone: "warning",
|
|
27
|
+
icon: <TriangleAlert aria-hidden />,
|
|
28
|
+
title: "19:30 just went",
|
|
29
|
+
children: "Someone booked it while you were filling this in. Your details are kept — pick another time.",
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/** B0c: a venue that takes no bookings. */
|
|
34
|
+
export const Info: Story = {
|
|
35
|
+
args: { tone: "info", children: "This venue does not take bookings. Walk-ins only." },
|
|
36
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
+
import { cn } from "../lib/utils";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Banner — a short inline note inside a flow, not a page-level alert: the
|
|
7
|
+
* booking flow's "19:30 just went" when a time is taken mid-form, "No table
|
|
8
|
+
* was booked" when a confirm fails, "This venue does not take bookings"
|
|
9
|
+
* (booking flow.html, `.bnr`).
|
|
10
|
+
*
|
|
11
|
+
* Not `Alert`: that one is a bordered card for page-level status with a
|
|
12
|
+
* pinned icon column. This is borderless, sits in the flow of a form, and
|
|
13
|
+
* reads as part of the screen — a soft ground, an optional 16px icon, an
|
|
14
|
+
* optional bold title over the body.
|
|
15
|
+
*
|
|
16
|
+
* Measured from the design: 12px radius, 12px × 14px inset, 10px between
|
|
17
|
+
* icon and text; the title at 13px bold, the body at 12.5px (90% in the
|
|
18
|
+
* warning tone), both at 1.5 leading.
|
|
19
|
+
* - `info`: the soft surface and the secondary ink.
|
|
20
|
+
* - `warning`: a 16% amber wash with the design's amber ink — darker than
|
|
21
|
+
* the solid `--warning`, which falls short of AA on its own wash at this
|
|
22
|
+
* size; dark mode uses the lifted token.
|
|
23
|
+
*/
|
|
24
|
+
const bannerVariants = cva(
|
|
25
|
+
"flex gap-2.5 rounded-xl px-3.5 py-3 text-[12.5px] leading-normal [&>svg]:mt-0.5 [&>svg]:size-4 [&>svg]:shrink-0",
|
|
26
|
+
{
|
|
27
|
+
variants: {
|
|
28
|
+
tone: {
|
|
29
|
+
info: "bg-surface-2 text-ink-secondary",
|
|
30
|
+
warning:
|
|
31
|
+
"bg-[oklch(0.62_0.15_70/0.16)] text-[oklch(0.42_0.1_70)] dark:bg-warning/15 dark:text-warning",
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
defaultVariants: { tone: "info" },
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
export type BannerProps = Omit<React.HTMLAttributes<HTMLDivElement>, "title"> &
|
|
39
|
+
VariantProps<typeof bannerVariants> & {
|
|
40
|
+
/** A lucide icon, drawn at 16px beside the text. */
|
|
41
|
+
icon?: React.ReactNode;
|
|
42
|
+
/** The bold first line — "19:30 just went". */
|
|
43
|
+
title?: React.ReactNode;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
function Banner({ tone, icon, title, className, children, ...props }: BannerProps) {
|
|
47
|
+
return (
|
|
48
|
+
<div data-slot="banner" className={cn(bannerVariants({ tone }), className)} {...props}>
|
|
49
|
+
{icon}
|
|
50
|
+
<div className="min-w-0">
|
|
51
|
+
{title ? <b className="mb-[3px] block text-[13px] font-bold">{title}</b> : null}
|
|
52
|
+
<div className={cn(tone === "warning" && title ? "opacity-90" : undefined)}>{children}</div>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export { Banner, bannerVariants };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { render, screen } from "@testing-library/react";
|
|
3
|
+
import { TriangleAlert } from "lucide-react";
|
|
4
|
+
import { cn } from "../lib/utils";
|
|
5
|
+
import { Banner } from "./banner";
|
|
6
|
+
import { Checkbox } from "./checkbox";
|
|
7
|
+
import { Field, FieldControl, FieldError, FieldLabel, FieldOptional } from "./field";
|
|
8
|
+
import { Input } from "./input";
|
|
9
|
+
import { Textarea } from "./textarea";
|
|
10
|
+
import { toggleVariants } from "./toggle";
|
|
11
|
+
|
|
12
|
+
describe("toggleVariants chip and tab", () => {
|
|
13
|
+
it("keeps the chip's own sizing when called bare, with the default size", () => {
|
|
14
|
+
const classes = cn(toggleVariants({ variant: "chip" })).split(" ");
|
|
15
|
+
expect(classes).toContain("h-auto");
|
|
16
|
+
expect(classes).toContain("px-[13px]");
|
|
17
|
+
expect(classes).not.toContain("h-9");
|
|
18
|
+
expect(classes).not.toContain("px-2");
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("keeps the tab's own sizing too", () => {
|
|
22
|
+
const classes = cn(toggleVariants({ variant: "tab", size: "lg" })).split(" ");
|
|
23
|
+
expect(classes).toContain("h-auto");
|
|
24
|
+
expect(classes).toContain("px-3");
|
|
25
|
+
expect(classes).not.toContain("h-10");
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe("booking field", () => {
|
|
30
|
+
it("labels its control, marks it invalid and describes it by the error", () => {
|
|
31
|
+
render(
|
|
32
|
+
<Field appearance="booking" invalid>
|
|
33
|
+
<FieldLabel>
|
|
34
|
+
Phone <FieldOptional>(optional)</FieldOptional>
|
|
35
|
+
</FieldLabel>
|
|
36
|
+
<FieldControl>
|
|
37
|
+
<Input appearance="booking" defaultValue="0712 34" />
|
|
38
|
+
</FieldControl>
|
|
39
|
+
<FieldError>That number looks too short.</FieldError>
|
|
40
|
+
</Field>
|
|
41
|
+
);
|
|
42
|
+
const input = screen.getByLabelText(/Phone/);
|
|
43
|
+
expect(input).toHaveAttribute("aria-invalid", "true");
|
|
44
|
+
expect(input).toHaveAccessibleDescription(/That number looks too short\./);
|
|
45
|
+
expect(input.className).toContain("h-[46px]");
|
|
46
|
+
// The booking label stays muted when the field is invalid.
|
|
47
|
+
expect(screen.getByText(/Phone/).className).not.toContain("text-destructive");
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("gives the note field and the opt-in their booking shapes", () => {
|
|
51
|
+
render(
|
|
52
|
+
<>
|
|
53
|
+
<Textarea appearance="booking" aria-label="Anything we should know" />
|
|
54
|
+
<Checkbox appearance="booking" aria-label="Save these details" defaultChecked />
|
|
55
|
+
</>
|
|
56
|
+
);
|
|
57
|
+
expect(screen.getByRole("textbox").className).toContain("min-h-[66px]");
|
|
58
|
+
const box = screen.getByRole("checkbox");
|
|
59
|
+
expect(box).toHaveAttribute("data-state", "checked");
|
|
60
|
+
expect(box.className).toContain("size-[17px]");
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe("Banner", () => {
|
|
65
|
+
it("reads as its title over its body, with the icon beside", () => {
|
|
66
|
+
render(
|
|
67
|
+
<Banner tone="warning" icon={<TriangleAlert aria-hidden />} title="19:30 just went">
|
|
68
|
+
Someone booked it while you were filling this in.
|
|
69
|
+
</Banner>
|
|
70
|
+
);
|
|
71
|
+
const banner = screen.getByText("19:30 just went").closest("[data-slot=banner]");
|
|
72
|
+
expect(banner).toHaveTextContent("19:30 just wentSomeone booked it");
|
|
73
|
+
expect(banner?.querySelector("svg")).not.toBeNull();
|
|
74
|
+
});
|
|
75
|
+
});
|