@snacky/ui 0.6.2 → 0.7.1

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/CHANGELOG.md CHANGED
@@ -4,6 +4,28 @@ How `@snacky/ui` got to its current state. The README documents what the
4
4
  package *is*; this documents how it got there, including the mistakes, so the
5
5
  verification claims in the README can be taken at face value.
6
6
 
7
+ ## ImagePlaceholder added, a non-Figma utility (0.7.0)
8
+
9
+ Every image prop (`ProductCard.imageUrl`, `ProductImage.src`, `Avatar.src`,
10
+ the Banner family's `imageUrl`) has always been required, deliberately - this
11
+ package ships no photography, so there was never anything to default to.
12
+ That was correct as far as it went, but it left a real gap: a consumer with a
13
+ genuinely empty state (a new product with no photo yet) had no sanctioned way
14
+ to say so, and either left `src` empty (silently falling through to the
15
+ browser's own broken-image icon) or invented their own placeholder, which is
16
+ exactly the kind of gap that produced emoji fallbacks elsewhere in this
17
+ project's history.
18
+
19
+ `ImagePlaceholder` closes it: a neutral `bg-surface-variant` box with a
20
+ generic "no image" glyph in `icon-disabled`. The glyph is hand-drawn
21
+ (frame/circle/mountain outline), not one of `SnackyIcons` - it is decorative
22
+ placeholder artwork, not a real icon prop, and the first instinct (reuse the
23
+ package's own `camera` icon, reasoning "at least it's a real glyph") read as
24
+ "take a photo" rather than "no image here" once someone actually looked at
25
+ it. This is a standalone utility, not the 25th documented component - there
26
+ is no Figma node for it, and the README says so explicitly rather than
27
+ letting the count quietly drift.
28
+
7
29
  ## Icon set replaced with the real Figma artwork (0.3.0)
8
30
 
9
31
  The package originally shipped a hand-drawn "starter" icon set: roughly 30
@@ -104,3 +126,12 @@ unverified - see the README's Verification status.
104
126
  enough to wrap onto a second line got clipped instead of growing the banner.
105
127
  Changed to `min-height: 40px` and let the message text take `flex: 1` so it
106
128
  shrinks and wraps within the row instead of overflowing sideways.
129
+ - **PointBalanceBanner's 0.6.2 fix corrected again (0.7.1).** Hugging content
130
+ was a correct read of Figma's own frame in isolation, but wrong once placed
131
+ next to a sibling with different content: the docs gallery's "Default" and
132
+ "LowBalance" stories sit side by side, and a low "0" / "Rp 0" collapsed to a
133
+ fraction of the other's width, visibly stranded inside its card. Back to
134
+ `width: 100%`, but `justify-content` stays at its flex-start default (not
135
+ `space-between`) - the original 0.6.2 bug was the groups spreading apart,
136
+ not the fill-width itself, so this keeps that part of the fix while
137
+ dropping the part that looked wrong once seen with real sibling content.
package/README.md CHANGED
@@ -94,6 +94,32 @@ normally pass no colour. To tint one deliberately, use `color`:
94
94
 
95
95
  Names are listed under **What's here** below. `outline` has 42, `solid` has 11.
96
96
 
97
+ ### 4. Handle a missing image
98
+
99
+ Every image slot (`ProductCard`'s `imageUrl`, `ProductImage`'s `src`,
100
+ `Avatar`'s `src`, the Banner family's `imageUrl`) is a **required** prop, on
101
+ purpose - this package ships no photography, so there is no fallback to fall
102
+ back to. If you leave one out anyway, you get the browser's own broken-image
103
+ icon, not anything from this design system.
104
+
105
+ For a genuinely empty state (a new product with no photo yet, a user with no
106
+ avatar), pass `ImagePlaceholder` explicitly instead of inventing your own:
107
+
108
+ ```tsx
109
+ import { ImagePlaceholder, ProductCard } from '@snacky/ui';
110
+
111
+ {photo ? (
112
+ <ProductCard imageUrl={photo} ... />
113
+ ) : (
114
+ <ImagePlaceholder width={152} height={128} />
115
+ )}
116
+ ```
117
+
118
+ It renders a neutral `bg-surface-variant` box with a generic "no image" glyph
119
+ in `icon-disabled` - not a `SnackyIcons` icon, since this is decorative
120
+ placeholder artwork rather than a real icon prop. Apply your own
121
+ `className`/border radius to match whatever slot it fills.
122
+
97
123
  ## What's here
98
124
 
99
125
  All 24 documented components, each matching its `code.tsx` sample's prop
@@ -118,6 +144,9 @@ the same shell with different `children`, so you get two components rather
118
144
  than 22 near-duplicates. Their spacing varies per variant in Figma, so the
119
145
  shells ship sensible defaults and expect `children` to override it.
120
146
 
147
+ Plus `ImagePlaceholder`, a standalone utility (see **Handle a missing image**
148
+ above) - not one of the 24, there is no Figma node for it.
149
+
121
150
  ## Verification status
122
151
 
123
152
  Every component is diffed against `index.html`'s own Live Preview
package/dist/index.cjs CHANGED
@@ -38,6 +38,7 @@ __export(index_exports, {
38
38
  HeroBanner: () => HeroBanner,
39
39
  IconButton: () => IconButton,
40
40
  Illustration: () => Illustration,
41
+ ImagePlaceholder: () => ImagePlaceholder,
41
42
  NavBar: () => NavBar,
42
43
  NotificationBadge: () => NotificationBadge,
43
44
  NotificationListItem: () => NotificationListItem,
@@ -1257,6 +1258,39 @@ function ProductCard(props) {
1257
1258
  }
1258
1259
  );
1259
1260
  }
1261
+
1262
+ // src/components/ImagePlaceholder/ImagePlaceholder.tsx
1263
+ var import_jsx_runtime33 = require("react/jsx-runtime");
1264
+ function ImagePlaceholder({ width, height, className }) {
1265
+ const iconSize = Math.round(Math.min(width, height) * 0.32);
1266
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
1267
+ "div",
1268
+ {
1269
+ className: cx("snacky-image-placeholder", className),
1270
+ style: { width, height },
1271
+ role: "img",
1272
+ "aria-label": "No image",
1273
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
1274
+ "svg",
1275
+ {
1276
+ width: iconSize,
1277
+ height: iconSize,
1278
+ viewBox: "0 0 24 24",
1279
+ fill: "none",
1280
+ stroke: "currentColor",
1281
+ strokeWidth: 2,
1282
+ strokeLinecap: "round",
1283
+ strokeLinejoin: "round",
1284
+ children: [
1285
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }),
1286
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("circle", { cx: "8.5", cy: "8.5", r: "1.5", fill: "currentColor", stroke: "none" }),
1287
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("polyline", { points: "21 15 16 10 5 21" })
1288
+ ]
1289
+ }
1290
+ )
1291
+ }
1292
+ );
1293
+ }
1260
1294
  // Annotate the CommonJS export names for ESM import in node:
1261
1295
  0 && (module.exports = {
1262
1296
  Accordion,
@@ -1277,6 +1311,7 @@ function ProductCard(props) {
1277
1311
  HeroBanner,
1278
1312
  IconButton,
1279
1313
  Illustration,
1314
+ ImagePlaceholder,
1280
1315
  NavBar,
1281
1316
  NotificationBadge,
1282
1317
  NotificationListItem,