barua-ui 0.3.4 → 0.4.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.
@@ -1,7 +1,8 @@
1
1
  /* ==========================================================================
2
2
  Barua UI — Media
3
- Image Viewer, Image Gallery, Carousel, Video Player frame, Audio Player,
4
- Media Controls, Thumbnail, Media Placeholder, Upload Preview grid.
3
+ Image Viewer, Image Gallery, Carousel, Billboard, Poster, Video Player
4
+ frame, Audio Player, Media Controls, Thumbnail, Media Placeholder, Upload
5
+ Preview grid.
5
6
  ========================================================================== */
6
7
 
7
8
  @layer components {
@@ -69,7 +70,7 @@
69
70
  border-radius: var(--b-radius-lg);
70
71
  overflow: hidden;
71
72
  }
72
- .b-carousel__slide img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; }
73
+ .b-carousel__slide > img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; }
73
74
  .b-carousel__nav {
74
75
  position: absolute;
75
76
  inset-block-start: 50%;
@@ -99,6 +100,152 @@
99
100
  background: var(--b-color-accent);
100
101
  }
101
102
 
103
+ /* Posters on a carousel make a shelf: each slide narrows to a poster and
104
+ stops clipping, because the poster owns its frame and needs room to lift. */
105
+ .b-carousel--posters { --b-slide-w: clamp(7.5rem, 30vw, 10.5rem); }
106
+ .b-carousel--posters .b-carousel__track { padding-block: var(--b-space-2); scroll-padding-inline: 0; }
107
+ .b-carousel--posters .b-carousel__slide { border-radius: 0; overflow: visible; }
108
+ @media (hover: none) { .b-carousel--posters .b-carousel__nav { display: none; } }
109
+
110
+ /* ---- Billboard: the featured title, art behind, words in front ------------
111
+ A media storefront's front window. The block is tall on a phone so the
112
+ picture reads, and capped on a desktop so the shelves stay above the
113
+ fold. The scrim fades the art into the page colour from below and from
114
+ the start edge, so the words never fight the picture and the shelf
115
+ underneath feels attached rather than pasted on. Put .b-container on the
116
+ body for the gutters; --b-billboard-h and --b-billboard-focus are the
117
+ knobs, one for the height and one for where the picture's subject is. */
118
+ .b-billboard {
119
+ position: relative;
120
+ display: flex;
121
+ align-items: flex-end;
122
+ min-block-size: var(--b-billboard-h, min(62svh, 34rem));
123
+ overflow: hidden;
124
+ color: var(--b-text);
125
+ background: var(--b-fill-tertiary);
126
+ }
127
+ .b-billboard__art {
128
+ position: absolute;
129
+ inset: 0;
130
+ inline-size: 100%;
131
+ block-size: 100%;
132
+ object-fit: cover;
133
+ object-position: var(--b-billboard-focus, 50% 20%);
134
+ }
135
+ .b-billboard__scrim {
136
+ position: absolute;
137
+ inset: 0;
138
+ background:
139
+ linear-gradient(to top,
140
+ var(--b-bg) 0%,
141
+ color-mix(in srgb, var(--b-bg) 55%, transparent) 42%,
142
+ transparent 78%),
143
+ linear-gradient(to right,
144
+ color-mix(in srgb, var(--b-bg) 70%, transparent),
145
+ transparent 60%);
146
+ }
147
+ .b-billboard__body {
148
+ position: relative;
149
+ display: flex;
150
+ flex-direction: column;
151
+ align-items: flex-start;
152
+ gap: var(--b-space-3);
153
+ padding-block: var(--b-space-6);
154
+ }
155
+ .b-billboard__body > * { margin: 0; max-inline-size: var(--b-billboard-measure, 38rem); }
156
+ .b-billboard__title {
157
+ margin: 0;
158
+ font-size: clamp(2rem, 8vw, 3.5rem);
159
+ font-weight: var(--b-weight-bold);
160
+ line-height: 1.02;
161
+ letter-spacing: var(--b-tracking-tight);
162
+ text-wrap: balance;
163
+ }
164
+ .b-billboard__lede { margin: 0; color: var(--b-text-secondary); line-height: var(--b-leading-body); }
165
+ .b-billboard__actions { display: flex; flex-wrap: wrap; gap: var(--b-space-2); }
166
+
167
+ /* ---- Poster: a title as a picture with its name under it ------------------
168
+ The unit of a catalogue. The whole block is one link — one thing to tap.
169
+ The frame holds its 2:3 shape before the picture arrives, so a slow
170
+ connection never makes the shelf jump, and a title with no picture shows
171
+ its initial on a plate tinted from the accent rather than a broken image.
172
+ .b-poster--wide is the 16:9 form for an episode; .is-selected marks the
173
+ one that is playing. */
174
+ .b-poster {
175
+ display: flex;
176
+ flex-direction: column;
177
+ gap: var(--b-space-2);
178
+ min-inline-size: 0;
179
+ color: inherit;
180
+ text-decoration: none;
181
+ }
182
+ .b-poster:hover { color: inherit; text-decoration: none; }
183
+ .b-poster__frame {
184
+ position: relative;
185
+ display: grid;
186
+ place-items: center;
187
+ aspect-ratio: var(--b-poster-ratio, 2 / 3);
188
+ overflow: hidden;
189
+ border-radius: var(--b-radius-lg);
190
+ background: color-mix(in srgb, var(--b-color-accent) 18%, var(--b-fill-tertiary));
191
+ container-type: inline-size;
192
+ transition: translate var(--b-duration-normal) var(--b-ease-out), box-shadow var(--b-duration-normal);
193
+ }
194
+ .b-poster__frame > :is(img, video) {
195
+ position: absolute;
196
+ inset: 0;
197
+ inline-size: 100%;
198
+ block-size: 100%;
199
+ aspect-ratio: auto;
200
+ object-fit: cover;
201
+ }
202
+ .b-poster__initial {
203
+ font-size: 30cqi;
204
+ font-weight: var(--b-weight-bold);
205
+ line-height: 1;
206
+ color: color-mix(in srgb, var(--b-color-accent) 55%, var(--b-text-quaternary));
207
+ user-select: none;
208
+ }
209
+ .b-poster__badge {
210
+ position: absolute;
211
+ inset-block-start: var(--b-space-2);
212
+ inset-inline-start: var(--b-space-2);
213
+ }
214
+ .b-poster__meta { display: flex; flex-direction: column; gap: 0.125rem; min-inline-size: 0; }
215
+ .b-poster__title {
216
+ display: -webkit-box;
217
+ -webkit-box-orient: vertical;
218
+ -webkit-line-clamp: 2;
219
+ overflow: hidden;
220
+ margin: 0;
221
+ font-size: var(--b-text-subheadline);
222
+ font-weight: var(--b-weight-medium);
223
+ line-height: var(--b-leading-tight);
224
+ }
225
+ .b-poster__facts {
226
+ display: flex;
227
+ flex-wrap: wrap;
228
+ gap: var(--b-space-2);
229
+ margin: 0;
230
+ font-size: var(--b-text-caption);
231
+ color: var(--b-text-secondary);
232
+ }
233
+ .b-poster--wide { --b-poster-ratio: 16 / 9; }
234
+ @media (hover: hover) {
235
+ .b-poster:hover .b-poster__frame { translate: 0 -2px; box-shadow: var(--b-elevation-3); }
236
+ }
237
+ .b-poster:focus-visible { outline: none; }
238
+ .b-poster:focus-visible .b-poster__frame,
239
+ .b-poster.is-selected .b-poster__frame { outline: 2px solid var(--b-color-accent); outline-offset: 2px; }
240
+
241
+ /* A wall of posters: as many across as fit — three on a phone, eight on a
242
+ wide screen — with the poster's minimum width as the one knob. */
243
+ .b-poster-grid {
244
+ display: grid;
245
+ grid-template-columns: repeat(auto-fill, minmax(var(--b-poster-min, 6.5rem), 1fr));
246
+ gap: var(--b-space-4) var(--b-space-3);
247
+ }
248
+
102
249
  /* ---- Video Player frame ------------------------------------------------------ */
