barua-ui 0.5.0 → 0.7.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/css/base.css CHANGED
@@ -29,7 +29,10 @@
29
29
  min-height: 100dvh;
30
30
  }
31
31
 
32
- img, picture, video, canvas, svg { display: block; max-width: 100%; }
32
+ img, picture, video, canvas, svg, iframe { display: block; max-width: 100%; }
33
+ /* An iframe's inset border is legacy chrome, like a button's face. A mail
34
+ body or an embedded document should sit on the page, not in a box. */
35
+ iframe { border: 0; }
33
36
  input, button, textarea, select { font: inherit; color: inherit; letter-spacing: inherit; }
34
37
  p, h1, h2, h3, h4, h5, h6 { overflow-wrap: break-word; }
35
38
 
@@ -144,6 +144,13 @@
144
144
  box-shadow: var(--b-glass-edge);
145
145
  pointer-events: none;
146
146
  }
147
+ /* Thick material — the same glass, denser veil. For panels carrying data or
148
+ a form, where whatever the customer set as a wallpaper must not compete
149
+ with the ink. Translucency is decoration; a bounce rate is not. */
150
+ .b-card--glass.b-card--thick {
151
+ background: var(--b-material-thick-bg);
152
+ }
153
+
147
154
  /* Glass clear — transparent, for media-rich backgrounds */
148
155
  .b-card--glass-clear {
149
156
  position: relative;
@@ -225,7 +232,21 @@
225
232
  gap: var(--b-space-3);
226
233
  padding: var(--b-space-3) var(--b-space-4);
227
234
  font-size: var(--b-text-subheadline);
235
+ /* A row that does something is a <button>, and a <button> arrives wearing
236
+ the browser's own face: a grey plate, a border and centred text. Left
237
+ unstated, a whole list of actions renders as a column of grey slabs —
238
+ which is exactly what a mailbox did. Said once here, because every list
239
+ of actions would otherwise have to say it again. */
240
+ width: 100%;
241
+ text-align: start;
242
+ color: inherit;
243
+ background: none;
244
+ border: none;
228
245
  }
246
+ /* Three lines and a timestamp: the mark and the time belong beside the first
247
+ line, not floating in the middle of a tall row. */
248
+ .b-list-item--top { align-items: flex-start; }
249
+ .b-list-item--top .b-list-item__trailing { align-items: flex-end; flex-direction: column; gap: var(--b-space-1); }
229
250
  .b-list > .b-list-item + .b-list-item { border-top: 1px solid var(--b-separator); }
230
251
  .b-list--inset-divider > .b-list-item + .b-list-item {
231
252
  border-top: none;
@@ -678,6 +699,7 @@
678
699
  color: currentColor;
679
700
  }
680
701
  .b-icon svg { width: 100%; height: 100%; }
702
+ .b-icon--xs { width: 0.75rem; height: 0.75rem; }
681
703
  .b-icon--sm { width: 1rem; height: 1rem; }
682
704
  .b-icon--lg { width: 1.5rem; height: 1.5rem; }
683
705
  .b-icon--xl { width: 2rem; height: 2rem; }
@@ -692,6 +714,7 @@
692
714
  }
693
715
  /* iOS Settings-row size: small solid square, white glyph */
694
716
  .b-icon-tile--sm { width: 1.85rem; height: 1.85rem; border-radius: var(--b-radius-sm); }
717
+ .b-icon-tile svg { width: 1.25rem; height: 1.25rem; }
695
718
  .b-icon-tile--sm svg { width: 1.05rem; height: 1.05rem; }
