@bearmenu/ui 0.8.11 → 0.8.12
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-H3ZZDX5L.js → chunk-7A42J73Q.js} +1 -1
- package/dist/{chunk-5RWTOT5Y.js → chunk-CNJQUHCU.js} +11 -1
- package/dist/{chunk-JS3EINZD.js → chunk-VAXOQS7W.js} +12 -0
- package/dist/{chunk-AKQ57NXY.js → chunk-ZQ53AGML.js} +2 -2
- package/dist/components/alert-dialog.js +1 -1
- package/dist/components/alert.d.ts +2 -2
- package/dist/components/avatar.d.ts +3 -3
- package/dist/components/badge.d.ts +1 -1
- package/dist/components/button.d.ts +2 -2
- package/dist/components/button.js +1 -1
- package/dist/components/calendar.js +1 -1
- package/dist/components/card.d.ts +4 -4
- package/dist/components/carousel.js +1 -1
- package/dist/components/combobox.js +1 -1
- package/dist/components/command.d.ts +8 -8
- package/dist/components/concept-compare-rail.js +2 -2
- package/dist/components/concept-compare.d.ts +1 -1
- package/dist/components/concept-compare.js +28 -7
- package/dist/components/concept-convergence.js +1 -1
- package/dist/components/date-input.d.ts +1 -1
- package/dist/components/dialog.d.ts +2 -2
- package/dist/components/empty-state.js +1 -1
- package/dist/components/event-detail-panel.js +1 -1
- package/dist/components/event-list-row-wide.js +1 -1
- package/dist/components/haptic-button.js +1 -1
- package/dist/components/input-group.d.ts +4 -4
- package/dist/components/input.d.ts +2 -2
- package/dist/components/item.d.ts +19 -9
- package/dist/components/item.js +15 -10
- package/dist/components/kbd.d.ts +2 -2
- package/dist/components/kitchen-dossier.d.ts +2 -0
- package/dist/components/kitchen-dossier.js +25 -18
- package/dist/components/link-button.js +1 -1
- package/dist/components/menu-family-block.d.ts +15 -9
- package/dist/components/menu-family-block.js +62 -59
- package/dist/components/menu-family-card.js +1 -1
- package/dist/components/menu-family-tiles.d.ts +19 -0
- package/dist/components/menu-family-tiles.js +57 -0
- package/dist/components/menu-hub-hero.js +8 -6
- package/dist/components/menu-index-list.d.ts +31 -12
- package/dist/components/menu-index-list.js +68 -31
- package/dist/components/menu-intent-hero.d.ts +1 -1
- package/dist/components/menu-mocks.d.ts +10 -3
- package/dist/components/menu-mocks.js +21 -9
- package/dist/components/menu-types.d.ts +33 -10
- package/dist/components/multi-select-combobox.js +1 -1
- package/dist/components/native-select.d.ts +2 -2
- package/dist/components/pagination.js +1 -1
- package/dist/components/photo-ground.d.ts +7 -1
- package/dist/components/photo-ground.js +1 -1
- package/dist/components/searchable-select.js +1 -1
- package/dist/components/select.d.ts +1 -1
- package/dist/components/sliding-panels.js +1 -1
- package/dist/components/snap-rail.d.ts +2 -2
- package/dist/components/spinner.d.ts +4 -4
- package/dist/components/tag.d.ts +4 -4
- package/dist/components/text.d.ts +3 -3
- package/dist/components/toggle.d.ts +1 -1
- package/dist/components/venue-grade-dimensions.js +1 -1
- package/dist/components/weekday-theme-banner.d.ts +24 -3
- package/dist/components/weekday-theme-banner.js +62 -14
- package/package.json +1 -1
- package/src/components/button.stories.tsx +25 -2
- package/src/components/button.tsx +12 -0
- package/src/components/colour-dictionary.stories.tsx +1 -1
- package/src/components/concept-compare.tsx +40 -9
- package/src/components/item.tsx +69 -45
- package/src/components/kitchen-dossier.tsx +45 -24
- package/src/components/menu-family-block.tsx +86 -79
- package/src/components/menu-family-tiles.stories.tsx +54 -0
- package/src/components/menu-family-tiles.test.tsx +30 -0
- package/src/components/menu-family-tiles.tsx +132 -0
- package/src/components/menu-hub-hero.tsx +13 -7
- package/src/components/menu-index-list.stories.tsx +6 -1
- package/src/components/menu-index-list.tsx +101 -54
- package/src/components/menu-intent-hero.tsx +1 -1
- package/src/components/menu-mocks.ts +32 -9
- package/src/components/menu-types.ts +32 -9
- package/src/components/photo-ground.tsx +13 -1
- package/src/components/venue-grade-dimensions.tsx +9 -2
- package/src/components/weekday-theme-banner.stories.tsx +43 -4
- package/src/components/weekday-theme-banner.tsx +94 -17
- package/dist/components/menu-intent-tiles.d.ts +0 -31
- package/dist/components/menu-intent-tiles.js +0 -50
- package/src/components/menu-intent-tiles.stories.tsx +0 -54
- package/src/components/menu-intent-tiles.tsx +0 -76
|
@@ -52,7 +52,7 @@ type MenuIntentHeroProps = {
|
|
|
52
52
|
* Finished CSS gradient for the ground, e.g. `linear-gradient(140deg, …)`.
|
|
53
53
|
*
|
|
54
54
|
* A gradient rather than a token name, for the same reason `<MenuField>` and
|
|
55
|
-
* `<
|
|
55
|
+
* `<MenuFamilyTiles>` take one: the hue tables are app-owned, and a component
|
|
56
56
|
* referencing `var(--h-pizza)` renders an unstyled panel in any consumer that
|
|
57
57
|
* does not define it. Missing, the panel falls back to the foreground colour
|
|
58
58
|
* — visibly unstyled rather than white text on white.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MenuFamilyBlockPreview, MenuConceptPreview, MenuFamilyPreview, MenuFilterChip, MenuIndexEntry, MenuIntentFigure,
|
|
1
|
+
import { MenuFamilyBlockPreview, MenuConceptPreview, MenuFamilyPreview, MenuFamilyTile, MenuFilterChip, MenuIndexEntry, MenuIntentFigure, MenuItemPreview, MenuKitchenPreview, MenuLoosenOption, QaItem, MenuVenuePreview } from './menu-types.js';
|
|
2
2
|
import { PlacePreview } from './place-types.js';
|
|
3
3
|
import 'react';
|
|
4
4
|
|
|
@@ -36,7 +36,14 @@ declare const mockConcept: MenuConceptPreview;
|
|
|
36
36
|
declare const mockFamily: MenuFamilyPreview;
|
|
37
37
|
/** The drinks counterpart, and the reason `chip.count` is optional. */
|
|
38
38
|
declare const mockDrinkFamily: MenuFamilyPreview;
|
|
39
|
-
|
|
39
|
+
/**
|
|
40
|
+
* The hub's seven cuisines, in the registry's order. The photograph is a
|
|
41
|
+
* venue's, never a plate's; the last one ships without, so the story shows
|
|
42
|
+
* the initial fallback beside six real tiles.
|
|
43
|
+
*/
|
|
44
|
+
declare const mockFamilyTiles: MenuFamilyTile[];
|
|
45
|
+
/** The closing tile: stone, so it reads as the index and not as an eighth cuisine. */
|
|
46
|
+
declare const mockFamilyTilesAll: MenuFamilyTile;
|
|
40
47
|
/** Formatters the stories pass. Real callers inject locale-aware ones. */
|
|
41
48
|
declare const mockFormatters: {
|
|
42
49
|
price: (value: number) => string;
|
|
@@ -87,4 +94,4 @@ declare const mockFamilyBlock: MenuFamilyBlockPreview;
|
|
|
87
94
|
declare const mockBareFamilyBlock: MenuFamilyBlockPreview;
|
|
88
95
|
declare const mockQa: QaItem[];
|
|
89
96
|
|
|
90
|
-
export { mockBareFamilyBlock, mockConcept, mockDrinkFamily, mockFamily, mockFamilyBlock, mockFilterChips, mockFormatters, mockGradients, mockHubLabels, mockIndexEntries, mockIntentFigures,
|
|
97
|
+
export { mockBareFamilyBlock, mockConcept, mockDrinkFamily, mockFamily, mockFamilyBlock, mockFamilyTiles, mockFamilyTilesAll, mockFilterChips, mockFormatters, mockGradients, mockHubLabels, mockIndexEntries, mockIntentFigures, mockItems, mockKitchens, mockLoosenOptions, mockMatchedKitchens, mockPlaces, mockQa, mockVenues };
|
|
@@ -330,15 +330,27 @@ var mockDrinkFamily = {
|
|
|
330
330
|
price_median: 28,
|
|
331
331
|
venue_photo_urls: []
|
|
332
332
|
};
|
|
333
|
-
var
|
|
334
|
-
var
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
{ slug: "
|
|
339
|
-
{ slug: "
|
|
340
|
-
{ slug: "
|
|
333
|
+
var familyGradient = (hue) => `linear-gradient(150deg, oklch(0.52 0.14 ${hue}), oklch(0.43 0.13 ${hue - 4}))`;
|
|
334
|
+
var familyPhoto = (hue) => "data:image/svg+xml;utf8," + encodeURIComponent(
|
|
335
|
+
`<svg xmlns="http://www.w3.org/2000/svg" width="320" height="320"><defs><linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="hsl(${hue} 28% 60%)"/><stop offset="1" stop-color="hsl(${hue} 22% 26%)"/></linearGradient></defs><rect width="320" height="320" fill="url(#g)"/><circle cx="100" cy="110" r="56" fill="hsl(${hue} 40% 82%)" opacity=".55"/><rect x="170" y="190" width="120" height="90" fill="hsl(${hue} 15% 18%)" opacity=".7"/></svg>`
|
|
336
|
+
);
|
|
337
|
+
var mockFamilyTiles = [
|
|
338
|
+
{ slug: "italian", label: "Italian", countLabel: "66", href: "/menu/cuisines/italian", gradient: familyGradient(38), photoUrl: familyPhoto(30) },
|
|
339
|
+
{ slug: "romanian", label: "Romanian", countLabel: "64", href: "/menu/cuisines/romanian", gradient: familyGradient(25), photoUrl: familyPhoto(10) },
|
|
340
|
+
{ slug: "breakfast-brunch", label: "Breakfast & brunch", countLabel: "64", href: "/menu/cuisines/breakfast-brunch", gradient: familyGradient(82), photoUrl: familyPhoto(45) },
|
|
341
|
+
{ slug: "vegetarian", label: "Vegetarian", countLabel: "64", href: "/menu/cuisines/vegetarian", gradient: familyGradient(148), photoUrl: familyPhoto(120) },
|
|
342
|
+
{ slug: "pizza", label: "Pizza", countLabel: "63", href: "/menu/cuisines/pizza", gradient: familyGradient(58), photoUrl: familyPhoto(20) },
|
|
343
|
+
{ slug: "vegan", label: "Vegan", countLabel: "38", href: "/menu/cuisines/vegan", gradient: familyGradient(135), photoUrl: familyPhoto(100) },
|
|
344
|
+
{ slug: "bakery", label: "Bakeries & patisseries", countLabel: "65", href: "/menu/cuisines/bakery", gradient: familyGradient(72) }
|
|
341
345
|
];
|
|
346
|
+
var mockFamilyTilesAll = {
|
|
347
|
+
slug: "all",
|
|
348
|
+
label: "All 38 cuisines",
|
|
349
|
+
countLabel: "The full index",
|
|
350
|
+
href: "/menu/cuisines",
|
|
351
|
+
gradient: "linear-gradient(150deg, oklch(0.50 0.03 70), oklch(0.40 0.028 64))",
|
|
352
|
+
photoUrl: familyPhoto(60)
|
|
353
|
+
};
|
|
342
354
|
var mockFormatters = {
|
|
343
355
|
price: (value) => `${value} lei`,
|
|
344
356
|
number: (value) => value.toLocaleString("en-US"),
|
|
@@ -501,4 +513,4 @@ var mockQa = [
|
|
|
501
513
|
}
|
|
502
514
|
];
|
|
503
515
|
|
|
504
|
-
export { mockBareFamilyBlock, mockConcept, mockDrinkFamily, mockFamily, mockFamilyBlock, mockFilterChips, mockFormatters, mockGradients, mockHubLabels, mockIndexEntries, mockIntentFigures,
|
|
516
|
+
export { mockBareFamilyBlock, mockConcept, mockDrinkFamily, mockFamily, mockFamilyBlock, mockFamilyTiles, mockFamilyTilesAll, mockFilterChips, mockFormatters, mockGradients, mockHubLabels, mockIndexEntries, mockIntentFigures, mockItems, mockKitchens, mockLoosenOptions, mockMatchedKitchens, mockPlaces, mockQa, mockVenues };
|
|
@@ -126,6 +126,20 @@ type MenuConceptRow = {
|
|
|
126
126
|
featured?: boolean;
|
|
127
127
|
/** Portion, already formatted with its unit, e.g. "260g". */
|
|
128
128
|
portion_label?: string;
|
|
129
|
+
/**
|
|
130
|
+
* What this room WON — "CHEAPEST", "MOST NAMED", "HIGHEST GRADE",
|
|
131
|
+
* "DEAREST" — already localised. A card whose rooms are four winners rather
|
|
132
|
+
* than four ranks sets one per room; without it the card falls back to
|
|
133
|
+
* "cheapest, then #2, #3, #4".
|
|
134
|
+
*/
|
|
135
|
+
badge?: string;
|
|
136
|
+
/** Which figure the badge is about; that figure is emphasised. */
|
|
137
|
+
lead?: 'price' | 'mentions' | 'grade';
|
|
138
|
+
/**
|
|
139
|
+
* The venue's BearMenu grade, pre-formatted ("9.2"). Takes the star's
|
|
140
|
+
* place beside the kitchen's name; `rating` (Google's) shows only without it.
|
|
141
|
+
*/
|
|
142
|
+
grade?: string;
|
|
129
143
|
};
|
|
130
144
|
/**
|
|
131
145
|
* A browsable grouping of venues — a cuisine on the dishes tab, a drink family
|
|
@@ -190,17 +204,21 @@ type MenuVenueSignature = {
|
|
|
190
204
|
isSignature?: boolean;
|
|
191
205
|
};
|
|
192
206
|
/**
|
|
193
|
-
*
|
|
207
|
+
* A family tile — a cuisine on the dishes tab, a going-out family on the
|
|
208
|
+
* drinks tab — as the hub's doorway grid draws it: a hue, a name, a venue
|
|
209
|
+
* count and one venue's photograph.
|
|
194
210
|
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
* rather than linking nowhere.
|
|
211
|
+
* `href` is required: a tile that cannot resolve to a real destination is not
|
|
212
|
+
* rendered rather than linking nowhere.
|
|
198
213
|
*/
|
|
199
|
-
type
|
|
214
|
+
type MenuFamilyTile = {
|
|
200
215
|
slug: string;
|
|
201
216
|
label: string;
|
|
202
|
-
/**
|
|
203
|
-
|
|
217
|
+
/**
|
|
218
|
+
* The venue count, already formatted by the caller — "64", "1,204" — because
|
|
219
|
+
* thousands separators are locale-dependent and the DS owns no locale.
|
|
220
|
+
*/
|
|
221
|
+
countLabel?: string;
|
|
204
222
|
href: string;
|
|
205
223
|
/**
|
|
206
224
|
* Finished CSS gradient for the tile's ground, e.g.
|
|
@@ -213,8 +231,8 @@ type MenuIntentTile = {
|
|
|
213
231
|
* — visible and obviously unstyled, rather than white text on white.
|
|
214
232
|
*/
|
|
215
233
|
gradient?: string;
|
|
216
|
-
/**
|
|
217
|
-
|
|
234
|
+
/** Pre-resolved VENUE photograph. Venue photography is real; item photography is not. */
|
|
235
|
+
photoUrl?: string;
|
|
218
236
|
};
|
|
219
237
|
/**
|
|
220
238
|
* One figure in the intent hero — a number the reader can tap to filter by.
|
|
@@ -333,6 +351,11 @@ type MenuIndexEntry = {
|
|
|
333
351
|
slug: string;
|
|
334
352
|
name: string;
|
|
335
353
|
count: number;
|
|
354
|
+
/**
|
|
355
|
+
* `count`, already formatted ("1,204"). The list is a client component and a
|
|
356
|
+
* formatter cannot cross into it from a server caller; a string can.
|
|
357
|
+
*/
|
|
358
|
+
countLabel?: string;
|
|
336
359
|
href: string;
|
|
337
360
|
/** Finished CSS gradient for the mark. Falls back to the border colour. */
|
|
338
361
|
gradient?: string;
|
|
@@ -418,4 +441,4 @@ type MenuHubLabels = {
|
|
|
418
441
|
until: string;
|
|
419
442
|
};
|
|
420
443
|
|
|
421
|
-
export { type MenuConceptPreview, type MenuConceptRow, type MenuFamilyBlockPreview, type MenuFamilyChip, type MenuFamilyPreview, type MenuFilterChip, type MenuFormatters, type MenuHubLabels, type MenuIndexEntry, type MenuIntentFigure, type
|
|
444
|
+
export { type MenuConceptPreview, type MenuConceptRow, type MenuFamilyBlockPreview, type MenuFamilyChip, type MenuFamilyPreview, type MenuFamilyTile, type MenuFilterChip, type MenuFormatters, type MenuHubLabels, type MenuIndexEntry, type MenuIntentFigure, type MenuItemPlaceRef, type MenuItemPreview, type MenuKitchenDish, type MenuKitchenPreview, type MenuLinkComponent, type MenuLinkProps, type MenuLoosenOption, MenuSizeAndPrice, type MenuVenuePreview, type MenuVenueSignature, type QaItem };
|
|
@@ -2,7 +2,7 @@ import { Popover, PopoverTrigger, PopoverContent } from '../chunk-66MAPLXS.js';
|
|
|
2
2
|
import { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem } from '../chunk-XNA2INVQ.js';
|
|
3
3
|
import '../chunk-FRPPIXMY.js';
|
|
4
4
|
import { Checkbox } from '../chunk-D5QHEHXJ.js';
|
|
5
|
-
import { Button } from '../chunk-
|
|
5
|
+
import { Button } from '../chunk-VAXOQS7W.js';
|
|
6
6
|
import '../chunk-R47NEOSI.js';
|
|
7
7
|
import { Badge } from '../chunk-2CXU5WZO.js';
|
|
8
8
|
import { cn } from '../chunk-FEK5XGZW.js';
|
|
@@ -3,10 +3,10 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const nativeSelectVariants: (props?: ({
|
|
6
|
-
size?: "
|
|
6
|
+
size?: "default" | "sm" | "lg" | null | undefined;
|
|
7
7
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
8
8
|
declare const NativeSelect: React.ForwardRefExoticComponent<Omit<React.SelectHTMLAttributes<HTMLSelectElement>, "size"> & VariantProps<(props?: ({
|
|
9
|
-
size?: "
|
|
9
|
+
size?: "default" | "sm" | "lg" | null | undefined;
|
|
10
10
|
} & class_variance_authority_types.ClassProp) | undefined) => string> & React.RefAttributes<HTMLSelectElement>>;
|
|
11
11
|
|
|
12
12
|
export { NativeSelect, nativeSelectVariants };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { buttonVariants } from '../chunk-
|
|
1
|
+
import { buttonVariants } from '../chunk-VAXOQS7W.js';
|
|
2
2
|
import '../chunk-R47NEOSI.js';
|
|
3
3
|
import { cn } from '../chunk-FEK5XGZW.js';
|
|
4
4
|
import { __objRest, __spreadValues, __spreadProps } from '../chunk-3GWWZKX7.js';
|
|
@@ -57,8 +57,14 @@ type PhotoGroundProps = {
|
|
|
57
57
|
overlayClassName?: string;
|
|
58
58
|
/** How eagerly the first photograph loads. `stack` grounds are above the fold. */
|
|
59
59
|
loading?: "lazy" | "eager";
|
|
60
|
+
/**
|
|
61
|
+
* Classes on the fallback initial — its size, when the ground is smaller
|
|
62
|
+
* than a card. The 64px default fills a card cell; a tile's 88px polaroid
|
|
63
|
+
* passes `text-[44px]`.
|
|
64
|
+
*/
|
|
65
|
+
glyphClassName?: string;
|
|
60
66
|
className?: string;
|
|
61
67
|
};
|
|
62
|
-
declare function PhotoGround({ photos, initials, mode, active, mosaicClassName, phoneTiles, gradient, overlay, overlayClassName, loading, className, }: PhotoGroundProps): react_jsx_runtime.JSX.Element;
|
|
68
|
+
declare function PhotoGround({ photos, initials, mode, active, mosaicClassName, phoneTiles, gradient, overlay, overlayClassName, loading, glyphClassName, className, }: PhotoGroundProps): react_jsx_runtime.JSX.Element;
|
|
63
69
|
|
|
64
70
|
export { PHOTO_GROUND, PhotoGround, type PhotoGroundProps };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Popover, PopoverTrigger, PopoverContent } from '../chunk-66MAPLXS.js';
|
|
2
2
|
import { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem } from '../chunk-XNA2INVQ.js';
|
|
3
3
|
import '../chunk-FRPPIXMY.js';
|
|
4
|
-
import { Button } from '../chunk-
|
|
4
|
+
import { Button } from '../chunk-VAXOQS7W.js';
|
|
5
5
|
import '../chunk-R47NEOSI.js';
|
|
6
6
|
import { cn } from '../chunk-FEK5XGZW.js';
|
|
7
7
|
import '../chunk-3GWWZKX7.js';
|
|
@@ -7,7 +7,7 @@ declare const Select: React.FC<SelectPrimitive.SelectProps>;
|
|
|
7
7
|
declare const SelectGroup: React.ForwardRefExoticComponent<SelectPrimitive.SelectGroupProps & React.RefAttributes<HTMLDivElement>>;
|
|
8
8
|
declare const SelectValue: React.ForwardRefExoticComponent<SelectPrimitive.SelectValueProps & React.RefAttributes<HTMLSpanElement>>;
|
|
9
9
|
declare const SelectTrigger: React.ForwardRefExoticComponent<Omit<SelectPrimitive.SelectTriggerProps & React.RefAttributes<HTMLButtonElement>, "ref"> & VariantProps<(props?: ({
|
|
10
|
-
size?: "
|
|
10
|
+
size?: "default" | "sm" | "lg" | null | undefined;
|
|
11
11
|
} & class_variance_authority_types.ClassProp) | undefined) => string> & React.RefAttributes<HTMLButtonElement>>;
|
|
12
12
|
declare const SelectScrollUpButton: React.ForwardRefExoticComponent<Omit<SelectPrimitive.SelectScrollUpButtonProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
13
13
|
declare const SelectScrollDownButton: React.ForwardRefExoticComponent<Omit<SelectPrimitive.SelectScrollDownButtonProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -22,7 +22,7 @@ import { VariantProps } from 'class-variance-authority';
|
|
|
22
22
|
*/
|
|
23
23
|
declare const snapRailVariants: (props?: ({
|
|
24
24
|
itemWidth?: "sm" | "lg" | "full" | "md" | null | undefined;
|
|
25
|
-
gap?: "
|
|
25
|
+
gap?: "default" | "sm" | null | undefined;
|
|
26
26
|
bleed?: "none" | "page" | "card" | null | undefined;
|
|
27
27
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
28
28
|
type SnapRailProps = React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof snapRailVariants> & {
|
|
@@ -44,7 +44,7 @@ type SnapRailProps = React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof
|
|
|
44
44
|
};
|
|
45
45
|
declare const SnapRail: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & VariantProps<(props?: ({
|
|
46
46
|
itemWidth?: "sm" | "lg" | "full" | "md" | null | undefined;
|
|
47
|
-
gap?: "
|
|
47
|
+
gap?: "default" | "sm" | null | undefined;
|
|
48
48
|
bleed?: "none" | "page" | "card" | null | undefined;
|
|
49
49
|
} & class_variance_authority_types.ClassProp) | undefined) => string> & {
|
|
50
50
|
/**
|
|
@@ -3,12 +3,12 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const spinnerVariants: (props?: ({
|
|
6
|
-
size?: "
|
|
7
|
-
tone?: "
|
|
6
|
+
size?: "default" | "xs" | "sm" | "lg" | "xl" | null | undefined;
|
|
7
|
+
tone?: "inherit" | "default" | "destructive" | "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
|
-
size?: "
|
|
11
|
-
tone?: "
|
|
10
|
+
size?: "default" | "xs" | "sm" | "lg" | "xl" | null | undefined;
|
|
11
|
+
tone?: "inherit" | "default" | "destructive" | "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,12 +3,12 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const tagVariants: (props?: ({
|
|
6
|
-
variant?: "default" | "
|
|
7
|
-
size?: "
|
|
6
|
+
variant?: "default" | "destructive" | "outline" | "success" | "warning" | "primary" | "quiet" | null | undefined;
|
|
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" | "
|
|
11
|
-
size?: "
|
|
10
|
+
variant?: "default" | "destructive" | "outline" | "success" | "warning" | "primary" | "quiet" | null | undefined;
|
|
11
|
+
size?: "default" | "sm" | "lg" | null | undefined;
|
|
12
12
|
} & class_variance_authority_types.ClassProp) | undefined) => string> & {
|
|
13
13
|
onRemove?: () => void;
|
|
14
14
|
removeLabel?: string;
|
|
@@ -23,10 +23,10 @@ import { VariantProps } from 'class-variance-authority';
|
|
|
23
23
|
*/
|
|
24
24
|
declare const textVariants: (props?: ({
|
|
25
25
|
variant?: "h2" | "h3" | "label" | "body" | "caption" | "h1" | "h4" | "small" | "display" | "body-lg" | "body-sm" | "overline" | null | undefined;
|
|
26
|
-
color?: "
|
|
26
|
+
color?: "inherit" | "default" | "destructive" | "muted" | "primary" | "primary-foreground" | null | undefined;
|
|
27
27
|
weight?: "bold" | "medium" | "normal" | "semibold" | null | undefined;
|
|
28
|
-
leading?: "none" | "
|
|
29
|
-
tracking?: "
|
|
28
|
+
leading?: "none" | "normal" | "tight" | "snug" | "relaxed" | "loose" | null | undefined;
|
|
29
|
+
tracking?: "normal" | "tight" | "wide" | "wider" | null | undefined;
|
|
30
30
|
wrap?: "balance" | "pretty" | "nowrap" | null | undefined;
|
|
31
31
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
32
32
|
type TextTag = "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "span" | "div" | "label" | "strong" | "em" | "small" | "li" | "dt" | "dd";
|
|
@@ -6,7 +6,7 @@ import { VariantProps } from 'class-variance-authority';
|
|
|
6
6
|
|
|
7
7
|
declare const toggleVariants: (props?: ({
|
|
8
8
|
variant?: "default" | "outline" | null | undefined;
|
|
9
|
-
size?: "
|
|
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;
|
|
12
12
|
|
|
@@ -26,8 +26,15 @@ type WeekdayThemeBannerLinkProps = {
|
|
|
26
26
|
type WeekdayThemeDay = {
|
|
27
27
|
/** Short code, e.g. "THU". Already localised. */
|
|
28
28
|
code: string;
|
|
29
|
-
/** Theme name, e.g. "Burger Thursday". */
|
|
29
|
+
/** Theme name, e.g. "Burger Thursday in Cluj". */
|
|
30
30
|
name: string;
|
|
31
|
+
/**
|
|
32
|
+
* The phone's title, e.g. "Burger Thursday" — one line where `name` takes
|
|
33
|
+
* two, so the photograph behind it stays a photograph. A separate string,
|
|
34
|
+
* never `name` with a clause stripped: word order is the locale's. Falls
|
|
35
|
+
* back to `name`.
|
|
36
|
+
*/
|
|
37
|
+
shortHeadline?: string;
|
|
31
38
|
/** Short form for the rail, e.g. "Burger". Falls back to `name`. */
|
|
32
39
|
shortName?: string;
|
|
33
40
|
/** Items under the theme. Omit where there is no count to show. */
|
|
@@ -44,10 +51,24 @@ type WeekdayThemeBannerProps = {
|
|
|
44
51
|
body?: string;
|
|
45
52
|
/** Heading over the week rail, e.g. "THE WEEK". */
|
|
46
53
|
weekLabel?: string;
|
|
47
|
-
/**
|
|
54
|
+
/**
|
|
55
|
+
* The primary action — pass a rendered button or link. From `lg` up only
|
|
56
|
+
* when `compactAction` is also given: on a phone the banner is a row, and a
|
|
57
|
+
* row does not carry a labelled button.
|
|
58
|
+
*/
|
|
48
59
|
action?: React.ReactNode;
|
|
49
60
|
/** Note beside the action, e.g. "Bruno picks nine, ranked on mentions". */
|
|
50
61
|
actionNote?: string;
|
|
62
|
+
/**
|
|
63
|
+
* The phone's action: the whole banner becomes the target and a chevron on
|
|
64
|
+
* the right is the signal — a disclosure row, not a call to action, so the
|
|
65
|
+
* banner stays as tall as its title. `label` names the target for a screen
|
|
66
|
+
* reader. Hidden from `lg`, where `action` takes over.
|
|
67
|
+
*/
|
|
68
|
+
compactAction?: {
|
|
69
|
+
label: string;
|
|
70
|
+
onClick: () => void;
|
|
71
|
+
};
|
|
51
72
|
/** Destination per day index. Renders the rail as links. */
|
|
52
73
|
dayHref?: (day: WeekdayThemeDay, index: number) => string;
|
|
53
74
|
/** Selects a day in place. Renders the rail as buttons. */
|
|
@@ -65,6 +86,6 @@ type WeekdayThemeBannerProps = {
|
|
|
65
86
|
linkComponent?: React.ComponentType<WeekdayThemeBannerLinkProps>;
|
|
66
87
|
className?: string;
|
|
67
88
|
};
|
|
68
|
-
declare function WeekdayThemeBanner({ days, activeDay, kicker, kickerIcon, body, weekLabel, action, actionNote, dayHref, onDayChange, imageUrl, linkComponent: LinkComponent, className, }: WeekdayThemeBannerProps): react_jsx_runtime.JSX.Element | null;
|
|
89
|
+
declare function WeekdayThemeBanner({ days, activeDay, kicker, kickerIcon, body, weekLabel, action, actionNote, compactAction, dayHref, onDayChange, imageUrl, linkComponent: LinkComponent, className, }: WeekdayThemeBannerProps): react_jsx_runtime.JSX.Element | null;
|
|
69
90
|
|
|
70
91
|
export { WeekdayThemeBanner, type WeekdayThemeBannerLinkProps, type WeekdayThemeBannerProps, type WeekdayThemeDay };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { cn } from '../chunk-FEK5XGZW.js';
|
|
2
2
|
import { __objRest, __spreadValues } from '../chunk-3GWWZKX7.js';
|
|
3
|
+
import { ChevronRight } from 'lucide-react';
|
|
3
4
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
4
5
|
|
|
5
6
|
function DefaultLink(_a) {
|
|
@@ -15,6 +16,7 @@ function WeekdayThemeBanner({
|
|
|
15
16
|
weekLabel,
|
|
16
17
|
action,
|
|
17
18
|
actionNote,
|
|
19
|
+
compactAction,
|
|
18
20
|
dayHref,
|
|
19
21
|
onDayChange,
|
|
20
22
|
imageUrl,
|
|
@@ -27,7 +29,9 @@ function WeekdayThemeBanner({
|
|
|
27
29
|
"div",
|
|
28
30
|
{
|
|
29
31
|
className: cn(
|
|
30
|
-
|
|
32
|
+
// A plate needs a ~2.8:1 window to read on a phone; the text alone
|
|
33
|
+
// would give it ~85px.
|
|
34
|
+
"group relative grid overflow-hidden rounded-[18px] bg-[linear-gradient(120deg,oklch(0.32_0.06_45),oklch(0.24_0.04_40))] text-white max-lg:min-h-[128px] lg:grid-cols-[1fr_auto]",
|
|
31
35
|
className
|
|
32
36
|
),
|
|
33
37
|
children: [
|
|
@@ -45,7 +49,7 @@ function WeekdayThemeBanner({
|
|
|
45
49
|
"div",
|
|
46
50
|
{
|
|
47
51
|
"aria-hidden": true,
|
|
48
|
-
className: "absolute inset-0 bg-[linear-gradient(100deg,oklch(0.18_0.03_45_/_0.94)_0%,oklch(0.18_0.03_45_/_0.82)_45%,oklch(0.18_0.03_45_/_0.66)_100%)]"
|
|
52
|
+
className: "absolute inset-0 bg-[linear-gradient(100deg,oklch(0.18_0.03_45_/_0.85)_0%,oklch(0.18_0.03_45_/_0.45)_48%,oklch(0.18_0.03_45_/_0.2)_100%)] lg:bg-[linear-gradient(100deg,oklch(0.18_0.03_45_/_0.94)_0%,oklch(0.18_0.03_45_/_0.82)_45%,oklch(0.18_0.03_45_/_0.66)_100%)]"
|
|
49
53
|
}
|
|
50
54
|
)
|
|
51
55
|
] }),
|
|
@@ -57,18 +61,62 @@ function WeekdayThemeBanner({
|
|
|
57
61
|
children: active.code
|
|
58
62
|
}
|
|
59
63
|
),
|
|
60
|
-
/* @__PURE__ */
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
64
|
+
compactAction && /* @__PURE__ */ jsx(
|
|
65
|
+
"button",
|
|
66
|
+
{
|
|
67
|
+
type: "button",
|
|
68
|
+
"aria-label": compactAction.label,
|
|
69
|
+
onClick: compactAction.onClick,
|
|
70
|
+
className: "absolute inset-0 z-[2] rounded-[18px] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-white/70 lg:hidden",
|
|
71
|
+
children: /* @__PURE__ */ jsx(
|
|
72
|
+
"span",
|
|
73
|
+
{
|
|
74
|
+
"aria-hidden": true,
|
|
75
|
+
className: "absolute right-4 top-1/2 flex h-11 w-11 -translate-y-1/2 items-center justify-center rounded-full border border-white/20 bg-[oklch(0.18_0.03_45_/_0.55)] text-white transition-colors [@media(pointer:coarse)]:group-active:bg-[oklch(0.18_0.03_45_/_0.75)]",
|
|
76
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-5 w-5" })
|
|
77
|
+
}
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
),
|
|
81
|
+
/* @__PURE__ */ jsxs(
|
|
82
|
+
"div",
|
|
83
|
+
{
|
|
84
|
+
className: cn(
|
|
85
|
+
"relative z-[1] flex flex-col gap-2.5 p-4 lg:gap-3 lg:p-6",
|
|
86
|
+
// On a phone the text keeps to the left 64% — the photograph gets
|
|
87
|
+
// the rest, and the chevron sits in it — and centres in the row.
|
|
88
|
+
imageUrl && "max-lg:max-w-[64%] max-lg:justify-center max-lg:gap-1.5",
|
|
89
|
+
// Without a photograph the text may run wide; keep it off the
|
|
90
|
+
// chevron. With one, the 36% beside the column already holds it.
|
|
91
|
+
compactAction && !imageUrl && "max-lg:pr-16"
|
|
92
|
+
),
|
|
93
|
+
children: [
|
|
94
|
+
kicker && /* @__PURE__ */ jsxs("span", { className: "inline-flex w-max items-center gap-1.5 text-[10.5px] font-bold tracking-[0.09em] text-white/75 lg:rounded-full lg:bg-white/15 lg:px-2.5 lg:py-1 lg:text-white", children: [
|
|
95
|
+
kickerIcon,
|
|
96
|
+
kicker
|
|
97
|
+
] }),
|
|
98
|
+
/* @__PURE__ */ jsx("h3", { className: "font-serif text-[22px] font-semibold leading-[1.15] tracking-[-0.02em] lg:text-[36px] lg:leading-tight", children: active.shortHeadline ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
99
|
+
/* @__PURE__ */ jsx("span", { className: "line-clamp-2 lg:hidden", children: active.shortHeadline }),
|
|
100
|
+
/* @__PURE__ */ jsx("span", { className: "hidden lg:block", children: active.name })
|
|
101
|
+
] }) : active.name }),
|
|
102
|
+
body && /* @__PURE__ */ jsx("p", { className: "hidden max-w-[520px] text-[13.5px] leading-[1.5] opacity-90 lg:block", children: body }),
|
|
103
|
+
(action || actionNote) && /* @__PURE__ */ jsxs(
|
|
104
|
+
"div",
|
|
105
|
+
{
|
|
106
|
+
className: cn(
|
|
107
|
+
"mt-1 flex flex-wrap items-center gap-3",
|
|
108
|
+
// With a compact action the phone has its chevron instead.
|
|
109
|
+
compactAction && "hidden lg:flex"
|
|
110
|
+
),
|
|
111
|
+
children: [
|
|
112
|
+
action,
|
|
113
|
+
actionNote && /* @__PURE__ */ jsx("span", { className: "text-xs opacity-75", children: actionNote })
|
|
114
|
+
]
|
|
115
|
+
}
|
|
116
|
+
)
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
),
|
|
72
120
|
/* @__PURE__ */ jsxs(
|
|
73
121
|
"div",
|
|
74
122
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
2
|
import { Button } from "./button";
|
|
3
|
-
import { Heart, Mail, Plus } from "lucide-react";
|
|
3
|
+
import { ArrowRight, Heart, Mail, Plus } from "lucide-react";
|
|
4
4
|
|
|
5
5
|
const meta = {
|
|
6
6
|
title: "Components/Button",
|
|
@@ -19,11 +19,13 @@ const meta = {
|
|
|
19
19
|
"glass",
|
|
20
20
|
"brown",
|
|
21
21
|
"antagonist",
|
|
22
|
+
"overlay",
|
|
23
|
+
"ink",
|
|
22
24
|
],
|
|
23
25
|
},
|
|
24
26
|
size: {
|
|
25
27
|
control: "select",
|
|
26
|
-
options: ["default", "sm", "lg", "icon"],
|
|
28
|
+
options: ["default", "sm", "lg", "pill", "icon"],
|
|
27
29
|
},
|
|
28
30
|
},
|
|
29
31
|
} satisfies Meta<typeof Button>;
|
|
@@ -59,6 +61,27 @@ export const Glass: Story = {
|
|
|
59
61
|
args: { children: "Glass", variant: "glass" },
|
|
60
62
|
};
|
|
61
63
|
|
|
64
|
+
/** The labelled action on a photo surface: glass on the ink, icon trailing. */
|
|
65
|
+
export const Ink: Story = {
|
|
66
|
+
args: {
|
|
67
|
+
children: (
|
|
68
|
+
<>
|
|
69
|
+
Open the menu
|
|
70
|
+
<ArrowRight aria-hidden />
|
|
71
|
+
</>
|
|
72
|
+
),
|
|
73
|
+
variant: "ink",
|
|
74
|
+
size: "pill",
|
|
75
|
+
},
|
|
76
|
+
decorators: [
|
|
77
|
+
(Story) => (
|
|
78
|
+
<div className="rounded-2xl bg-[oklch(0.21_0.012_55)] p-6">
|
|
79
|
+
<Story />
|
|
80
|
+
</div>
|
|
81
|
+
),
|
|
82
|
+
],
|
|
83
|
+
};
|
|
84
|
+
|
|
62
85
|
export const Brown: Story = {
|
|
63
86
|
args: { children: "Brown", variant: "brown" },
|
|
64
87
|
};
|
|
@@ -36,6 +36,16 @@ const buttonVariants = cva(
|
|
|
36
36
|
*/
|
|
37
37
|
overlay:
|
|
38
38
|
"bg-black/50 text-white hover:bg-black/65 focus-visible:ring-white/70",
|
|
39
|
+
/**
|
|
40
|
+
* The LABELLED action on a photo surface — "Open the menu", "See all
|
|
41
|
+
* 46 bars", "How we read menus" — where `overlay` is the unlabelled
|
|
42
|
+
* chrome. Glass on the ink: translucent white with a hairline, white
|
|
43
|
+
* type. Same reasoning as `overlay`: not theme-aware, because it
|
|
44
|
+
* contrasts with the photograph, not the canvas. Pair with `size="pill"`.
|
|
45
|
+
* Icons trail, never lead: `ArrowRight` when it navigates to a page,
|
|
46
|
+
* `ChevronRight` when it opens a sheet or drawer.
|
|
47
|
+
*/
|
|
48
|
+
ink: "border border-white/20 bg-white/[0.16] text-white hover:bg-white/25 focus-visible:ring-white/70 focus-visible:ring-offset-0",
|
|
39
49
|
brown:
|
|
40
50
|
"bg-brown text-brown-foreground shadow-sm hover:bg-brown/85 hover:shadow",
|
|
41
51
|
antagonist:
|
|
@@ -46,6 +56,8 @@ const buttonVariants = cva(
|
|
|
46
56
|
sm: "h-9 rounded-lg px-4",
|
|
47
57
|
default: "h-11 px-6 py-2",
|
|
48
58
|
lg: "h-12 rounded-2xl px-8",
|
|
59
|
+
/** The `ink` action's shape. Owns the radius so no variant fights it. */
|
|
60
|
+
pill: "h-11 rounded-full px-5 text-[13.5px] font-bold",
|
|
49
61
|
icon: "h-11 w-11 rounded-full",
|
|
50
62
|
"icon-xs": "h-8 w-8 rounded-full [&_svg]:size-3.5",
|
|
51
63
|
"icon-sm": "h-9 w-9 rounded-full",
|
|
@@ -209,7 +209,7 @@ function ColourDictionaryPage() {
|
|
|
209
209
|
<section>
|
|
210
210
|
<h2 className="text-[15px] font-extrabold">Where the values live</h2>
|
|
211
211
|
<p className="mt-2 text-[13px] leading-[1.55] text-foreground/85">
|
|
212
|
-
The design system owns the typography, the falloff and the layering (<code>MenuField</code>, <code>MenuFamilyCard</code>, <code>
|
|
212
|
+
The design system owns the typography, the falloff and the layering (<code>MenuField</code>, <code>MenuFamilyCard</code>, <code>MenuFamilyTiles</code>) and takes a finished colour as a prop. The palette lives in the fe app: the eighteen <code>--menu-field-*</code> tokens in <code>app/globals.css</code>, <code>FAMILY_HUES</code> and <code>INTENT_GRADIENTS</code> in <code>hub-gradients.ts</code>, category → family in <code>category-colors.ts</code>. The Storybook mocks carry the same values so post-generator films what the app paints.
|
|
213
213
|
</p>
|
|
214
214
|
</section>
|
|
215
215
|
</div>
|