103
250
  .b-video {
104
251
  position: relative;
package/css/liquid.css CHANGED
@@ -41,7 +41,7 @@
41
41
 
42
42
  /* ---- Chrome: bars, sidebars, rails, status ------------------------------- */
43
43
  [data-glass="liquid"] :is(.b-topnav, .b-bottomnav, .b-mobile-header,
44
- .b-mobile-toolbar, .b-statusbar) {
44
+ .b-mobile-toolbar, .b-statusbar, .b-marketing-nav) {
45
45
  background: light-dark(rgba(250, 251, 254, 0.45), rgba(20, 20, 26, 0.45));
46
46
  -webkit-backdrop-filter: var(--b-glass-heavy);
47
47
  backdrop-filter: var(--b-glass-heavy);
@@ -198,6 +198,17 @@
198
198
  }
199
199
 
200
200
  /* ---- Feedback ------------------------------------------------------------------ */
201
+ [data-glass="liquid"] .b-spinner {
202
+ border-color: var(--b-lg-border);
203
+ border-top-color: var(--b-color-accent);
204
+ box-shadow: var(--b-glass-edge);
205
+ }
206
+ [data-glass="liquid"] .b-btn.is-loading::after { border-color: var(--b-lg-border); border-top-color: currentColor; }
207
+ [data-glass="liquid"] .b-btn--primary.is-loading::after { border-color: rgba(255, 255, 255, 0.35); border-top-color: #fff; }
208
+
209
+ /* ---- Media ------------------------------------------------------------------------- */
210
+ [data-glass="liquid"] .b-poster__frame { box-shadow: var(--b-glass-edge); }
211
+ [data-glass="liquid"] .b-billboard__actions .b-badge { background: var(--b-lg-pane); box-shadow: var(--b-glass-edge); }
201
212
  [data-glass="liquid"] .b-alert {
202
213
  -webkit-backdrop-filter: var(--b-glass-light);
203
214
  backdrop-filter: var(--b-glass-light);
package/css/utilities.css CHANGED
@@ -171,6 +171,12 @@
171
171
  otherwise compress its children to fit and nothing would ever scroll. */
172
172
  .b-scroll-area > * { flex-shrink: 0; }
173
173
  .b-scroll-area--x { overflow: auto hidden; }
174
+ /* A row inside a sideways scroll area is meant to overflow: it keeps its
175
+ content's width instead of squeezing every item to fit. */
176
+ .b-scroll-area--x > .b-hstack { width: max-content; min-width: 100%; }
177
+ /* …and is scrolled by thumb or wheel, so it carries no scrollbar of its own. */
178
+ .b-scroll-area--x:has(> .b-hstack) { scrollbar-width: none; }
179
+ .b-scroll-area--x:has(> .b-hstack)::-webkit-scrollbar { display: none; }
174
180
  .b-scroll-area--y { overflow: hidden auto; }
175
181
  .b-scroll-area--fade {
176
182
  mask-image: linear-gradient(to bottom, transparent, black var(--b-space-4),
package/dist/index.cjs CHANGED
@@ -43,6 +43,13 @@ __export(index_exports, {
43
43
  Bars: () => Bars,
44
44
  BaruaProvider: () => BaruaProvider,
45
45
  Bento: () => Bento,
46
+ Billboard: () => Billboard,
47
+ BillboardActions: () => BillboardActions,
48
+ BillboardArt: () => BillboardArt,
49
+ BillboardBody: () => BillboardBody,
50
+ BillboardLede: () => BillboardLede,
51
+ BillboardScrim: () => BillboardScrim,
52
+ BillboardTitle: () => BillboardTitle,
46
53
  BottomNav: () => BottomNav,
47
54
  BottomNavItem: () => BottomNavItem,
48
55
  BottomSheet: () => BottomSheet,
@@ -203,6 +210,13 @@ __export(index_exports, {
203
210
  PaginationItem: () => PaginationItem,
204
211
  PillNav: () => PillNav,
205
212
  Popover: () => Popover,
213
+ Poster: () => Poster,
214
+ PosterFacts: () => PosterFacts,
215
+ PosterFrame: () => PosterFrame,
216
+ PosterGrid: () => PosterGrid,
217
+ PosterInitial: () => PosterInitial,
218
+ PosterMeta: () => PosterMeta,
219
+ PosterTitle: () => PosterTitle,
206
220
  Progress: () => Progress,
207
221
  PromoBand: () => PromoBand,
208
222
  Quote: () => Quote,
@@ -1267,6 +1281,7 @@ var iconNames = [
1267
1281
  "doc",
1268
1282
  "download",
1269
1283
  "drop",
1284
+ "film",
1270
1285
  "filter",
1271
1286
  "flame",
1272
1287
  "folder",
@@ -1306,6 +1321,7 @@ var iconNames = [
1306
1321
  "star",
1307
1322
  "sun",
1308
1323
  "trash",
1324
+ "tv",
1309
1325
  "warning",
1310
1326
  "waveform",
1311
1327
  "wifi"
@@ -1346,6 +1362,10 @@ var GLYPHS = {
1346
1362
  ] }),
1347
1363
  "download": /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M10 3.5v9M6.5 9.5l3.5 3 3.5-3M4 16.5h12", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }),
1348
1364
  "drop": /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M10 2.8C7.7 6 5.5 8.6 5.5 11.4a4.5 4.5 0 0 0 9 0c0-2.8-2.2-5.4-4.5-8.6Z", stroke: "currentColor", strokeWidth: "1.5", strokeLinejoin: "round" }) }),
1365
+ "film": /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
1366
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M3.5 8.5h13V15a1.5 1.5 0 0 1-1.5 1.5H5A1.5 1.5 0 0 1 3.5 15V8.5Z", stroke: "currentColor", strokeWidth: "1.5", strokeLinejoin: "round" }),
1367
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "m3.5 8.5 1-3.4 11.6 1.7-.6 1.7M7.6 5.6 6.6 8.2M11.2 6.1l-1 2.4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
1368
+ ] }),
1349
1369
  "filter": /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M3.5 5.5h13M6 10h8M8.5 14.5h3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) }),
1350
1370
  "flame": /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M10 3c-2.5 3-4.5 5.2-4.5 7.4a4.5 4.5 0 0 0 9 0C14.5 8.2 12.5 6 10 3Z", stroke: "currentColor", strokeWidth: "1.5", strokeLinejoin: "round" }) }),
1351
1371
  "folder": /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M3.5 5.5A1.5 1.5 0 0 1 5 4h3l1.5 2H15a1.5 1.5 0 0 1 1.5 1.5V14a1.5 1.5 0 0 1-1.5 1.5H5A1.5 1.5 0 0 1 3.5 14V5.5Z", stroke: "currentColor", strokeWidth: "1.5", strokeLinejoin: "round" }) }),
@@ -1457,6 +1477,10 @@ var GLYPHS = {
1457
1477
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M10 1.5v2m0 13v2M18.5 10h-2m-13 0h-2m14.5-6-1.4 1.4M4.9 15.1 3.5 16.5m0-13 1.4 1.4m10.2 10.2 1.4 1.4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
1458
1478
  ] }),
1459
1479
  "trash": /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M4 6h12M8 6V4.5h4V6M6.5 6l.5 10h6l.5-10M8.5 9v4M11.5 9v4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }),
