barua-ui 0.2.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.
@@ -0,0 +1,511 @@
1
+ /* ==========================================================================
2
+ Barua UI — Forms
3
+ Field (text/textarea/search/password/number/url/email/date/time), Select,
4
+ Combobox/Autocomplete, Checkbox, Radio, Switch, Slider, Stepper Input,
5
+ File Upload, Color Picker, Form scaffolding & validation.
6
+ ========================================================================== */
7
+
8
+ @layer components {
9
+ /* ---- Field shell -------------------------------------------------------
10
+ <div class="b-field"> <label class="b-label"> <input class="b-input">
11
+ <p class="b-help"> | <p class="b-error"> </div>
12
+ ------------------------------------------------------------------------- */
13
+ .b-field { display: flex; flex-direction: column; gap: var(--b-space-1); }
14
+
15
+ .b-label {
16
+ font-size: var(--b-text-footnote);
17
+ font-weight: var(--b-weight-semibold);
18
+ color: var(--b-text);
19
+ }
20
+ .b-label .b-optional {
21
+ font-weight: var(--b-weight-regular);
22
+ color: var(--b-text-tertiary);
23
+ }
24
+ .b-label--required::after {
25
+ content: " *";
26
+ color: var(--b-color-danger);
27
+ }
28
+
29
+ .b-help {
30
+ font-size: var(--b-text-footnote);
31
+ color: var(--b-text-secondary);
32
+ }
33
+ .b-error {
34
+ display: flex;
35
+ align-items: center;
36
+ gap: var(--b-space-1);
37
+ font-size: var(--b-text-footnote);
38
+ color: var(--b-color-danger);
39
+ }
40
+
41
+ /* ---- Inputs ------------------------------------------------------------ */
42
+ .b-input, .b-textarea, .b-select {
43
+ width: 100%;
44
+ height: var(--b-control-h-md);
45
+ padding-inline: var(--b-space-3);
46
+ font-size: var(--b-text-subheadline);
47
+ color: var(--b-text);
48
+ background: var(--b-surface);
49
+ border: 1px solid var(--b-border);
50
+ border-radius: var(--b-radius-md);
51
+ transition: border-color var(--b-duration-fast) var(--b-ease-standard),
52
+ box-shadow var(--b-duration-fast) var(--b-ease-standard),
53
+ background var(--b-duration-fast) var(--b-ease-standard);
54
+ }
55
+ .b-input::placeholder, .b-textarea::placeholder { color: var(--b-text-tertiary); }
56
+ .b-input:hover, .b-textarea:hover, .b-select:hover { border-color: var(--b-border-strong); }
57
+ .b-input:focus-visible, .b-textarea:focus-visible, .b-select:focus-visible {
58
+ border-color: var(--b-color-accent);
59
+ box-shadow: var(--b-focus-ring);
60
+ outline: none;
61
+ }
62
+ .b-input--filled { background: var(--b-fill-tertiary); border-color: transparent; }
63
+ .b-input--filled:hover { background: var(--b-fill-secondary); }
64
+ .b-input--sm { height: var(--b-control-h-sm); font-size: var(--b-text-footnote); border-radius: var(--b-radius-sm); }
65
+ .b-input--lg { height: var(--b-control-h-lg); font-size: var(--b-text-callout); border-radius: var(--b-radius-lg); }
66
+
67
+ .b-textarea {
68
+ height: auto;
69
+ min-height: 5.5rem;
70
+ padding-block: var(--b-space-2);
71
+ line-height: var(--b-leading-body);
72
+ resize: vertical;
73
+ }
74
+
75
+ /* Validation states */
76
+ .b-field.is-invalid .b-input,
77
+ .b-field.is-invalid .b-textarea,
78
+ .b-field.is-invalid .b-select,
79
+ .b-input.is-invalid, .b-input:user-invalid {
80
+ border-color: var(--b-color-danger);
81
+ }
82
+ .b-field.is-invalid .b-input:focus-visible,
83
+ .b-input.is-invalid:focus-visible, .b-input:user-invalid:focus-visible {
84
+ box-shadow: 0 0 0 3.5px color-mix(in srgb, var(--b-color-danger) 25%, transparent);
85
+ }
86
+ .b-field.is-valid .b-input, .b-input.is-valid { border-color: var(--b-color-success); }
87
+
88
+ /* ---- Input group (affixes: icons, ⌘K, units, clear) -------------------- */
89
+ .b-input-group {
90
+ position: relative;
91
+ display: flex;
92
+ align-items: center;
93
+ }
94
+ .b-input-group > .b-input { flex: 1; }
95
+ .b-input-group .b-input-affix {
96
+ position: absolute;
97
+ display: inline-flex;
98
+ align-items: center;
99
+ gap: var(--b-space-1);
100
+ color: var(--b-text-tertiary);
101
+ pointer-events: none;
102
+ }
103
+ .b-input-affix svg { width: 1rem; height: 1rem; }
104
+ .b-input-affix--start { inset-inline-start: var(--b-space-3); }
105
+ .b-input-affix--end { inset-inline-end: var(--b-space-3); }
106
+ .b-input-affix--end :is(button, .b-btn) { pointer-events: auto; }
107
+ .b-input-group:has(.b-input-affix--start) > .b-input { padding-inline-start: var(--b-space-8); }
108
+ .b-input-group:has(.b-input-affix--end) > .b-input { padding-inline-end: var(--b-space-8); }
109
+
110
+ /* Search field — pill + icon */
111
+ .b-search .b-input { border-radius: var(--b-radius-full); background: var(--b-fill-tertiary); border-color: transparent; }
112
+ .b-search .b-input:focus-visible { background: var(--b-surface); border-color: var(--b-color-accent); }
113
+ .b-search .b-input::-webkit-search-cancel-button { -webkit-appearance: none; }
114
+
115
+ /* Native pickers */
116
+ .b-input::-webkit-calendar-picker-indicator {
117
+ opacity: 0.55;
118
+ cursor: pointer;
119
+ }
120
+ .b-input[type="date"], .b-input[type="time"], .b-input[type="datetime-local"] {
121
+ font-variant-numeric: tabular-nums;
122
+ }
123
+
124
+ /* ---- Select ------------------------------------------------------------ */
125
+ .b-select {
126
+ appearance: none;
127
+ padding-inline-end: var(--b-space-8);
128
+ background-image:
129
+ linear-gradient(45deg, transparent 50%, var(--b-text-secondary) 50%),
130
+ linear-gradient(135deg, var(--b-text-secondary) 50%, transparent 50%);
131
+ background-position:
132
+ calc(100% - 1.05rem) 50%,
133
+ calc(100% - 0.75rem) 50%;
134
+ background-size: 0.3rem 0.3rem;
135
+ background-repeat: no-repeat;
136
+ cursor: pointer;
137
+ }
138
+
139
+ /* ---- Combobox / Autocomplete ------------------------------------------- */
140
+ .b-combobox { position: relative; }
141
+ .b-combobox__list {
142
+ position: absolute;
143
+ inset-inline: 0;
144
+ top: calc(100% + var(--b-space-1));
145
+ z-index: var(--b-z-popover);
146
+ max-height: 16rem;
147
+ overflow: auto;
148
+ padding: var(--b-space-1);
149
+ margin: 0;
150
+ list-style: none;
151
+ background: var(--b-elevated);
152
+ border: 1px solid var(--b-hairline);
153
+ border-radius: var(--b-radius-lg);
154
+ box-shadow: var(--b-elevation-4);
155
+ }
156
+ .b-combobox__option {
157
+ display: flex;
158
+ align-items: center;
159
+ gap: var(--b-space-2);
160
+ padding: var(--b-space-2) var(--b-space-3);
161
+ font-size: var(--b-text-subheadline);
162
+ border-radius: var(--b-radius-sm);
163
+ cursor: pointer;
164
+ }
165
+ .b-combobox__option:hover { background: var(--b-fill-quaternary); }
166
+ .b-combobox__option.is-active { background: var(--b-fill-tertiary); }
167
+ .b-combobox__option[aria-selected="true"] {
168
+ color: var(--b-color-accent-text);
169
+ background: var(--b-color-accent-soft);
170
+ font-weight: var(--b-weight-medium);
171
+ }
172
+ .b-combobox__empty {
173
+ padding: var(--b-space-4);
174
+ text-align: center;
175
+ color: var(--b-text-tertiary);
176
+ font-size: var(--b-text-footnote);
177
+ }
178
+
179
+ /* ---- Checkbox ---------------------------------------------------------- */
180
+ .b-checkbox, .b-radio {
181
+ display: inline-flex;
182
+ align-items: flex-start;
183
+ gap: var(--b-space-2);
184
+ cursor: pointer;
185
+ font-size: var(--b-text-subheadline);
186
+ user-select: none;
187
+ }
188
+ .b-checkbox input, .b-radio input {
189
+ appearance: none;
190
+ flex: none;
191
+ width: 1.25rem; height: 1.25rem;
192
+ margin: 0.1rem 0 0;
193
+ background: var(--b-surface);
194
+ border: 1.5px solid var(--b-border-strong);
195
+ border-radius: var(--b-radius-sm);
196
+ cursor: pointer;
197
+ transition: background var(--b-duration-fast) var(--b-ease-standard),
198
+ border-color var(--b-duration-fast) var(--b-ease-standard);
199
+ }
200
+ .b-checkbox input:checked, .b-checkbox input:indeterminate {
201
+ background: var(--b-color-accent);
202
+ border-color: var(--b-color-accent);
203
+ }
204
+ .b-checkbox input:checked {
205
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 6.2 5 8.7l4.5-5.4' fill='none' stroke='white' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
206
+ background-size: 0.8rem;
207
+ background-position: center;
208
+ background-repeat: no-repeat;
209
+ }
210
+ .b-checkbox input:indeterminate {
211
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.8 6h6.4' fill='none' stroke='white' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
212
+ background-size: 0.8rem;
213
+ background-position: center;
214
+ background-repeat: no-repeat;
215
+ }
216
+
217
+ /* ---- Radio ------------------------------------------------------------- */
218
+ .b-radio input { border-radius: 50%; }
219
+ .b-radio input:checked {
220
+ border-width: 0.4rem;
221
+ border-color: var(--b-color-accent);
222
+ background: var(--b-surface);
223
+ }
224
+
225
+ /* ---- Toggle Switch ----------------------------------------------------- */
226
+ .b-switch {
227
+ display: inline-flex;
228
+ align-items: center;
229
+ gap: var(--b-space-2);
230
+ cursor: pointer;
231
+ font-size: var(--b-text-subheadline);
232
+ user-select: none;
233
+ }
234
+ .b-switch input {
235
+ appearance: none;
236
+ width: 2.6rem; height: 1.55rem;
237
+ margin: 0;
238
+ flex: none;
239
+ background: var(--b-fill);
240
+ border-radius: var(--b-radius-full);
241
+ position: relative;
242
+ cursor: pointer;
243
+ transition: background var(--b-duration-normal) var(--b-ease-standard);
244
+ }
245
+ .b-switch input::after {
246
+ content: "";
247
+ position: absolute;
248
+ inset-block-start: 50%;
249
+ inset-inline-start: 2px;
250
+ translate: 0 -50%;
251
+ width: 1.3rem; height: 1.3rem;
252
+ background: #fff;
253
+ border-radius: 50%;
254
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), 0 0 0 0.5px rgba(0, 0, 0, 0.06);
255
+ transition: inset-inline-start var(--b-duration-normal) var(--b-ease-spring);
256
+ }
257
+ .b-switch input:checked { background: var(--b-color-accent); }
258
+ .b-switch input:checked::after { inset-inline-start: calc(100% - 1.3rem - 2px); }
259
+ .b-switch--sm input { width: 2.1rem; height: 1.25rem; }
260
+ .b-switch--sm input::after { width: 1.05rem; height: 1.05rem; }
261
+ .b-switch--sm input:checked::after { inset-inline-start: calc(100% - 1.05rem - 2px); }
262
+
263
+ /* ---- Slider / Range Slider --------------------------------------------- */
264
+ .b-slider {
265
+ appearance: none;
266
+ width: 100%;
267
+ height: 1.25rem;
268
+ background: none;
269
+ cursor: pointer;
270
+ --b-slider-fill: 50%;
271
+ }
272
+ .b-slider::-webkit-slider-runnable-track {
273
+ height: 4px;
274
+ border-radius: var(--b-radius-full);
275
+ background: linear-gradient(to right,
276
+ var(--b-color-accent) var(--b-slider-fill),
277
+ var(--b-fill) var(--b-slider-fill));
278
+ }
279
+ .b-slider::-moz-range-track {
280
+ height: 4px;
281
+ border-radius: var(--b-radius-full);
282
+ background: var(--b-fill);
283
+ }
284
+ .b-slider::-moz-range-progress {
285
+ height: 4px;
286
+ border-radius: var(--b-radius-full);
287
+ background: var(--b-color-accent);
288
+ }
289
+ .b-slider::-webkit-slider-thumb {
290
+ appearance: none;
291
+ width: 1.25rem; height: 1.25rem;
292
+ margin-top: -0.5rem;
293
+ background: #fff;
294
+ border-radius: 50%;
295
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3), 0 0 0 0.5px rgba(0, 0, 0, 0.08);
296
+ transition: scale var(--b-duration-fast) var(--b-ease-standard);
297
+ }
298
+ .b-slider::-moz-range-thumb {
299
+ width: 1.25rem; height: 1.25rem;
300
+ background: #fff;
301
+ border: none;
302
+ border-radius: 50%;
303
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3), 0 0 0 0.5px rgba(0, 0, 0, 0.08);
304
+ }
305
+ .b-slider:active::-webkit-slider-thumb { scale: 1.15; }
306
+
307
+ /* Range slider (two thumbs overlaid) */
308
+ .b-range {
309
+ position: relative;
310
+ height: 1.25rem;
311
+ }
312
+ .b-range::before {
313
+ content: "";
314
+ position: absolute;
315
+ inset-inline: 0;
316
+ top: 50%;
317
+ translate: 0 -50%;
318
+ height: 4px;
319
+ border-radius: var(--b-radius-full);
320
+ background: var(--b-fill);
321
+ }
322
+ .b-range__fill {
323
+ position: absolute;
324
+ top: 50%;
325
+ translate: 0 -50%;
326
+ height: 4px;
327
+ border-radius: var(--b-radius-full);
328
+ background: var(--b-color-accent);
329
+ }
330
+ .b-range > input[type="range"] {
331
+ appearance: none;
332
+ position: absolute;
333
+ inset: 0;
334
+ width: 100%;
335
+ background: none;
336
+ pointer-events: none;
337
+ margin: 0;
338
+ }
339
+ .b-range > input[type="range"]::-webkit-slider-thumb {
340
+ appearance: none;
341
+ pointer-events: auto;
342
+ width: 1.25rem; height: 1.25rem;
343
+ background: #fff;
344
+ border-radius: 50%;
345
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3), 0 0 0 0.5px rgba(0, 0, 0, 0.08);
346
+ }
347
+ .b-range > input[type="range"]::-moz-range-thumb {
348
+ pointer-events: auto;
349
+ width: 1.25rem; height: 1.25rem;
350
+ background: #fff;
351
+ border: none;
352
+ border-radius: 50%;
353
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
354
+ }
355
+
356
+ /* ---- Stepper Input ------------------------------------------------------ */
357
+ .b-stepper-input {
358
+ display: inline-flex;
359
+ align-items: stretch;
360
+ border: 1px solid var(--b-border);
361
+ border-radius: var(--b-radius-md);
362
+ background: var(--b-surface);
363
+ overflow: hidden;
364
+ }
365
+ .b-stepper-input input {
366
+ width: 3.5rem;
367
+ text-align: center;
368
+ border: none;
369
+ background: none;
370
+ font-variant-numeric: tabular-nums;
371
+ appearance: textfield;
372
+ }
373
+ .b-stepper-input input::-webkit-outer-spin-button,
374
+ .b-stepper-input input::-webkit-inner-spin-button { appearance: none; }
375
+ .b-stepper-input button {
376
+ width: var(--b-control-h-md);
377
+ border: none;
378
+ background: var(--b-fill-quaternary);
379
+ color: var(--b-text-secondary);
380
+ font-size: var(--b-text-callout);
381
+ cursor: pointer;
382
+ transition: background var(--b-duration-fast) var(--b-ease-standard);
383
+ }
384
+ .b-stepper-input button:hover { background: var(--b-fill-secondary); color: var(--b-text); }
385
+ .b-stepper-input button:first-child { border-inline-end: 1px solid var(--b-separator); }
386
+ .b-stepper-input button:last-child { border-inline-start: 1px solid var(--b-separator); }
387
+
388
+ /* ---- File Upload ------------------------------------------------------- */
389
+ .b-upload {
390
+ display: flex;
391
+ flex-direction: column;
392
+ align-items: center;
393
+ justify-content: center;
394
+ gap: var(--b-space-2);
395
+ padding: var(--b-space-8) var(--b-space-4);
396
+ text-align: center;
397
+ color: var(--b-text-secondary);
398
+ background: var(--b-fill-quaternary);
399
+ border: 1.5px dashed var(--b-border-strong);
400
+ border-radius: var(--b-radius-lg);
401
+ cursor: pointer;
402
+ transition: border-color var(--b-duration-fast) var(--b-ease-standard),
403
+ background var(--b-duration-fast) var(--b-ease-standard);
404
+ }
405
+ .b-upload:hover, .b-upload.is-dragover {
406
+ border-color: var(--b-color-accent);
407
+ background: var(--b-color-accent-soft);
408
+ color: var(--b-color-accent-text);
409
+ }
410
+ .b-upload input[type="file"] { display: none; }
411
+ .b-upload svg { width: 2rem; height: 2rem; opacity: 0.7; }
412
+ .b-upload__hint { font-size: var(--b-text-footnote); color: var(--b-text-tertiary); }
413
+
414
+ /* Upload preview row */
415
+ .b-upload-item {
416
+ display: flex;
417
+ align-items: center;
418
+ gap: var(--b-space-3);
419
+ padding: var(--b-space-2) var(--b-space-3);
420
+ background: var(--b-surface);
421
+ border: 1px solid var(--b-separator);
422
+ border-radius: var(--b-radius-md);
423
+ }
424
+ .b-upload-item__thumb {
425
+ width: 2.5rem; height: 2.5rem;
426
+ border-radius: var(--b-radius-sm);
427
+ object-fit: cover;
428
+ background: var(--b-fill-tertiary);
429
+ }
430
+ .b-upload-item__meta { flex: 1; min-width: 0; }
431
+ .b-upload-item__name { font-size: var(--b-text-footnote); font-weight: var(--b-weight-medium); }
432
+ .b-upload-item__size { font-size: var(--b-text-caption); color: var(--b-text-tertiary); }
433
+
434
+ /* ---- Color Picker ------------------------------------------------------- */
435
+ .b-color-picker {
436
+ display: inline-flex;
437
+ align-items: center;
438
+ gap: var(--b-space-2);
439
+ }
440
+ .b-color-picker input[type="color"] {
441
+ appearance: none;
442
+ width: var(--b-control-h-md);
443
+ height: var(--b-control-h-md);
444
+ padding: 0;
445
+ border: 1px solid var(--b-border);
446
+ border-radius: var(--b-radius-md);
447
+ background: none;
448
+ cursor: pointer;
449
+ }
450
+ .b-color-picker input[type="color"]::-webkit-color-swatch-wrapper { padding: 3px; }
451
+ .b-color-picker input[type="color"]::-webkit-color-swatch {
452
+ border: none;
453
+ border-radius: calc(var(--b-radius-md) - 3px);
454
+ }
455
+ .b-color-picker input[type="color"]::-moz-color-swatch {
456
+ border: none;
457
+ border-radius: calc(var(--b-radius-md) - 3px);
458
+ }
459
+ .b-swatches { display: flex; flex-wrap: wrap; gap: var(--b-space-2); }
460
+ .b-swatch {
461
+ width: 1.75rem; height: 1.75rem;
462
+ border-radius: var(--b-radius-full);
463
+ border: 1px solid var(--b-hairline);
464
+ cursor: pointer;
465
+ transition: scale var(--b-duration-fast) var(--b-ease-bounce);
466
+ }
467
+ .b-swatch:hover { scale: 1.12; }
468
+ .b-swatch.is-selected {
469
+ box-shadow: 0 0 0 2px var(--b-bg), 0 0 0 4px var(--b-color-accent);
470
+ }
471
+
472
+ /* ---- Form scaffolding --------------------------------------------------- */
473
+ .b-form { display: flex; flex-direction: column; gap: var(--b-space-5); }
474
+ .b-form-section {
475
+ display: flex;
476
+ flex-direction: column;
477
+ gap: var(--b-space-4);
478
+ padding: var(--b-space-5);
479
+ background: var(--b-surface);
480
+ border: 1px solid var(--b-separator);
481
+ border-radius: var(--b-radius-xl);
482
+ }
483
+ .b-form-section__header { margin-block-end: var(--b-space-1); }
484
+ .b-form-section__title { font-size: var(--b-text-headline); font-weight: var(--b-weight-semibold); }
485
+ .b-form-section__desc { font-size: var(--b-text-footnote); color: var(--b-text-secondary); }
486
+ .b-form-row {
487
+ display: grid;
488
+ grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr));
489
+ gap: var(--b-space-4);
490
+ }
491
+ .b-form-actions {
492
+ display: flex;
493
+ justify-content: flex-end;
494
+ gap: var(--b-space-2);
495
+ padding-block-start: var(--b-space-2);
496
+ }
497
+
498
+ /* Fieldset */
499
+ .b-fieldset {
500
+ border: none;
501
+ padding: 0;
502
+ display: flex;
503
+ flex-direction: column;
504
+ gap: var(--b-space-2);
505
+ }
506
+ .b-fieldset legend {
507
+ font-size: var(--b-text-footnote);
508
+ font-weight: var(--b-weight-semibold);
509
+ margin-block-end: var(--b-space-2);
510
+ }
511
+ }