barua-ui 0.3.4 → 0.4.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.
@@ -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/utilities.css CHANGED
@@ -171,6 +171,9 @@
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%; }
174
177
  .b-scroll-area--y { overflow: hidden auto; }
175
178
  .b-scroll-area--fade {
176
179
  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,
@@ -2495,6 +2509,20 @@ var CommandCenterTile = block("div", "b-cc__tile", "CommandCenterTile");
2495
2509
  var CommandCenterLabel = block("div", "b-cc__label", "CommandCenterLabel");
2496
2510
  var CommandCenterStatus = block("div", "b-cc__status", "CommandCenterStatus");
2497
2511
  var ImageLens = block("div", "b-lens", "ImageLens");
2512
+ var Billboard = block("section", "b-billboard", "Billboard");
2513
+ var BillboardArt = block("img", "b-billboard__art", "BillboardArt");
2514
+ var BillboardScrim = block("div", "b-billboard__scrim", "BillboardScrim");
2515
+ var BillboardBody = block("div", "b-billboard__body", "BillboardBody");
2516
+ var BillboardTitle = block("h1", "b-billboard__title", "BillboardTitle");
2517
+ var BillboardLede = block("p", "b-billboard__lede", "BillboardLede");
2518
+ var BillboardActions = block("div", "b-billboard__actions", "BillboardActions");
2519
+ var Poster = block("a", "b-poster", "Poster");
2520
+ var PosterFrame = block("div", "b-poster__frame", "PosterFrame");
2521
+ var PosterInitial = block("span", "b-poster__initial", "PosterInitial");
2522
+ var PosterMeta = block("div", "b-poster__meta", "PosterMeta");
2523
+ var PosterTitle = block("p", "b-poster__title", "PosterTitle");
2524
+ var PosterFacts = block("p", "b-poster__facts", "PosterFacts");
2525
+ var PosterGrid = block("div", "b-poster-grid", "PosterGrid");
2498
2526
 
2499
2527
  // src/motion.tsx
2500
2528
  var import_react21 = require("react");
@@ -2603,6 +2631,13 @@ var ContextMenuTarget = (0, import_react21.forwardRef)(
2603
2631
  Bars,
2604
2632
  BaruaProvider,
2605
2633
  Bento,
2634
+ Billboard,
2635
+ BillboardActions,
2636
+ BillboardArt,
2637
+ BillboardBody,
2638
+ BillboardLede,
2639
+ BillboardScrim,
2640
+ BillboardTitle,
2606
2641
  BottomNav,
2607
2642
  BottomNavItem,
2608
2643
  BottomSheet,
@@ -2763,6 +2798,13 @@ var ContextMenuTarget = (0, import_react21.forwardRef)(
2763
2798
  PaginationItem,
2764
2799
  PillNav,
2765
2800
  Popover,
2801
+ Poster,
2802
+ PosterFacts,
2803
+ PosterFrame,
2804
+ PosterGrid,
2805
+ PosterInitial,
2806
+ PosterMeta,
2807
+ PosterTitle,
2766
2808
  Progress,
2767
2809
  PromoBand,
2768
2810
  Quote,