1480
+ "tv": /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
1481
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("rect", { x: "3", y: "6", width: "14", height: "9.5", rx: "1.8", stroke: "currentColor", strokeWidth: "1.5" }),
1482
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M7 17.5h6M7.5 2.5 10 5l2.5-2.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
1483
+ ] }),
1460
1484
  "warning": /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
1461
1485
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M10 3.5 18 17H2L10 3.5Z", stroke: "currentColor", strokeWidth: "1.5", strokeLinejoin: "round" }),
1462
1486
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M10 8.5V12M10 14.5h.01", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
@@ -2495,6 +2519,20 @@ var CommandCenterTile = block("div", "b-cc__tile", "CommandCenterTile");
2495
2519
  var CommandCenterLabel = block("div", "b-cc__label", "CommandCenterLabel");
2496
2520
  var CommandCenterStatus = block("div", "b-cc__status", "CommandCenterStatus");
2497
2521
  var ImageLens = block("div", "b-lens", "ImageLens");
2522
+ var Billboard = block("section", "b-billboard", "Billboard");
2523
+ var BillboardArt = block("img", "b-billboard__art", "BillboardArt");
2524
+ var BillboardScrim = block("div", "b-billboard__scrim", "BillboardScrim");
2525
+ var BillboardBody = block("div", "b-billboard__body", "BillboardBody");
2526
+ var BillboardTitle = block("h1", "b-billboard__title", "BillboardTitle");
2527
+ var BillboardLede = block("p", "b-billboard__lede", "BillboardLede");
2528
+ var BillboardActions = block("div", "b-billboard__actions", "BillboardActions");
2529
+ var Poster = block("a", "b-poster", "Poster");
2530
+ var PosterFrame = block("div", "b-poster__frame", "PosterFrame");
2531
+ var PosterInitial = block("span", "b-poster__initial", "PosterInitial");
2532
+ var PosterMeta = block("div", "b-poster__meta", "PosterMeta");
2533
+ var PosterTitle = block("p", "b-poster__title", "PosterTitle");
2534
+ var PosterFacts = block("p", "b-poster__facts", "PosterFacts");
2535
+ var PosterGrid = block("div", "b-poster-grid", "PosterGrid");
2498
2536
 
2499
2537
  // src/motion.tsx
2500
2538
  var import_react21 = require("react");
@@ -2603,6 +2641,13 @@ var ContextMenuTarget = (0, import_react21.forwardRef)(
2603
2641
  Bars,
2604
2642
  BaruaProvider,
2605
2643
  Bento,
2644
+ Billboard,
2645
+ BillboardActions,
2646
+ BillboardArt,
2647
+ BillboardBody,
2648
+ BillboardLede,
2649
+ BillboardScrim,
2650
+ BillboardTitle,
2606
2651
  BottomNav,
2607
2652
  BottomNavItem,
2608
2653
  BottomSheet,
@@ -2763,6 +2808,13 @@ var ContextMenuTarget = (0, import_react21.forwardRef)(
2763
2808
  PaginationItem,
2764
2809
  PillNav,
2765
2810
  Popover,
2811
+ Poster,
2812
+ PosterFacts,
2813
+ PosterFrame,
2814
+ PosterGrid,
2815
+ PosterInitial,
2816
+ PosterMeta,
2817
+ PosterTitle,
2766
2818
  Progress,
2767
2819
  PromoBand,
2768
2820
  Quote,