@bearmenu/ui 0.8.8 → 0.8.10
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-24RFI4RQ.js +167 -0
- package/dist/chunk-2XCZJWTV.js +121 -0
- package/dist/chunk-5RWTOT5Y.js +72 -0
- package/dist/chunk-62ES6N32.js +27 -0
- package/dist/chunk-AKQ57NXY.js +58 -0
- package/dist/chunk-CLLY6XB3.js +41 -0
- package/dist/chunk-DTXNDLSE.js +125 -0
- package/dist/chunk-F6FMZJDG.js +113 -0
- package/dist/{chunk-2WDJR6K7.js → chunk-G7IFL4Z4.js} +4 -1
- package/dist/chunk-MZL7CGCL.js +109 -0
- package/dist/chunk-Q6QH52LJ.js +38 -0
- package/dist/chunk-SY6RV476.js +48 -0
- package/dist/chunk-TH6W2PWG.js +213 -0
- package/dist/chunk-UDN7UHJW.js +60 -0
- package/dist/{chunk-TT3WFS6S.js → chunk-YOKHBAIH.js} +11 -11
- package/dist/components/alert.d.ts +2 -2
- package/dist/components/badge.d.ts +1 -1
- package/dist/components/concept-compare-rail.d.ts +50 -0
- package/dist/components/concept-compare-rail.js +5 -0
- package/dist/components/concept-compare.d.ts +110 -0
- package/dist/components/concept-compare.js +238 -0
- package/dist/components/concept-convergence.d.ts +41 -0
- package/dist/components/concept-convergence.js +53 -0
- package/dist/components/convergence.d.ts +25 -0
- package/dist/components/convergence.js +4 -0
- package/dist/components/date-input.d.ts +1 -1
- package/dist/components/event-card.js +1 -1
- package/dist/components/event-compact-row.d.ts +1 -1
- package/dist/components/event-compact-row.js +1 -1
- package/dist/components/event-detail-panel.d.ts +171 -25
- package/dist/components/event-detail-panel.js +472 -175
- package/dist/components/event-index-row.js +1 -1
- package/dist/components/event-list-row-wide.js +2 -2
- package/dist/components/event-list-row.js +2 -2
- package/dist/components/explainer-steps.d.ts +34 -0
- package/dist/components/explainer-steps.js +36 -0
- package/dist/components/glass-ground.d.ts +66 -0
- package/dist/components/glass-ground.js +3 -0
- package/dist/components/hub-surface.d.ts +27 -0
- package/dist/components/hub-surface.js +30 -0
- package/dist/components/hue-chip.d.ts +70 -0
- package/dist/components/hue-chip.js +3 -0
- package/dist/components/kitchen-dossier.d.ts +88 -0
- package/dist/components/kitchen-dossier.js +187 -0
- package/dist/components/menu-dead-end.d.ts +56 -0
- package/dist/components/menu-dead-end.js +49 -0
- package/dist/components/menu-family-block.d.ts +99 -0
- package/dist/components/menu-family-block.js +155 -0
- package/dist/components/menu-family-card.d.ts +65 -0
- package/dist/components/menu-family-card.js +79 -0
- package/dist/components/menu-field.d.ts +57 -0
- package/dist/components/menu-field.js +93 -0
- package/dist/components/menu-filter-chips.d.ts +86 -0
- package/dist/components/menu-filter-chips.js +122 -0
- package/dist/components/menu-group-rows.d.ts +53 -0
- package/dist/components/menu-group-rows.js +67 -0
- package/dist/components/menu-hub-hero.d.ts +65 -0
- package/dist/components/menu-hub-hero.js +103 -0
- package/dist/components/menu-index-header.d.ts +37 -0
- package/dist/components/menu-index-header.js +68 -0
- package/dist/components/menu-index-list.d.ts +48 -0
- package/dist/components/menu-index-list.js +96 -0
- package/dist/components/menu-intent-hero.d.ts +69 -0
- package/dist/components/menu-intent-hero.js +87 -0
- package/dist/components/menu-intent-tiles.d.ts +31 -0
- package/dist/components/menu-intent-tiles.js +50 -0
- package/dist/components/menu-item.d.ts +127 -0
- package/dist/components/menu-item.js +5 -0
- package/dist/components/menu-kitchen-list.d.ts +82 -0
- package/dist/components/menu-kitchen-list.js +5 -0
- package/dist/components/menu-mocks.d.ts +90 -0
- package/dist/components/menu-mocks.js +504 -0
- package/dist/components/menu-types.d.ts +421 -0
- package/dist/components/menu-types.js +1 -0
- package/dist/components/motion-icon-controls.js +2 -2
- package/dist/components/motion-icon-set.js +21 -9
- package/dist/components/motion-icon.d.ts +22 -1
- package/dist/components/motion-icon.js +1 -1
- package/dist/components/open-now-list.d.ts +40 -0
- package/dist/components/open-now-list.js +69 -0
- package/dist/components/photo-ground.d.ts +64 -0
- package/dist/components/photo-ground.js +3 -0
- package/dist/components/place-about-tab.js +2 -2
- package/dist/components/place-details-mobile.js +2 -2
- package/dist/components/place-types.d.ts +112 -1
- package/dist/components/qa-block.d.ts +36 -0
- package/dist/components/qa-block.js +24 -0
- package/dist/components/scroll-fade.js +3 -121
- package/dist/components/signature-chip.d.ts +37 -0
- package/dist/components/signature-chip.js +4 -0
- package/dist/components/snap-rail.d.ts +48 -5
- package/dist/components/snap-rail.js +3 -51
- package/dist/components/stat-banner.d.ts +47 -0
- package/dist/components/stat-banner.js +61 -0
- package/dist/components/story.d.ts +34 -0
- package/dist/components/story.js +3 -0
- package/dist/components/tag.d.ts +2 -2
- package/dist/components/text.d.ts +1 -1
- package/dist/components/top-comparison.d.ts +28 -0
- package/dist/components/top-comparison.js +76 -0
- package/dist/components/top-cross-link.d.ts +34 -0
- package/dist/components/top-cross-link.js +101 -0
- package/dist/components/top-ranking-entry.d.ts +53 -0
- package/dist/components/top-ranking-entry.js +217 -0
- package/dist/components/top-ranking-hero.d.ts +61 -0
- package/dist/components/top-ranking-hero.js +99 -0
- package/dist/components/top-ranking-legend.d.ts +69 -0
- package/dist/components/top-ranking-legend.js +124 -0
- package/dist/components/top-types.d.ts +109 -0
- package/dist/components/top-types.js +1 -0
- package/dist/components/venue-grade-dimensions.d.ts +38 -0
- package/dist/components/venue-grade-dimensions.js +3 -0
- package/dist/components/venue-quotes.d.ts +32 -0
- package/dist/components/venue-quotes.js +3 -0
- package/dist/components/venue-wall.d.ts +41 -0
- package/dist/components/venue-wall.js +118 -0
- package/dist/components/weekday-theme-banner.d.ts +70 -0
- package/dist/components/weekday-theme-banner.js +127 -0
- package/dist/components/weekend-panel.js +2 -2
- package/package.json +1 -1
- package/src/components/colour-dictionary.stories.tsx +227 -0
- package/src/components/concept-compare-rail.tsx +131 -0
- package/src/components/concept-compare.stories.tsx +172 -0
- package/src/components/concept-compare.tsx +443 -0
- package/src/components/concept-convergence.stories.tsx +53 -0
- package/src/components/concept-convergence.tsx +90 -0
- package/src/components/convergence.stories.tsx +54 -0
- package/src/components/convergence.tsx +177 -0
- package/src/components/event-compact-row.tsx +1 -1
- package/src/components/event-detail-panel.stories.tsx +205 -97
- package/src/components/event-detail-panel.test.tsx +181 -0
- package/src/components/event-detail-panel.tsx +703 -185
- package/src/components/explainer-steps.stories.tsx +46 -0
- package/src/components/explainer-steps.tsx +74 -0
- package/src/components/glass-ground.tsx +129 -0
- package/src/components/hub-surface.stories.tsx +68 -0
- package/src/components/hub-surface.tsx +50 -0
- package/src/components/hue-chip.stories.tsx +76 -0
- package/src/components/hue-chip.test.tsx +62 -0
- package/src/components/hue-chip.tsx +99 -0
- package/src/components/kitchen-dossier.stories.tsx +108 -0
- package/src/components/kitchen-dossier.tsx +322 -0
- package/src/components/menu-dead-end.stories.tsx +67 -0
- package/src/components/menu-dead-end.tsx +127 -0
- package/src/components/menu-family-block.stories.tsx +91 -0
- package/src/components/menu-family-block.tsx +314 -0
- package/src/components/menu-family-card.stories.tsx +120 -0
- package/src/components/menu-family-card.tsx +191 -0
- package/src/components/menu-field.stories.tsx +74 -0
- package/src/components/menu-field.tsx +199 -0
- package/src/components/menu-filter-chips.stories.tsx +107 -0
- package/src/components/menu-filter-chips.tsx +238 -0
- package/src/components/menu-group-rows.stories.tsx +54 -0
- package/src/components/menu-group-rows.tsx +133 -0
- package/src/components/menu-hub-hero.stories.tsx +92 -0
- package/src/components/menu-hub-hero.tsx +187 -0
- package/src/components/menu-index-header.stories.tsx +72 -0
- package/src/components/menu-index-header.tsx +125 -0
- package/src/components/menu-index-list.stories.tsx +50 -0
- package/src/components/menu-index-list.tsx +149 -0
- package/src/components/menu-intent-hero.stories.tsx +67 -0
- package/src/components/menu-intent-hero.tsx +189 -0
- package/src/components/menu-intent-tiles.stories.tsx +54 -0
- package/src/components/menu-intent-tiles.tsx +76 -0
- package/src/components/menu-item.tsx +416 -0
- package/src/components/menu-kitchen-list.stories.tsx +67 -0
- package/src/components/menu-kitchen-list.test.tsx +78 -0
- package/src/components/menu-kitchen-list.tsx +284 -0
- package/src/components/menu-mocks.ts +592 -0
- package/src/components/menu-types.ts +442 -0
- package/src/components/motion-icon-controls.tsx +11 -11
- package/src/components/motion-icon-set.tsx +36 -8
- package/src/components/motion-icon.test.tsx +23 -1
- package/src/components/motion-icon.tsx +20 -0
- package/src/components/open-now-list.stories.tsx +76 -0
- package/src/components/open-now-list.tsx +127 -0
- package/src/components/photo-ground.tsx +147 -0
- package/src/components/place-types.ts +112 -0
- package/src/components/qa-block.stories.tsx +43 -0
- package/src/components/qa-block.tsx +60 -0
- package/src/components/signature-chip.tsx +77 -0
- package/src/components/snap-rail.tsx +133 -9
- package/src/components/stat-banner.stories.tsx +100 -0
- package/src/components/stat-banner.tsx +117 -0
- package/src/components/story.tsx +225 -0
- package/src/components/top-comparison.stories.tsx +78 -0
- package/src/components/top-comparison.tsx +151 -0
- package/src/components/top-cross-link.stories.tsx +84 -0
- package/src/components/top-cross-link.tsx +171 -0
- package/src/components/top-ranking-entry.stories.tsx +171 -0
- package/src/components/top-ranking-entry.test.tsx +105 -0
- package/src/components/top-ranking-entry.tsx +425 -0
- package/src/components/top-ranking-hero.stories.tsx +76 -0
- package/src/components/top-ranking-hero.tsx +218 -0
- package/src/components/top-ranking-legend.stories.tsx +78 -0
- package/src/components/top-ranking-legend.tsx +239 -0
- package/src/components/top-types.ts +110 -0
- package/src/components/venue-grade-dimensions.stories.tsx +83 -0
- package/src/components/venue-grade-dimensions.tsx +91 -0
- package/src/components/venue-quotes.stories.tsx +59 -0
- package/src/components/venue-quotes.tsx +64 -0
- package/src/components/venue-wall.stories.tsx +78 -0
- package/src/components/venue-wall.tsx +185 -0
- package/src/components/weekday-theme-banner.stories.tsx +113 -0
- package/src/components/weekday-theme-banner.tsx +231 -0
- package/dist/{chunk-XWMRABZW.js → chunk-HSIYYA2E.js} +1 -1
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cn } from "../lib/utils";
|
|
5
|
+
import { PhotoGround } from "./photo-ground";
|
|
6
|
+
import { SnapRail, SnapRailDots } from "./snap-rail";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* ConceptCompareRail — the rooms as a rail, the card's backdrop following the
|
|
10
|
+
* active room, and the foot band that carries the page dots.
|
|
11
|
+
*
|
|
12
|
+
* On the phone the card IS the current room's photograph: the head, the rail
|
|
13
|
+
* and the foot all sit on it, and it cross-fades to the next room as the
|
|
14
|
+
* reader swipes. That needs the rail's active index, which is state — so this
|
|
15
|
+
* is the one client boundary in `ConceptCompare`. It takes only what can cross
|
|
16
|
+
* that boundary: photograph URLs, initials, and the pre-rendered rooms and
|
|
17
|
+
* foot as children. `labels`, `formatPrice` and the rest stay server-side.
|
|
18
|
+
*
|
|
19
|
+
* ## Why the backdrop lives here and not in each slide
|
|
20
|
+
*
|
|
21
|
+
* A slide carrying its own photograph is a boxed card sliding over a dark
|
|
22
|
+
* ground; the backdrop changing under a transparent slide is the reader
|
|
23
|
+
* turning to look at the next room. The second is the smoother thing, and it
|
|
24
|
+
* is also cheaper to look at — one photograph at a time instead of the edge of
|
|
25
|
+
* the next one peeking in.
|
|
26
|
+
*
|
|
27
|
+
* ## Why the foot is here too
|
|
28
|
+
*
|
|
29
|
+
* The dots need the rail's state, and on the phone they belong INSIDE the foot
|
|
30
|
+
* band's glass — under the rail they sat on a strip of bare photograph between
|
|
31
|
+
* the room's scrim and the foot's. So the foot renders here, with the dots as
|
|
32
|
+
* its first row below `lg`, and `ConceptCompare` hands it the foot's content.
|
|
33
|
+
*
|
|
34
|
+
* Desktop ignores the backdrop and the dots (`lg:hidden`); each room carries
|
|
35
|
+
* its own photograph there, side by side, and the foot is an absolute glass
|
|
36
|
+
* band over them.
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
export type ConceptCompareBackdrop = {
|
|
40
|
+
/** The room's photograph. Absent: the ground with the venue's initial. */
|
|
41
|
+
src?: string;
|
|
42
|
+
/** The venue's first letter, for the no-photograph fallback. */
|
|
43
|
+
initial: string;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export type ConceptCompareRailProps = {
|
|
47
|
+
backdrops: ConceptCompareBackdrop[];
|
|
48
|
+
/** Classes for the rail itself — the desktop grid lives here. */
|
|
49
|
+
railClassName?: string;
|
|
50
|
+
/** The foot's content: the note and the action. Omit for no foot. */
|
|
51
|
+
foot?: React.ReactNode;
|
|
52
|
+
children: React.ReactNode;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The foot band's glass — two behaviours, one element.
|
|
57
|
+
*
|
|
58
|
+
* On the phone the band sits directly under a slide whose own scrim has
|
|
59
|
+
* already reached 0.9 at its bottom edge, so the glass is SOLID from its first
|
|
60
|
+
* pixel: a fade-in here left a lighter strip at the seam where the photograph
|
|
61
|
+
* showed through between the slide's darkness and the foot's, and the two read
|
|
62
|
+
* as disconnected pieces. From `lg` the foot floats over open photography with
|
|
63
|
+
* the room text well above it, so there it fades out over its top edge on the
|
|
64
|
+
* same curve as its mask, the way the head does at its underside.
|
|
65
|
+
*
|
|
66
|
+
* Same literal as every other scrim on the card, so they read as one shadow;
|
|
67
|
+
* not `var(--scrim)`, which is the app's token and not this package's.
|
|
68
|
+
*/
|
|
69
|
+
const FOOT_GLASS = cn(
|
|
70
|
+
"before:pointer-events-none before:absolute before:inset-0 before:-z-10 before:content-[''] before:backdrop-blur-lg",
|
|
71
|
+
"before:bg-[oklch(0.16_0.012_55_/_0.9)]",
|
|
72
|
+
"lg:before:[mask-image:linear-gradient(to_top,black_60%,transparent_100%)] lg:before:bg-[linear-gradient(to_top,oklch(0.16_0.012_55_/_0.88)_0%,oklch(0.16_0.012_55_/_0.84)_60%,oklch(0.16_0.012_55_/_0.4)_85%,oklch(0.16_0.012_55_/_0)_100%)]"
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
export function ConceptCompareRail({
|
|
76
|
+
backdrops,
|
|
77
|
+
railClassName,
|
|
78
|
+
foot,
|
|
79
|
+
children,
|
|
80
|
+
}: ConceptCompareRailProps) {
|
|
81
|
+
const [active, setActive] = React.useState(0);
|
|
82
|
+
const count = React.Children.count(children);
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<>
|
|
86
|
+
{/* The backdrop: every room's photograph stacked, the active one shown,
|
|
87
|
+
cross-fading on swipe. Positioned against the CARD — `ConceptCompare`
|
|
88
|
+
renders this inside its `relative isolate` frame. Desktop hides it;
|
|
89
|
+
each room carries its own photograph there. */}
|
|
90
|
+
<PhotoGround
|
|
91
|
+
className="-z-10 lg:hidden"
|
|
92
|
+
mode="stack"
|
|
93
|
+
active={active}
|
|
94
|
+
photos={backdrops.map((backdrop) => backdrop.src)}
|
|
95
|
+
initials={backdrops.map((backdrop) => backdrop.initial)}
|
|
96
|
+
overlay
|
|
97
|
+
loading="eager"
|
|
98
|
+
/>
|
|
99
|
+
|
|
100
|
+
{/* `pb-0` over the rail's default `pb-0.5`: two pixels of half-inked
|
|
101
|
+
photograph between the slide's scrim and the foot's glass reads as a
|
|
102
|
+
hairline where none was drawn.
|
|
103
|
+
|
|
104
|
+
`overscroll-x-contain`, because this card is itself a slide in the
|
|
105
|
+
hub's concept carousel. Without it a swipe that reaches the last room
|
|
106
|
+
chains into the outer rail and jumps to the next concept — the reader
|
|
107
|
+
asked to see the fourth kitchen and got a different dish. */}
|
|
108
|
+
<SnapRail
|
|
109
|
+
itemWidth="full"
|
|
110
|
+
gap="sm"
|
|
111
|
+
onActiveChange={setActive}
|
|
112
|
+
className={cn("pb-0 overscroll-x-contain", railClassName)}
|
|
113
|
+
>
|
|
114
|
+
{children}
|
|
115
|
+
</SnapRail>
|
|
116
|
+
|
|
117
|
+
{foot && (
|
|
118
|
+
<div
|
|
119
|
+
className={cn(
|
|
120
|
+
"relative isolate flex flex-col gap-3 px-4 pb-4 pt-3",
|
|
121
|
+
"lg:absolute lg:inset-x-0 lg:bottom-0 lg:z-10 lg:flex-row lg:items-center lg:gap-5 lg:px-5 lg:pb-4 lg:pt-6",
|
|
122
|
+
FOOT_GLASS
|
|
123
|
+
)}
|
|
124
|
+
>
|
|
125
|
+
<SnapRailDots count={count} active={active} className="lg:hidden" />
|
|
126
|
+
{foot}
|
|
127
|
+
</div>
|
|
128
|
+
)}
|
|
129
|
+
</>
|
|
130
|
+
);
|
|
131
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { ConceptCompare } from "./concept-compare";
|
|
3
|
+
import { mockConcept } from "./menu-mocks";
|
|
4
|
+
import type { MenuConceptRow } from "./menu-types";
|
|
5
|
+
|
|
6
|
+
const labels = {
|
|
7
|
+
kind: "DISH CONCEPT",
|
|
8
|
+
cheapest: "Cheapest",
|
|
9
|
+
mentions: (count: number) => `${count} mentions`,
|
|
10
|
+
openRoom: (alias: string, venue: string) => `${alias} at ${venue}`,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const formatPrice = (amount: number) => `${amount} lei`;
|
|
14
|
+
|
|
15
|
+
/** A stand-in venue photograph with enough variance that the glass has something to blur. */
|
|
16
|
+
function room(hue: number, label: string) {
|
|
17
|
+
return (
|
|
18
|
+
"data:image/svg+xml;utf8," +
|
|
19
|
+
encodeURIComponent(
|
|
20
|
+
`<svg xmlns="http://www.w3.org/2000/svg" width="480" height="640"><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="480" height="640" fill="url(#g)"/><circle cx="140" cy="150" r="70" fill="hsl(${hue} 40% 82%)" opacity=".55"/><rect x="240" y="360" width="200" height="140" fill="hsl(${hue} 15% 18%)" opacity=".7"/><text x="50%" y="92%" font-family="monospace" font-size="20" fill="#fff" text-anchor="middle">${label}</text></svg>`
|
|
21
|
+
)
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const rooms: MenuConceptRow[] = [
|
|
26
|
+
{
|
|
27
|
+
place_slug: "casa-maramureseana",
|
|
28
|
+
place_name: "Casa Maramureșeană",
|
|
29
|
+
alias: "Papanași cu Smântână și Dulceață",
|
|
30
|
+
price: 29,
|
|
31
|
+
mentions: 12,
|
|
32
|
+
rating: 4.5,
|
|
33
|
+
place_area: "Centru",
|
|
34
|
+
place_thumbnail_url: room(30, "room 1"),
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
place_slug: "maimuta-plangatoare",
|
|
38
|
+
place_name: "Maimuța Plângătoare",
|
|
39
|
+
alias: "Papanasi cu Gem si Smantana",
|
|
40
|
+
price: 31,
|
|
41
|
+
mentions: 19,
|
|
42
|
+
rating: 4.5,
|
|
43
|
+
place_area: "Centru",
|
|
44
|
+
place_thumbnail_url: room(200, "room 2"),
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
place_slug: "cafe-bulgakov",
|
|
48
|
+
place_name: "Café Bulgakov",
|
|
49
|
+
alias: "Papanași",
|
|
50
|
+
price: 32,
|
|
51
|
+
mentions: 12,
|
|
52
|
+
rating: 4.6,
|
|
53
|
+
place_area: "Centru",
|
|
54
|
+
place_thumbnail_url: room(90, "room 3"),
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
place_slug: "garlic",
|
|
58
|
+
place_name: "GARLIC - bites&tales",
|
|
59
|
+
alias: "Papanași în Țeapă",
|
|
60
|
+
price: 38,
|
|
61
|
+
mentions: 12,
|
|
62
|
+
rating: 4.7,
|
|
63
|
+
place_area: "Centru",
|
|
64
|
+
place_thumbnail_url: room(300, "room 4"),
|
|
65
|
+
},
|
|
66
|
+
];
|
|
67
|
+
|
|
68
|
+
const concept = { ...mockConcept, slug: "papanasi", title: "Papanași", rows: rooms };
|
|
69
|
+
|
|
70
|
+
const figures = [
|
|
71
|
+
{ value: "45", label: "kitchens" },
|
|
72
|
+
{ value: "29–52", label: "lei across them", accent: true },
|
|
73
|
+
{ value: "167", label: "mentions" },
|
|
74
|
+
{ value: "8", label: "names" },
|
|
75
|
+
];
|
|
76
|
+
|
|
77
|
+
const hrefs = Object.fromEntries(rooms.map((r) => [r.place_slug, `/places/${r.place_slug}`]));
|
|
78
|
+
|
|
79
|
+
const seeAll = (
|
|
80
|
+
<a
|
|
81
|
+
href="/menu/dishes/papanasi"
|
|
82
|
+
className="inline-flex h-10 items-center justify-center gap-1.5 rounded-full border border-white/20 bg-white/[0.12] px-4 text-[13.5px] font-bold text-white backdrop-blur-md"
|
|
83
|
+
>
|
|
84
|
+
See all 45 kitchens
|
|
85
|
+
</a>
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const meta: Meta<typeof ConceptCompare> = {
|
|
89
|
+
title: "Menu/ConceptCompare",
|
|
90
|
+
component: ConceptCompare,
|
|
91
|
+
tags: ["autodocs"],
|
|
92
|
+
args: {
|
|
93
|
+
concept,
|
|
94
|
+
labels,
|
|
95
|
+
lede: "45 kitchens make it, and they do not agree on the name",
|
|
96
|
+
formatPrice,
|
|
97
|
+
figures,
|
|
98
|
+
hrefs,
|
|
99
|
+
footnote:
|
|
100
|
+
"The four cheapest of the 45, priced from each menu as it stands — the dearest is 52 lei. One photograph per kitchen; no room here is a room that does not serve it.",
|
|
101
|
+
actions: seeAll,
|
|
102
|
+
},
|
|
103
|
+
decorators: [
|
|
104
|
+
(Story) => (
|
|
105
|
+
<div className="w-[1100px] bg-background p-6">
|
|
106
|
+
<Story />
|
|
107
|
+
</div>
|
|
108
|
+
),
|
|
109
|
+
],
|
|
110
|
+
parameters: {
|
|
111
|
+
docs: {
|
|
112
|
+
description: {
|
|
113
|
+
component:
|
|
114
|
+
"One dish across the kitchens that make it — and **no surfaces at all**. The card is a contact sheet of venue photographs, one per room, and the three readable things float on it through glass: the identity across the top, each kitchen's line over its own photograph, the foot along the bottom. Read ACROSS, not down: four rooms side by side, each with its own name and price. The photographs are placed as cells of the same grid as the rooms, spanning from the head down, so the head's glass genuinely blurs them and every seam lands on a room boundary. Nothing in it is themed — the edge is the only thing that adapts to the page.",
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export default meta;
|
|
121
|
+
type Story = StoryObj<typeof ConceptCompare>;
|
|
122
|
+
|
|
123
|
+
export const Default: Story = {};
|
|
124
|
+
|
|
125
|
+
/** The same card on a dark page: identical inside, a light hairline and deeper shadow outside. */
|
|
126
|
+
export const DarkPage: Story = {
|
|
127
|
+
decorators: [
|
|
128
|
+
(Story) => (
|
|
129
|
+
<div className="dark w-[1100px] bg-background p-6">
|
|
130
|
+
<Story />
|
|
131
|
+
</div>
|
|
132
|
+
),
|
|
133
|
+
],
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
/** Three rooms: one across on the phone, then two. */
|
|
137
|
+
export const ThreeRooms: Story = {
|
|
138
|
+
args: {
|
|
139
|
+
concept: { ...concept, title: "Kürtőskalács", rows: rooms.slice(0, 3) },
|
|
140
|
+
lede: "Three kitchens in the city make it",
|
|
141
|
+
figures: [
|
|
142
|
+
{ value: "3", label: "kitchens" },
|
|
143
|
+
{ value: "14–19", label: "lei across them", accent: true },
|
|
144
|
+
{ value: "11", label: "mentions" },
|
|
145
|
+
{ value: "3", label: "names" },
|
|
146
|
+
],
|
|
147
|
+
footnote:
|
|
148
|
+
"All three kitchens, all three rooms — so the spread above is the whole spread. A concept this thin has no tail to open.",
|
|
149
|
+
actions: undefined,
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
/** A room with no photograph: the ground with the venue's initial, never a grey box. */
|
|
154
|
+
export const MissingPhoto: Story = {
|
|
155
|
+
args: {
|
|
156
|
+
concept: {
|
|
157
|
+
...concept,
|
|
158
|
+
rows: rooms.map((r, i) => (i === 2 ? { ...r, place_thumbnail_url: undefined } : r)),
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
/** 2×2 on the phone — the reading turns from across to around, but it is still four rooms in one view. */
|
|
164
|
+
export const Mobile: Story = {
|
|
165
|
+
decorators: [
|
|
166
|
+
(Story) => (
|
|
167
|
+
<div className="w-[390px] bg-background p-3">
|
|
168
|
+
<Story />
|
|
169
|
+
</div>
|
|
170
|
+
),
|
|
171
|
+
],
|
|
172
|
+
};
|