@stoovles/gap-kit 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +2417 -0
- package/dist/styles.css +4309 -0
- package/guidelines/components/accordion.md +99 -0
- package/guidelines/components/breadcrumb.md +74 -0
- package/guidelines/components/buttons.md +90 -0
- package/guidelines/components/checkbox.md +86 -0
- package/guidelines/components/chip.md +77 -0
- package/guidelines/components/divider.md +52 -0
- package/guidelines/components/dropdown.md +125 -0
- package/guidelines/components/filter-sort.md +108 -0
- package/guidelines/components/fulfillment.md +100 -0
- package/guidelines/components/global-footer.md +71 -0
- package/guidelines/components/global-header.md +67 -0
- package/guidelines/components/hamburger-nav.md +79 -0
- package/guidelines/components/handle.md +49 -0
- package/guidelines/components/icons.md +147 -0
- package/guidelines/components/link.md +70 -0
- package/guidelines/components/logo.md +63 -0
- package/guidelines/components/mega-nav.md +103 -0
- package/guidelines/components/notification.md +97 -0
- package/guidelines/components/pagination.md +88 -0
- package/guidelines/components/popover.md +77 -0
- package/guidelines/components/price.md +86 -0
- package/guidelines/components/product-card.md +82 -0
- package/guidelines/components/radio.md +92 -0
- package/guidelines/components/search-input.md +63 -0
- package/guidelines/components/selector-swatch.md +78 -0
- package/guidelines/components/selector.md +95 -0
- package/guidelines/components/slider.md +116 -0
- package/guidelines/components/switch.md +108 -0
- package/guidelines/components/tabs.md +83 -0
- package/guidelines/components/text-input.md +80 -0
- package/guidelines/composition/buy-box.md +132 -0
- package/guidelines/composition/recommendations.md +100 -0
- package/package.json +38 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Buy Box
|
|
2
|
+
|
|
3
|
+
The Buy Box is the core purchase area on a Product Detail Page (PDP). It is **not** a single component — it is a composition of existing atoms and components arranged in a specific vertical layout.
|
|
4
|
+
|
|
5
|
+
## Structure
|
|
6
|
+
|
|
7
|
+
Build a Buy Box by stacking the following components top-to-bottom:
|
|
8
|
+
|
|
9
|
+
1. **Breadcrumb** — navigation context (e.g. "Women / Jeans / Slim Fit")
|
|
10
|
+
2. **Product Name** — plain text styled with `--text-header-font-size` (16px) and `--font-weight-base-heavier`
|
|
11
|
+
3. **Price** — use the `Price` component to show original, sale, and discount pricing
|
|
12
|
+
4. **Notification** (optional) — inline variant for promotional messaging (e.g. "Extra 40% off with code SAVE40")
|
|
13
|
+
5. **SelectorSwatch + SwatchGrid** — color selection with swatches; show the selected color label
|
|
14
|
+
6. **SelectorGroup + Selector** — size selection pills with a "Size Guide" link
|
|
15
|
+
7. **Fulfillment** — shipping/pickup tiles for delivery options
|
|
16
|
+
8. **Button (primary)** — "Add to Bag" full-width CTA
|
|
17
|
+
9. **BopisSwitch** — buy online, pick up in store toggle with store info
|
|
18
|
+
10. **Accordion** — collapsible sections for Product Details, Fit & Sizing, Shipping & Returns
|
|
19
|
+
|
|
20
|
+
## Example
|
|
21
|
+
|
|
22
|
+
```jsx
|
|
23
|
+
import {
|
|
24
|
+
Breadcrumb,
|
|
25
|
+
Price,
|
|
26
|
+
Notification,
|
|
27
|
+
SelectorSwatch,
|
|
28
|
+
SwatchGrid,
|
|
29
|
+
SelectorGroup,
|
|
30
|
+
Selector,
|
|
31
|
+
FulfillmentTile,
|
|
32
|
+
Fulfillment,
|
|
33
|
+
Button,
|
|
34
|
+
BopisSwitch,
|
|
35
|
+
Accordion,
|
|
36
|
+
AccordionItem,
|
|
37
|
+
} from "@stoovles/gap-kit";
|
|
38
|
+
|
|
39
|
+
function BuyBox() {
|
|
40
|
+
return (
|
|
41
|
+
<div style={{ maxWidth: 400, display: "flex", flexDirection: "column", gap: 16 }}>
|
|
42
|
+
<Breadcrumb items={[
|
|
43
|
+
{ label: "Women", href: "/women" },
|
|
44
|
+
{ label: "Jeans", href: "/women/jeans" },
|
|
45
|
+
{ label: "Slim Fit", href: "/women/jeans/slim" },
|
|
46
|
+
]} />
|
|
47
|
+
|
|
48
|
+
<h1 className="gap-buy-box-name">Mid Rise Vintage Slim Jeans</h1>
|
|
49
|
+
|
|
50
|
+
<Price
|
|
51
|
+
original="$79.95"
|
|
52
|
+
sale="$49.99"
|
|
53
|
+
discount="38% off"
|
|
54
|
+
/>
|
|
55
|
+
|
|
56
|
+
<Notification type="info" variant="inline">
|
|
57
|
+
Extra 40% off with code SAVE40
|
|
58
|
+
</Notification>
|
|
59
|
+
|
|
60
|
+
<SelectorGroup label="Color" selectedLabel="Dark Wash">
|
|
61
|
+
<SwatchGrid>
|
|
62
|
+
<SelectorSwatch color="#2C3E50" label="Dark Wash" active />
|
|
63
|
+
<SelectorSwatch color="#8BA3C7" label="Light Wash" />
|
|
64
|
+
<SelectorSwatch color="#1A1A1A" label="Black" />
|
|
65
|
+
</SwatchGrid>
|
|
66
|
+
</SelectorGroup>
|
|
67
|
+
|
|
68
|
+
<SelectorGroup label="Size" selectedLabel="8">
|
|
69
|
+
<Selector options={[
|
|
70
|
+
{ label: "4", value: "4" },
|
|
71
|
+
{ label: "6", value: "6" },
|
|
72
|
+
{ label: "8", value: "8" },
|
|
73
|
+
{ label: "10", value: "10" },
|
|
74
|
+
{ label: "12", value: "12", unavailable: true },
|
|
75
|
+
]} value="8" />
|
|
76
|
+
</SelectorGroup>
|
|
77
|
+
|
|
78
|
+
<Fulfillment>
|
|
79
|
+
<FulfillmentTile
|
|
80
|
+
title="Shipping"
|
|
81
|
+
availability="In Stock"
|
|
82
|
+
selected
|
|
83
|
+
>
|
|
84
|
+
Free on orders $50+
|
|
85
|
+
</FulfillmentTile>
|
|
86
|
+
<FulfillmentTile
|
|
87
|
+
title="Pick Up"
|
|
88
|
+
availability="Available nearby"
|
|
89
|
+
>
|
|
90
|
+
Ready in 2 hours
|
|
91
|
+
</FulfillmentTile>
|
|
92
|
+
</Fulfillment>
|
|
93
|
+
|
|
94
|
+
<Button variant="primary" fullWidth>Add to Bag</Button>
|
|
95
|
+
|
|
96
|
+
<BopisSwitch
|
|
97
|
+
storeLabel="Union Square"
|
|
98
|
+
storeSubtext="0.3 mi"
|
|
99
|
+
availability="In Stock - Few Left"
|
|
100
|
+
/>
|
|
101
|
+
|
|
102
|
+
<Accordion>
|
|
103
|
+
<AccordionItem title="Product Details">
|
|
104
|
+
<p>Mid rise. Slim through hip and thigh. Premium stretch denim.</p>
|
|
105
|
+
</AccordionItem>
|
|
106
|
+
<AccordionItem title="Fit & Sizing">
|
|
107
|
+
<p>Model is 5'10" and wearing a size 8.</p>
|
|
108
|
+
</AccordionItem>
|
|
109
|
+
<AccordionItem title="Shipping & Returns">
|
|
110
|
+
<p>Free shipping on $50+. Free returns within 30 days.</p>
|
|
111
|
+
</AccordionItem>
|
|
112
|
+
</Accordion>
|
|
113
|
+
</div>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Layout guidelines
|
|
119
|
+
|
|
120
|
+
- The Buy Box should be placed to the **right** of the product image gallery on desktop, or **below** on mobile.
|
|
121
|
+
- Maximum width: ~400px on desktop; full-width on mobile.
|
|
122
|
+
- Use consistent 16px vertical spacing between sections.
|
|
123
|
+
- The "Add to Bag" button should always be the most prominent element.
|
|
124
|
+
- Promotional notifications should appear above the color selector.
|
|
125
|
+
- Accordion sections at the bottom should default to collapsed.
|
|
126
|
+
|
|
127
|
+
## Rules
|
|
128
|
+
|
|
129
|
+
- Do NOT create a standalone Buy Box component — compose it from existing atoms.
|
|
130
|
+
- Ensure the `SelectorGroup` label shows the currently selected value (e.g. "Color: Dark Wash").
|
|
131
|
+
- Size pills with `unavailable: true` get the diagonal slash treatment.
|
|
132
|
+
- Use the `Fulfillment` component for ship/pickup options, not radio buttons.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Recommendations
|
|
2
|
+
|
|
3
|
+
A horizontal carousel of product cards used for "You may also like", "Recently viewed", "Complete the look", and other recommendation placements. This is a **composition** — not a standalone component — built from existing atoms.
|
|
4
|
+
|
|
5
|
+
## Structure
|
|
6
|
+
|
|
7
|
+
1. **Section header** — Bold title (e.g. "You May Also Like") styled with `--text-header-font-size` and optional "View All" link
|
|
8
|
+
2. **Horizontal scroll container** — A flex row with `overflow-x: auto` containing multiple `ProductCard` components
|
|
9
|
+
3. **Navigation arrows** (optional) — Left/right buttons using the `Handle` component or simple chevron icons to scroll the carousel
|
|
10
|
+
|
|
11
|
+
## Example
|
|
12
|
+
|
|
13
|
+
```jsx
|
|
14
|
+
import { ProductCard, Link } from "@stoovles/gap-kit";
|
|
15
|
+
|
|
16
|
+
function Recommendations({ title, products, viewAllHref }) {
|
|
17
|
+
return (
|
|
18
|
+
<section style={{ width: "100%", display: "flex", flexDirection: "column", gap: 16 }}>
|
|
19
|
+
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
|
|
20
|
+
<h2 className="gap-section-title">{title}</h2>
|
|
21
|
+
{viewAllHref && <Link href={viewAllHref}>View All</Link>}
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<div style={{
|
|
25
|
+
display: "flex",
|
|
26
|
+
gap: 16,
|
|
27
|
+
overflowX: "auto",
|
|
28
|
+
scrollSnapType: "x mandatory",
|
|
29
|
+
paddingBottom: 8,
|
|
30
|
+
}}>
|
|
31
|
+
{products.map((product) => (
|
|
32
|
+
<div key={product.id} style={{ flex: "0 0 220px", scrollSnapAlign: "start" }}>
|
|
33
|
+
<ProductCard
|
|
34
|
+
imageUrl={product.imageUrl}
|
|
35
|
+
name={product.name}
|
|
36
|
+
originalPrice={product.originalPrice}
|
|
37
|
+
salePrice={product.salePrice}
|
|
38
|
+
discount={product.discount}
|
|
39
|
+
rating={product.rating}
|
|
40
|
+
reviewCount={product.reviewCount}
|
|
41
|
+
swatches={product.swatches}
|
|
42
|
+
moreSwatches={product.moreSwatches}
|
|
43
|
+
onClick={() => navigate(product.href)}
|
|
44
|
+
/>
|
|
45
|
+
</div>
|
|
46
|
+
))}
|
|
47
|
+
</div>
|
|
48
|
+
</section>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Mini variant for recently viewed
|
|
54
|
+
|
|
55
|
+
```jsx
|
|
56
|
+
function RecentlyViewed({ products }) {
|
|
57
|
+
return (
|
|
58
|
+
<section>
|
|
59
|
+
<h3 className="gap-section-title">Recently Viewed</h3>
|
|
60
|
+
<div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
|
|
61
|
+
{products.map((product) => (
|
|
62
|
+
<ProductCard
|
|
63
|
+
key={product.id}
|
|
64
|
+
variant="mini"
|
|
65
|
+
imageUrl={product.imageUrl}
|
|
66
|
+
name={product.name}
|
|
67
|
+
originalPrice={product.originalPrice}
|
|
68
|
+
salePrice={product.salePrice}
|
|
69
|
+
/>
|
|
70
|
+
))}
|
|
71
|
+
</div>
|
|
72
|
+
</section>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Placement guidelines
|
|
78
|
+
|
|
79
|
+
| Placement | Where | Product card variant |
|
|
80
|
+
|-----------|-------|---------------------|
|
|
81
|
+
| "You May Also Like" | Below PDP buy box | Default (220px) |
|
|
82
|
+
| "Complete the Look" | PDP, below main content | Default (220px) |
|
|
83
|
+
| "Recently Viewed" | PDP sidebar or footer | Mini (326px) |
|
|
84
|
+
| "Trending Now" | Homepage, PLP | Default (220px) |
|
|
85
|
+
|
|
86
|
+
## Layout guidelines
|
|
87
|
+
|
|
88
|
+
- Show 4–6 cards visible on desktop; the rest scroll horizontally.
|
|
89
|
+
- Use `scroll-snap-type: x mandatory` for smooth snapping.
|
|
90
|
+
- On mobile, show 1.5 cards to hint at scrollability.
|
|
91
|
+
- The section header and "View All" link should not scroll — only the card row scrolls.
|
|
92
|
+
- Use 16px gap between cards (matching `--spacing-utk-l`).
|
|
93
|
+
|
|
94
|
+
## Rules
|
|
95
|
+
|
|
96
|
+
- Do NOT create a standalone Recommendations component — compose using `ProductCard`.
|
|
97
|
+
- Each card should be wrapped in a fixed-width container (220px for default, 326px for mini) to prevent flex stretching.
|
|
98
|
+
- Always include an `onClick` on each card for navigation.
|
|
99
|
+
- Use the mini variant for compact placements like sidebars.
|
|
100
|
+
- The horizontal scroll container should hide the scrollbar on desktop (`::-webkit-scrollbar { display: none }`).
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@stoovles/gap-kit",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Gap 1.0.0 MakeKit for Figma Make",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"module": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
},
|
|
14
|
+
"./styles.css": "./dist/styles.css"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"guidelines"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"dev": "vite",
|
|
22
|
+
"build": "vite build && node scripts/bundle-css.mjs",
|
|
23
|
+
"preview": "vite preview"
|
|
24
|
+
},
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
27
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/react": "^19.0.0",
|
|
31
|
+
"@types/react-dom": "^19.0.0",
|
|
32
|
+
"@vitejs/plugin-react": "^4.3.0",
|
|
33
|
+
"react": "^19.0.0",
|
|
34
|
+
"react-dom": "^19.0.0",
|
|
35
|
+
"typescript": "^5.7.0",
|
|
36
|
+
"vite": "^6.0.0"
|
|
37
|
+
}
|
|
38
|
+
}
|