696
719
  .b-icon-tile--solid { color: #fff; background: var(--b-color-accent); }
697
720
  .b-icon-tile--green { color: #fff; background: var(--b-color-green); }
@@ -701,7 +724,6 @@
701
724
  .b-icon-tile--teal { color: #fff; background: var(--b-color-teal); }
702
725
  .b-icon-tile--indigo { color: #fff; background: var(--b-color-indigo); }
703
726
  .b-icon-tile--gray { color: #fff; background: var(--b-gray-1); }
704
- .b-icon-tile svg { width: 1.25rem; height: 1.25rem; }
705
727
 
706
728
  /* ---- Image ------------------------------------------------------------------------------------ */
707
729
  .b-img { border-radius: var(--b-radius-lg); object-fit: cover; }
@@ -833,6 +855,14 @@
833
855
  backdrop-filter: blur(var(--b-blur-lg)) saturate(1.1);
834
856
  border-color: var(--b-material-neutral-edge);
835
857
  }
858
+ /* …but a table of numbers is not decoration. A card that asks for the thick
859
+ material keeps its blur and doubles the veil, so the picture still shows at
860
+ the edges without competing with the ink. The veil follows the wallpaper's
861
+ own scheme, so it lightens on a bright picture and darkens on a dark one. */
862
+ .b-has-wallpaper .b-card--thick {
863
+ background: var(--b-material-thick-bg);
864
+ }
865
+
836
866
  /* A panel inside glass is a fill, never a second material. */
837
867
  .b-has-wallpaper .b-card .b-card {
838
868
  background: var(--b-fill-quaternary);
@@ -35,6 +35,15 @@
35
35
  }
36
36
  .b-alert__close:hover { color: var(--b-text); }
37
37
 
38
+ /* No opinion. The default alert is info-tinted, which turns a plain
39
+ "still working on it" strip blue and gives it a meaning it does not
40
+ have. This is the same anatomy on the neutral surface. */
41
+ .b-alert--neutral {
42
+ background: var(--b-fill-quaternary);
43
+ border-color: var(--b-border);
44
+ }
45
+ .b-alert--neutral .b-alert__icon { color: var(--b-text-secondary); }
46
+
38
47
  .b-alert--success {
39
48
  background: var(--b-color-success-soft);
40
49
  border-color: color-mix(in srgb, var(--b-color-success) 30%, transparent);
@@ -82,6 +82,114 @@
82
82
  .b-hero__title { font-size: clamp(2.5rem, 7vw, 4.75rem); }
83
83
  .b-hero__media { margin-block-start: clamp(2.5rem, 5vw, 4rem); }
84
84
 
85
+ /* The tile field a hero stands on.
86
+
87
+ A flat page makes a centred headline look like it is floating in milk.
88
+ This is the quietest possible ground: three checkerboards at different
89
+ scales, each barely there, masked so the pattern dissolves before it
90
+ reaches the text. It is drawn entirely from gradients — no image, no
91
+ element per square — so it costs nothing and re-tints with the theme.
92
+ --b-tile is the cell; --b-tile-ink is how loud the squares are. */
93
+ /* The tile field is absolute, so whatever holds it has to be positioned and
94
+ has to clip. Saying it here means no page has to remember. */
95
+ .b-has-tiles { position: relative; overflow: hidden; }
96
+ .b-tile-field {
97
+ position: absolute;
98
+ inset: 0;
99
+ z-index: 0;
100
+ pointer-events: none;
101
+ --b-tile: 5.5rem;
102
+ /* The field paints its own ground, a shade off the page, and the squares
103
+ sit *lighter* on it — which is the only way the pattern is visible on a
104
+ white page and still barely there on a dark one. Two knobs, both
105
+ translucent, so whatever surface it lands on shows through. */
106
+ --b-tile-ground: light-dark(rgba(20, 24, 38, 0.045), rgba(255, 255, 255, 0.014));
107
+ --b-tile-ink: light-dark(rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.03));
108
+ background-color: var(--b-tile-ground);
109
+ background-image:
110
+ repeating-conic-gradient(var(--b-tile-ink) 0% 25%, transparent 0% 50%),
111
+ repeating-conic-gradient(var(--b-tile-ink) 0% 25%, transparent 0% 50%),
112
+ repeating-conic-gradient(var(--b-tile-ink) 0% 25%, transparent 0% 50%);
113
+ background-size:
114
+ var(--b-tile) var(--b-tile),
115
+ calc(var(--b-tile) * 1.62) calc(var(--b-tile) * 1.62),
116
+ calc(var(--b-tile) * 2.71) calc(var(--b-tile) * 2.71);
117
+ background-position: 0 0, calc(var(--b-tile) * 0.5) calc(var(--b-tile) * 0.8), calc(var(--b-tile) * -0.7) calc(var(--b-tile) * 0.3);
118
+ /* Nothing in the middle, where the words are. */
119
+ -webkit-mask-image: radial-gradient(120% 85% at 50% 0%, #000 0%, transparent 72%);
120
+ mask-image: radial-gradient(120% 85% at 50% 0%, #000 0%, transparent 72%);
121
+ }
122
+ /* Anything that has to sit on top of it says so once. */
123
+ .b-tile-field ~ * { position: relative; z-index: 1; }
124
+
125
+ /* ---- Announcement: one line of news above a headline --------------------- */
126
+ /* The pill every product page opens with — a release, a launch, a price
127
+ change. It is a link, so it is an <a>; the arrow is a text mark, not an
128
+ icon, and it steps forward on hover the way a link should suggest travel. */
129
+ .b-announce {
130
+ display: inline-flex;
131
+ align-items: center;
132
+ gap: var(--b-space-2);
133
+ padding: var(--b-space-1) var(--b-space-3);
134
+ font-size: var(--b-text-footnote);
135
+ font-weight: var(--b-weight-medium);
136
+ color: var(--b-color-accent-text);
137
+ background: var(--b-color-accent-soft);
138
+ border: 1px solid color-mix(in srgb, var(--b-color-accent) 22%, transparent);
139
+ border-radius: var(--b-radius-full);
140
+ text-decoration: none;
141
+ }
142
+ .b-announce:hover { text-decoration: none; background: color-mix(in srgb, var(--b-color-accent) 18%, transparent); }
143
+ .b-announce .b-icon { width: 1rem; height: 1rem; }
144
+ .b-announce__go { transition: translate var(--b-duration-fast) var(--b-ease-out); }
145
+ .b-announce:hover .b-announce__go { translate: 2px 0; }
146
+
147
+ /* ---- Rating: borrowed credibility, stated plainly ------------------------ */
148
+ /* Five marks and who is vouching. The stars are the library's own star at
149
+ caption size; a star that was not earned carries .is-empty rather than
150
+ being left out, so the row is always five wide and reads as a score. */
151
+ .b-rating {
152
+ display: inline-flex;
153
+ align-items: center;
154
+ gap: var(--b-space-2);
155
+ font-size: var(--b-text-footnote);
156
+ color: var(--b-text-secondary);
157
+ }
158
+ .b-rating__stars { display: inline-flex; gap: 0.125rem; color: var(--b-color-yellow); }
159
+ .b-rating__stars .b-icon { width: 0.95rem; height: 0.95rem; fill: currentColor; }
160
+ .b-rating__stars .is-empty { color: var(--b-fill); }
161
+
162
+ /* ---- Logo wall: the companies already here ------------------------------- */
163
+ /* A quiet row, evenly spaced, every mark the same height whatever its
164
+ proportions — which is the only way a wall of logos looks deliberate
165
+ rather than pasted. Inline SVG on currentColor is the intended form: it
166
+ inherits the wall's ink and therefore survives the dark theme. Raster
167
+ logos get greyed instead, because a PNG cannot follow the text colour. */
168
+ .b-logo-wall {
169
+ display: flex;
170
+ flex-wrap: wrap;
171
+ align-items: center;
172
+ justify-content: center;
173
+ gap: clamp(var(--b-space-6), 5vw, var(--b-space-12));
174
+ padding-block: var(--b-space-8);
175
+ color: var(--b-text-secondary);
176
+ }
177
+ .b-logo-wall__logo {
178
+ display: inline-flex;
179
+ align-items: center;
180
+ gap: var(--b-space-2);
181
+ height: var(--b-logo-h, 1.5rem);
182
+ font-size: var(--b-text-title3);
183
+ font-weight: var(--b-weight-semibold);
184
+ letter-spacing: var(--b-tracking-tight);
185
+ white-space: nowrap;
186
+ opacity: 0.7;
187
+ transition: opacity var(--b-duration-fast);
188
+ }
189
+ .b-logo-wall__logo:hover { opacity: 1; }
190
+ .b-logo-wall__logo :is(svg, img) { height: 100%; width: auto; }
191
+ .b-logo-wall__logo img { filter: grayscale(1); }
192
+
85
193
  /* ---- Figures: a picture is furniture, so it has a shape ------------------ */
86
194
  .b-figure { margin: 0; }
87
195
  .b-figure__frame {
@@ -158,6 +158,23 @@
158
158
  .b-sheet[open] { translate: 100% 0; }
159
159
  }
160
160
  .b-sheet::backdrop { background: var(--b-scrim); }
161
+
162
+ /* The scrim, as a class rather than a pseudo-element.
163
+ `::backdrop` is drawn by the browser for a top-layer element — a native
164
+ <dialog> or a [popover] — and nothing else. An overlay that portals a
165
+ plain <div> instead, to keep a focus trap the top layer cannot give it,
166
+ has no backdrop to style, and every such component was repeating these
167
+ six declarations inline. Opacity is left to the caller, because only it
168
+ knows whether the overlay is arriving or leaving. */
169
+ .b-scrim {
170
+ position: fixed;
171
+ inset: 0;
172
+ z-index: var(--b-z-modal);
173
+ background: var(--b-scrim);
174
+ -webkit-backdrop-filter: blur(var(--b-blur-xs));
175
+ backdrop-filter: blur(var(--b-blur-xs));
176
+ transition: opacity var(--b-duration-normal) var(--b-ease-out);
177
+ }
161
178
  .b-sheet__header {
162
179
  display: flex;
163
180
  align-items: center;
package/css/utilities.css CHANGED
@@ -82,6 +82,15 @@
82
82
  .b-stack--stretch { align-items: stretch; }
83
83
  .b-stack--between { justify-content: space-between; }
84
84
  .b-stack--wrap { flex-wrap: wrap; }
85
+
86
+ /* Main-axis placement, which the modifiers above do not cover: they set
87
+ align-items, so on a row they decide the cross axis. Centring a row
88
+ horizontally is a different instruction and needs its own word. */
89
+ .b-justify-start { justify-content: flex-start; }
90
+ .b-justify-center { justify-content: center; }
91
+ .b-justify-end { justify-content: flex-end; }
92
+ .b-justify-between { justify-content: space-between; }
93
+ .b-justify-around { justify-content: space-around; }
85
94
  .b-gap-0 { --b-gap: 0; }
86
95
  .b-gap-1 { --b-gap: var(--b-space-1); }
87
96
  .b-gap-2 { --b-gap: var(--b-space-2); }
@@ -196,6 +205,17 @@
196
205
  border-radius: var(--b-radius-lg);
197
206
  }
198
207
  .b-panel--plain { background: none; border: none; border-radius: 0; }
208
+
209
+ /* The list side of a list-and-detail split.
210
+ Full width on a phone, where it is the whole screen and a fixed column
211
+ would leave a band of empty glass beside it; a measured column once
212
+ there is room to show two things at once. This has to be a media query:
213
+ clamp() cannot say "fill, then stop filling", because it cannot see
214
+ whether anything is sitting next to it. */
215
+ .b-list-pane { inline-size: 100%; flex: none; }
216
+ @media (min-width: 768px) {
217
+ .b-list-pane { inline-size: clamp(20rem, 4rem + 25vw, 28rem); }
218
+ }
199
219
  .b-resizable { resize: horizontal; overflow: auto; min-width: 12rem; max-width: 70%; }
200
220
  .b-resizable--vertical { resize: vertical; min-height: 6rem; max-height: 80vh; }
201
221
  .b-resize-handle {
@@ -656,4 +676,58 @@
656
676
  border-radius: var(--b-radius-xl);
657
677
  box-shadow: var(--b-glass-edge), var(--b-shadow-md);
658
678
  }
679
+
680
+ /* ---- Box behaviours ------------------------------------------------------
681
+ The handful of layout facts that Stack and Grid do not express, and that
682
+ every application reaches for eventually: a child that takes the room
683
+ left over, a child that refuses to shrink, a box allowed to be narrower
684
+ than its content, and the positioning contexts. Named plainly, because
685
+ each one says exactly what it does and nothing more. */
686
+ .b-flex-1 { flex: 1 1 0%; }
687
+ .b-shrink-0 { flex-shrink: 0; }
688
+ .b-grow-0 { flex-grow: 0; }
689
+
690
+ /* A flex or grid child will not go narrower than its content unless it is
691
+ told it may — which is why a long subject line pushes a mail row wider
692
+ instead of ellipsing. This is the permission. */
693
+ .b-min-w-0 { min-width: 0; }
694
+ .b-min-h-0 { min-height: 0; }
695
+
696
+ .b-w-full { inline-size: 100%; }
697
+ .b-h-full { block-size: 100%; }
698
+ .b-block { display: block; }
699
+ .b-inline-block { display: inline-block; }
700
+ .b-inline-flex { display: inline-flex; align-items: center; gap: var(--b-space-2); }
701
+
702
+ .b-relative { position: relative; }
703
+ .b-absolute { position: absolute; }
704
+ .b-sticky { position: sticky; }
705
+
706
+ .b-overflow-hidden { overflow: hidden; }
707
+ .b-overflow-auto { overflow: auto; }
708
+ .b-overflow-x-auto { overflow-x: auto; overflow-y: hidden; }
709
+
710
+ /* Figures, keys, record values: anything read character by character. */
711
+ .b-mono { font-family: var(--b-font-mono); font-size: 0.875em; }
712
+
713
+ /* Present to a screen reader, absent to the eye. */
714
+ .b-sr-only {
715
+ position: absolute;
716
+ inline-size: 1px;
717
+ block-size: 1px;
718
+ padding: 0;
719
+ margin: -1px;
720
+ overflow: hidden;
721
+ clip-path: inset(50%);
722
+ white-space: nowrap;
723
+ border: 0;
724
+ }
725
+
726
+ /* For a glyph standing in as a busy indicator. The spinner component is the
727
+ better answer; this is for the cases that already have an icon. */
728
+ .b-spin { animation: b-spin 0.8s linear infinite; }
729
+ @keyframes b-spin { to { transform: rotate(360deg); } }
730
+ @media (prefers-reduced-motion: reduce) {
731
+ .b-spin { animation-duration: 2.4s; }
732
+ }
659
733
  }