@usefillo/dom 0.12.0 → 0.12.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/dist/styles.css CHANGED
@@ -84,11 +84,12 @@
84
84
  /* ---------- Field chrome ---------- */
85
85
  .fillo-field { display: flex; flex-direction: column; gap: 0.45rem; }
86
86
  .fillo-label { font-weight: 550; font-size: 0.95rem; }
87
+ :where(.fillo-field--error) .fillo-label { color: var(--fillo-error); }
87
88
  /* Fillo marks the few optional fields rather than starring the many required
88
89
  ones — so a clean label reads as required by default. */
89
90
  .fillo-optional { color: var(--fillo-muted); font-weight: 400; font-size: 0.85em; }
90
91
  .fillo-description { color: var(--fillo-muted); font-size: 0.85rem; margin: 0; line-height: 1.5; }
91
- .fillo-error { color: var(--fillo-error); font-size: 0.85rem; margin: 0; }
92
+ .fillo-error { color: var(--fillo-error); font-size: 0.85rem; font-weight: 500; line-height: 1.4; margin: 0; }
92
93
  .fillo-submit-error { color: var(--fillo-error); font-size: 0.85rem; font-weight: 500; margin: 0; }
93
94
 
94
95
  /* ---------- Inputs ---------- */
@@ -111,6 +112,11 @@
111
112
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-primary) 15%, transparent);
112
113
  }
113
114
  :where(.fillo-field--error) .fillo-input { border-color: var(--fillo-error); }
115
+ :where(.fillo-field--error) .fillo-input:focus-visible {
116
+ border-color: var(--fillo-error);
117
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-error) 20%, transparent);
118
+ outline: none;
119
+ }
114
120
  .fillo-textarea { resize: vertical; min-height: 6rem; }
115
121
 
116
122
  /* Number field adornments: the wrapper draws the field's box (border/
@@ -134,6 +140,11 @@
134
140
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-primary) 15%, transparent);
135
141
  }
136
142
  :where(.fillo-field--error) .fillo-number { border-color: var(--fillo-error); }
143
+ :where(.fillo-field--error) .fillo-number:focus-within {
144
+ border-color: var(--fillo-error);
145
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-error) 20%, transparent);
146
+ outline: none;
147
+ }
137
148
  :where(.fillo-number) .fillo-input {
138
149
  flex: 1 1 auto;
139
150
  min-width: 0;
@@ -143,6 +154,7 @@
143
154
  padding: 0;
144
155
  }
145
156
  :where(.fillo-number) .fillo-input:focus-visible { box-shadow: none; }
157
+ :where(.fillo-field--error) :where(.fillo-number) .fillo-input:focus-visible { outline: none; }
146
158
  .fillo-number-prefix, .fillo-number-suffix { flex: 0 0 auto; color: var(--fillo-muted); }
147
159
 
148
160
  /* Phone field: country picker + national input */
@@ -242,6 +254,15 @@
242
254
  border-color: var(--fillo-primary);
243
255
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-primary) 14%, transparent);
244
256
  }
257
+ :where(.fillo-field--error) .fillo-option {
258
+ border-color: var(--fillo-error);
259
+ background: color-mix(in srgb, var(--fillo-error) 2%, var(--fillo-control-bg));
260
+ }
261
+ :where(.fillo-field--error) .fillo-option:focus-within {
262
+ border-color: var(--fillo-error);
263
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-error) 20%, transparent);
264
+ outline: none;
265
+ }
245
266
  .fillo-option--selected {
246
267
  border-color: var(--fillo-primary);
247
268
  background: color-mix(in srgb, var(--fillo-primary) 6%, var(--fillo-control-bg));
@@ -357,6 +378,13 @@
357
378
  inset 0 0 0 1px var(--fillo-primary),
358
379
  0 0 0 3px color-mix(in srgb, var(--fillo-primary) 15%, transparent);
359
380
  }
381
+ :where(.fillo-field--error) .fillo-toggle { border-color: var(--fillo-error); }
382
+ :where(.fillo-field--error) :where(.fillo-toggle-input:focus-visible) + .fillo-toggle-track {
383
+ box-shadow:
384
+ inset 0 0 0 1px var(--fillo-error),
385
+ 0 0 0 3px color-mix(in srgb, var(--fillo-error) 20%, transparent);
386
+ outline: none;
387
+ }
360
388
  .fillo-toggle:where(:has(.fillo-toggle-input:checked)) {
361
389
  border-color: var(--fillo-primary);
362
390
  background: color-mix(in srgb, var(--fillo-primary) 5%, var(--fillo-control-bg));
@@ -416,6 +444,11 @@
416
444
  border-color: var(--fillo-primary);
417
445
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-primary) 15%, transparent);
418
446
  }
447
+ :where(.fillo-field--error) .fillo-scale-step:focus-visible {
448
+ border-color: var(--fillo-error);
449
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-error) 20%, transparent);
450
+ outline: none;
451
+ }
419
452
  .fillo-scale-step--active {
420
453
  background: var(--fillo-primary);
421
454
  border-color: var(--fillo-primary);
@@ -480,6 +513,12 @@
480
513
  .fillo-matrix thead th { color: var(--fillo-muted); font-weight: 500; font-size: 0.8rem; }
481
514
  .fillo-matrix tbody th { text-align: start; font-weight: 500; }
482
515
  .fillo-matrix tbody tr:last-child th, .fillo-matrix tbody tr:last-child td { border-bottom: none; }
516
+ .fillo-matrix-cell:focus-within {
517
+ border-radius: var(--fillo-radius);
518
+ outline: 2px solid var(--fillo-primary);
519
+ outline-offset: 2px;
520
+ }
521
+ :where(.fillo-field--error) .fillo-matrix-cell:focus-within { outline-color: var(--fillo-error); }
483
522
 
484
523
  /* ---------- Calculated ---------- */
485
524
  /* A quiet computed-value line, not a control: no border or input chrome —
@@ -571,6 +610,15 @@
571
610
  border-color: var(--fillo-primary);
572
611
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-primary) 15%, transparent);
573
612
  }
613
+ :where(.fillo-field--error) .fillo-dropzone {
614
+ border-color: var(--fillo-error);
615
+ background: color-mix(in srgb, var(--fillo-error) 2%, var(--fillo-control-bg));
616
+ }
617
+ :where(.fillo-field--error) .fillo-dropzone:focus-visible {
618
+ border-color: var(--fillo-error);
619
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-error) 20%, transparent);
620
+ outline: none;
621
+ }
574
622
  .fillo-dropzone--disabled { cursor: not-allowed; opacity: 0.6; }
575
623
  .fillo-dropzone-title { font-weight: 550; font-size: 0.95rem; }
576
624
  .fillo-dropzone-hint { color: var(--fillo-muted); font-size: 0.82rem; }
@@ -578,20 +626,50 @@
578
626
  .fillo-files { list-style: none; display: flex; flex-direction: column; gap: 0.45rem; margin: 0; padding: 0; }
579
627
  .fillo-file {
580
628
  display: grid;
581
- grid-template-columns: minmax(0, 1fr) auto auto;
629
+ grid-template-columns: auto minmax(0, 1fr) auto;
582
630
  align-items: center;
583
- gap: 0.45rem 0.65rem;
631
+ gap: 0.45rem 0.625rem;
584
632
  border: 1px solid var(--fillo-border);
585
633
  border-radius: var(--fillo-radius);
586
634
  padding: 0.625rem 0.75rem;
587
635
  font-size: 0.88rem;
588
636
  background: var(--fillo-control-bg);
637
+ box-sizing: border-box;
638
+ min-width: 0;
589
639
  }
590
640
  .fillo-file--failed {
591
- grid-template-columns: minmax(0, 1fr) auto;
592
- border-color: var(--fillo-error);
641
+ border-color: color-mix(in srgb, var(--fillo-error) 32%, var(--fillo-border));
642
+ border-inline-start: 3px solid var(--fillo-error);
643
+ background: color-mix(in srgb, var(--fillo-error) 4%, var(--fillo-control-bg));
644
+ }
645
+ .fillo-file-state {
646
+ display: inline-flex;
647
+ align-items: center;
648
+ justify-content: center;
649
+ width: 1.5rem;
650
+ height: 1.5rem;
651
+ color: var(--fillo-muted);
652
+ }
653
+ .fillo-file-state--done { color: var(--fillo-primary); }
654
+ .fillo-file-state--failed { color: var(--fillo-error); }
655
+ .fillo-file-state-icon {
656
+ display: block;
657
+ width: 1.35rem;
658
+ height: 1.35rem;
659
+ stroke: currentColor;
660
+ stroke-width: 1.75;
661
+ stroke-linecap: round;
662
+ stroke-linejoin: round;
663
+ }
664
+ .fillo-file-content {
665
+ display: flex;
666
+ flex-direction: column;
667
+ gap: 0.1rem;
668
+ min-width: 0;
669
+ text-align: start;
593
670
  }
594
671
  .fillo-file-name {
672
+ display: block;
595
673
  min-width: 0;
596
674
  overflow: hidden;
597
675
  text-overflow: ellipsis;
@@ -609,14 +687,14 @@
609
687
  display: inline-flex;
610
688
  align-items: center;
611
689
  justify-content: flex-end;
612
- gap: 0.15rem;
690
+ gap: 0.25rem;
613
691
  white-space: nowrap;
614
692
  }
615
693
  .fillo-file-error {
616
- grid-column: 1 / -1;
617
694
  color: var(--fillo-error);
618
695
  font-size: 0.82rem;
619
696
  line-height: 1.35;
697
+ overflow-wrap: anywhere;
620
698
  }
621
699
  .fillo-file-remove {
622
700
  appearance: none;
@@ -627,11 +705,18 @@
627
705
  border: none;
628
706
  cursor: pointer;
629
707
  color: var(--fillo-muted);
630
- font-size: 1.1rem;
631
708
  line-height: 1;
632
709
  padding: 0;
633
710
  }
634
- .fillo-file-remove:hover { color: var(--fillo-error); }
711
+ .fillo-file-action-icon {
712
+ display: block;
713
+ width: 1rem;
714
+ height: 1rem;
715
+ stroke: currentColor;
716
+ stroke-width: 1.75;
717
+ stroke-linecap: round;
718
+ }
719
+ .fillo-file-remove:hover { color: var(--fillo-text); }
635
720
  .fillo-file-retry {
636
721
  appearance: none;
637
722
  display: inline-flex;
@@ -643,11 +728,11 @@
643
728
  color: var(--fillo-primary);
644
729
  font: inherit;
645
730
  font-weight: 550;
646
- padding: 0 0.3rem;
731
+ padding: 0 0.5rem;
647
732
  }
648
733
  .fillo-file-retry:hover { text-decoration: underline; }
649
734
  .fillo-progress {
650
- grid-column: 1 / -1;
735
+ grid-column: 2 / -1;
651
736
  height: 4px;
652
737
  border-radius: 999px;
653
738
  background: var(--fillo-border);
@@ -913,18 +998,6 @@
913
998
  line-height: 1.45;
914
999
  }
915
1000
 
916
- /* Error summary (GOV.UK pattern): ONE alert on failed submit; links focus
917
- their fields. Per-field messages are plain describedby text. */
918
- .fillo-error-summary {
919
- border: 2px solid var(--fillo-error);
920
- border-radius: var(--fillo-radius);
921
- padding: 0.8rem 1rem;
922
- }
923
- .fillo-error-summary-title { margin: 0 0 0.4rem; font-size: 1rem; font-weight: 600; }
924
- .fillo-error-summary ul { margin: 0; padding-inline-start: 1.1rem; }
925
- .fillo-error-summary li { margin: 0.2rem 0; }
926
- .fillo-error-summary a { color: var(--fillo-error); }
927
-
928
1001
  /* ---------- Accessibility: focus rings, pointer targets, forced-colors
929
1002
  (input-quality audit P1.1-P1.3) ---------- */
930
1003
  /* Focus visibility: controls without a compensating border swap get a
@@ -941,11 +1014,10 @@
941
1014
  outline-offset: 2px;
942
1015
  box-shadow: none;
943
1016
  }
1017
+ :where(.fillo-field--error) .fillo-star:focus-visible { outline-color: var(--fillo-error); }
944
1018
 
945
1019
  /* Minimum pointer targets (WCAG 2.2 AA 24px; 1.5rem = 24px @16px root). */
946
1020
  .fillo-ranking-move,
947
- .fillo-file-remove,
948
- .fillo-file-retry,
949
1021
  .fillo-signature-clear {
950
1022
  min-width: 1.5rem;
951
1023
  min-height: 1.5rem;
@@ -953,6 +1025,12 @@
953
1025
  align-items: center;
954
1026
  justify-content: center;
955
1027
  }
1028
+ /* Upload row actions use a calmer, easier 32px target. */
1029
+ .fillo-file-remove,
1030
+ .fillo-file-retry {
1031
+ min-width: 2rem;
1032
+ min-height: 2rem;
1033
+ }
956
1034
  .fillo-star { min-width: 1.75rem; min-height: 1.75rem; }
957
1035
  .fillo-matrix-cell {
958
1036
  display: flex;
@@ -974,6 +1052,7 @@
974
1052
  /* Matrix on narrow viewports: stacked rows, never a horizontal scroll
975
1053
  trap. Column names come from data-label (set by both renderers). */
976
1054
  @media (max-width: 30rem) {
1055
+ .fillo-file { gap: 0.4rem 0.5rem; padding: 0.55rem 0.625rem; }
977
1056
  .fillo-matrix thead { position: absolute; width: 1px; height: 1px;
978
1057
  overflow: hidden; clip-path: inset(50%); }
979
1058
  .fillo-matrix, .fillo-matrix tbody, .fillo-matrix tr,
@@ -991,6 +1070,12 @@
991
1070
 
992
1071
  /* Forced-colors: restore what author colors can't carry. */
993
1072
  @media (forced-colors: active) {
1073
+ .fillo-file--failed {
1074
+ border-color: CanvasText;
1075
+ border-inline-start-color: Highlight;
1076
+ background: Canvas;
1077
+ }
1078
+ .fillo-file-state--failed { color: Highlight; }
994
1079
  .fillo-star--active,
995
1080
  .fillo-scale-step--active,
996
1081
  :where(.fillo-option--selected) {
@@ -1001,7 +1086,11 @@
1001
1086
  .fillo-number:focus-within,
1002
1087
  .fillo-phone-flag:focus-visible,
1003
1088
  .fillo-phone-search:focus-visible,
1089
+ .fillo-option:focus-within,
1090
+ :where(.fillo-toggle-input:focus-visible) + .fillo-toggle-track,
1091
+ .fillo-star:focus-visible,
1004
1092
  .fillo-scale-step:focus-visible,
1093
+ .fillo-matrix-cell:focus-within,
1005
1094
  .fillo-dropzone:focus-visible,
1006
1095
  .fillo-select:focus-visible {
1007
1096
  outline: 2px solid Highlight;
@@ -84,11 +84,12 @@
84
84
  /* ---------- Field chrome ---------- */
85
85
  .fillo-field { display: flex; flex-direction: column; gap: 0.45rem; }
86
86
  .fillo-label { font-weight: 550; font-size: 0.95rem; }
87
+ :where(.fillo-field--error) .fillo-label { color: var(--fillo-error); }
87
88
  /* Fillo marks the few optional fields rather than starring the many required
88
89
  ones — so a clean label reads as required by default. */
89
90
  .fillo-optional { color: var(--fillo-muted); font-weight: 400; font-size: 0.85em; }
90
91
  .fillo-description { color: var(--fillo-muted); font-size: 0.85rem; margin: 0; line-height: 1.5; }
91
- .fillo-error { color: var(--fillo-error); font-size: 0.85rem; margin: 0; }
92
+ .fillo-error { color: var(--fillo-error); font-size: 0.85rem; font-weight: 500; line-height: 1.4; margin: 0; }
92
93
  .fillo-submit-error { color: var(--fillo-error); font-size: 0.85rem; font-weight: 500; margin: 0; }
93
94
 
94
95
  /* ---------- Inputs ---------- */
@@ -111,6 +112,11 @@
111
112
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-primary) 15%, transparent);
112
113
  }
113
114
  :where(.fillo-field--error) .fillo-input { border-color: var(--fillo-error); }
115
+ :where(.fillo-field--error) .fillo-input:focus-visible {
116
+ border-color: var(--fillo-error);
117
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-error) 20%, transparent);
118
+ outline: none;
119
+ }
114
120
  .fillo-textarea { resize: vertical; min-height: 6rem; }
115
121
 
116
122
  /* Number field adornments: the wrapper draws the field's box (border/
@@ -134,6 +140,11 @@
134
140
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-primary) 15%, transparent);
135
141
  }
136
142
  :where(.fillo-field--error) .fillo-number { border-color: var(--fillo-error); }
143
+ :where(.fillo-field--error) .fillo-number:focus-within {
144
+ border-color: var(--fillo-error);
145
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-error) 20%, transparent);
146
+ outline: none;
147
+ }
137
148
  :where(.fillo-number) .fillo-input {
138
149
  flex: 1 1 auto;
139
150
  min-width: 0;
@@ -143,6 +154,7 @@
143
154
  padding: 0;
144
155
  }
145
156
  :where(.fillo-number) .fillo-input:focus-visible { box-shadow: none; }
157
+ :where(.fillo-field--error) :where(.fillo-number) .fillo-input:focus-visible { outline: none; }
146
158
  .fillo-number-prefix, .fillo-number-suffix { flex: 0 0 auto; color: var(--fillo-muted); }
147
159
 
148
160
  /* Phone field: country picker + national input */
@@ -242,6 +254,15 @@
242
254
  border-color: var(--fillo-primary);
243
255
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-primary) 14%, transparent);
244
256
  }
257
+ :where(.fillo-field--error) .fillo-option {
258
+ border-color: var(--fillo-error);
259
+ background: color-mix(in srgb, var(--fillo-error) 2%, var(--fillo-control-bg));
260
+ }
261
+ :where(.fillo-field--error) .fillo-option:focus-within {
262
+ border-color: var(--fillo-error);
263
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-error) 20%, transparent);
264
+ outline: none;
265
+ }
245
266
  .fillo-option--selected {
246
267
  border-color: var(--fillo-primary);
247
268
  background: color-mix(in srgb, var(--fillo-primary) 6%, var(--fillo-control-bg));
@@ -357,6 +378,13 @@
357
378
  inset 0 0 0 1px var(--fillo-primary),
358
379
  0 0 0 3px color-mix(in srgb, var(--fillo-primary) 15%, transparent);
359
380
  }
381
+ :where(.fillo-field--error) .fillo-toggle { border-color: var(--fillo-error); }
382
+ :where(.fillo-field--error) :where(.fillo-toggle-input:focus-visible) + .fillo-toggle-track {
383
+ box-shadow:
384
+ inset 0 0 0 1px var(--fillo-error),
385
+ 0 0 0 3px color-mix(in srgb, var(--fillo-error) 20%, transparent);
386
+ outline: none;
387
+ }
360
388
  .fillo-toggle:where(:has(.fillo-toggle-input:checked)) {
361
389
  border-color: var(--fillo-primary);
362
390
  background: color-mix(in srgb, var(--fillo-primary) 5%, var(--fillo-control-bg));
@@ -416,6 +444,11 @@
416
444
  border-color: var(--fillo-primary);
417
445
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-primary) 15%, transparent);
418
446
  }
447
+ :where(.fillo-field--error) .fillo-scale-step:focus-visible {
448
+ border-color: var(--fillo-error);
449
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-error) 20%, transparent);
450
+ outline: none;
451
+ }
419
452
  .fillo-scale-step--active {
420
453
  background: var(--fillo-primary);
421
454
  border-color: var(--fillo-primary);
@@ -480,6 +513,12 @@
480
513
  .fillo-matrix thead th { color: var(--fillo-muted); font-weight: 500; font-size: 0.8rem; }
481
514
  .fillo-matrix tbody th { text-align: start; font-weight: 500; }
482
515
  .fillo-matrix tbody tr:last-child th, .fillo-matrix tbody tr:last-child td { border-bottom: none; }
516
+ .fillo-matrix-cell:focus-within {
517
+ border-radius: var(--fillo-radius);
518
+ outline: 2px solid var(--fillo-primary);
519
+ outline-offset: 2px;
520
+ }
521
+ :where(.fillo-field--error) .fillo-matrix-cell:focus-within { outline-color: var(--fillo-error); }
483
522
 
484
523
  /* ---------- Calculated ---------- */
485
524
  /* A quiet computed-value line, not a control: no border or input chrome —
@@ -571,6 +610,15 @@
571
610
  border-color: var(--fillo-primary);
572
611
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-primary) 15%, transparent);
573
612
  }
613
+ :where(.fillo-field--error) .fillo-dropzone {
614
+ border-color: var(--fillo-error);
615
+ background: color-mix(in srgb, var(--fillo-error) 2%, var(--fillo-control-bg));
616
+ }
617
+ :where(.fillo-field--error) .fillo-dropzone:focus-visible {
618
+ border-color: var(--fillo-error);
619
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-error) 20%, transparent);
620
+ outline: none;
621
+ }
574
622
  .fillo-dropzone--disabled { cursor: not-allowed; opacity: 0.6; }
575
623
  .fillo-dropzone-title { font-weight: 550; font-size: 0.95rem; }
576
624
  .fillo-dropzone-hint { color: var(--fillo-muted); font-size: 0.82rem; }
@@ -578,20 +626,50 @@
578
626
  .fillo-files { list-style: none; display: flex; flex-direction: column; gap: 0.45rem; margin: 0; padding: 0; }
579
627
  .fillo-file {
580
628
  display: grid;
581
- grid-template-columns: minmax(0, 1fr) auto auto;
629
+ grid-template-columns: auto minmax(0, 1fr) auto;
582
630
  align-items: center;
583
- gap: 0.45rem 0.65rem;
631
+ gap: 0.45rem 0.625rem;
584
632
  border: 1px solid var(--fillo-border);
585
633
  border-radius: var(--fillo-radius);
586
634
  padding: 0.625rem 0.75rem;
587
635
  font-size: 0.88rem;
588
636
  background: var(--fillo-control-bg);
637
+ box-sizing: border-box;
638
+ min-width: 0;
589
639
  }
590
640
  .fillo-file--failed {
591
- grid-template-columns: minmax(0, 1fr) auto;
592
- border-color: var(--fillo-error);
641
+ border-color: color-mix(in srgb, var(--fillo-error) 32%, var(--fillo-border));
642
+ border-inline-start: 3px solid var(--fillo-error);
643
+ background: color-mix(in srgb, var(--fillo-error) 4%, var(--fillo-control-bg));
644
+ }
645
+ .fillo-file-state {
646
+ display: inline-flex;
647
+ align-items: center;
648
+ justify-content: center;
649
+ width: 1.5rem;
650
+ height: 1.5rem;
651
+ color: var(--fillo-muted);
652
+ }
653
+ .fillo-file-state--done { color: var(--fillo-primary); }
654
+ .fillo-file-state--failed { color: var(--fillo-error); }
655
+ .fillo-file-state-icon {
656
+ display: block;
657
+ width: 1.35rem;
658
+ height: 1.35rem;
659
+ stroke: currentColor;
660
+ stroke-width: 1.75;
661
+ stroke-linecap: round;
662
+ stroke-linejoin: round;
663
+ }
664
+ .fillo-file-content {
665
+ display: flex;
666
+ flex-direction: column;
667
+ gap: 0.1rem;
668
+ min-width: 0;
669
+ text-align: start;
593
670
  }
594
671
  .fillo-file-name {
672
+ display: block;
595
673
  min-width: 0;
596
674
  overflow: hidden;
597
675
  text-overflow: ellipsis;
@@ -609,14 +687,14 @@
609
687
  display: inline-flex;
610
688
  align-items: center;
611
689
  justify-content: flex-end;
612
- gap: 0.15rem;
690
+ gap: 0.25rem;
613
691
  white-space: nowrap;
614
692
  }
615
693
  .fillo-file-error {
616
- grid-column: 1 / -1;
617
694
  color: var(--fillo-error);
618
695
  font-size: 0.82rem;
619
696
  line-height: 1.35;
697
+ overflow-wrap: anywhere;
620
698
  }
621
699
  .fillo-file-remove {
622
700
  appearance: none;
@@ -627,11 +705,18 @@
627
705
  border: none;
628
706
  cursor: pointer;
629
707
  color: var(--fillo-muted);
630
- font-size: 1.1rem;
631
708
  line-height: 1;
632
709
  padding: 0;
633
710
  }
634
- .fillo-file-remove:hover { color: var(--fillo-error); }
711
+ .fillo-file-action-icon {
712
+ display: block;
713
+ width: 1rem;
714
+ height: 1rem;
715
+ stroke: currentColor;
716
+ stroke-width: 1.75;
717
+ stroke-linecap: round;
718
+ }
719
+ .fillo-file-remove:hover { color: var(--fillo-text); }
635
720
  .fillo-file-retry {
636
721
  appearance: none;
637
722
  display: inline-flex;
@@ -643,11 +728,11 @@
643
728
  color: var(--fillo-primary);
644
729
  font: inherit;
645
730
  font-weight: 550;
646
- padding: 0 0.3rem;
731
+ padding: 0 0.5rem;
647
732
  }
648
733
  .fillo-file-retry:hover { text-decoration: underline; }
649
734
  .fillo-progress {
650
- grid-column: 1 / -1;
735
+ grid-column: 2 / -1;
651
736
  height: 4px;
652
737
  border-radius: 999px;
653
738
  background: var(--fillo-border);
@@ -913,18 +998,6 @@
913
998
  line-height: 1.45;
914
999
  }
915
1000
 
916
- /* Error summary (GOV.UK pattern): ONE alert on failed submit; links focus
917
- their fields. Per-field messages are plain describedby text. */
918
- .fillo-error-summary {
919
- border: 2px solid var(--fillo-error);
920
- border-radius: var(--fillo-radius);
921
- padding: 0.8rem 1rem;
922
- }
923
- .fillo-error-summary-title { margin: 0 0 0.4rem; font-size: 1rem; font-weight: 600; }
924
- .fillo-error-summary ul { margin: 0; padding-inline-start: 1.1rem; }
925
- .fillo-error-summary li { margin: 0.2rem 0; }
926
- .fillo-error-summary a { color: var(--fillo-error); }
927
-
928
1001
  /* ---------- Accessibility: focus rings, pointer targets, forced-colors
929
1002
  (input-quality audit P1.1-P1.3) ---------- */
930
1003
  /* Focus visibility: controls without a compensating border swap get a
@@ -941,11 +1014,10 @@
941
1014
  outline-offset: 2px;
942
1015
  box-shadow: none;
943
1016
  }
1017
+ :where(.fillo-field--error) .fillo-star:focus-visible { outline-color: var(--fillo-error); }
944
1018
 
945
1019
  /* Minimum pointer targets (WCAG 2.2 AA 24px; 1.5rem = 24px @16px root). */
946
1020
  .fillo-ranking-move,
947
- .fillo-file-remove,
948
- .fillo-file-retry,
949
1021
  .fillo-signature-clear {
950
1022
  min-width: 1.5rem;
951
1023
  min-height: 1.5rem;
@@ -953,6 +1025,12 @@
953
1025
  align-items: center;
954
1026
  justify-content: center;
955
1027
  }
1028
+ /* Upload row actions use a calmer, easier 32px target. */
1029
+ .fillo-file-remove,
1030
+ .fillo-file-retry {
1031
+ min-width: 2rem;
1032
+ min-height: 2rem;
1033
+ }
956
1034
  .fillo-star { min-width: 1.75rem; min-height: 1.75rem; }
957
1035
  .fillo-matrix-cell {
958
1036
  display: flex;
@@ -974,6 +1052,7 @@
974
1052
  /* Matrix on narrow viewports: stacked rows, never a horizontal scroll
975
1053
  trap. Column names come from data-label (set by both renderers). */
976
1054
  @media (max-width: 30rem) {
1055
+ .fillo-file { gap: 0.4rem 0.5rem; padding: 0.55rem 0.625rem; }
977
1056
  .fillo-matrix thead { position: absolute; width: 1px; height: 1px;
978
1057
  overflow: hidden; clip-path: inset(50%); }
979
1058
  .fillo-matrix, .fillo-matrix tbody, .fillo-matrix tr,
@@ -991,6 +1070,12 @@
991
1070
 
992
1071
  /* Forced-colors: restore what author colors can't carry. */
993
1072
  @media (forced-colors: active) {
1073
+ .fillo-file--failed {
1074
+ border-color: CanvasText;
1075
+ border-inline-start-color: Highlight;
1076
+ background: Canvas;
1077
+ }
1078
+ .fillo-file-state--failed { color: Highlight; }
994
1079
  .fillo-star--active,
995
1080
  .fillo-scale-step--active,
996
1081
  :where(.fillo-option--selected) {
@@ -1001,7 +1086,11 @@
1001
1086
  .fillo-number:focus-within,
1002
1087
  .fillo-phone-flag:focus-visible,
1003
1088
  .fillo-phone-search:focus-visible,
1089
+ .fillo-option:focus-within,
1090
+ :where(.fillo-toggle-input:focus-visible) + .fillo-toggle-track,
1091
+ .fillo-star:focus-visible,
1004
1092
  .fillo-scale-step:focus-visible,
1093
+ .fillo-matrix-cell:focus-within,
1005
1094
  .fillo-dropzone:focus-visible,
1006
1095
  .fillo-select:focus-visible {
1007
1096
  outline: 2px solid Highlight;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usefillo/dom",
3
- "version": "0.12.0",
3
+ "version": "0.12.1",
4
4
  "description": "Framework-agnostic DOM renderer and web component for embedding Fillo forms.",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -36,7 +36,7 @@
36
36
  "access": "public"
37
37
  },
38
38
  "dependencies": {
39
- "@usefillo/core": "^0.12.0"
39
+ "@usefillo/core": "^0.12.1"
40
40
  },
41
41
  "devDependencies": {
42
42
  "axe-core": "^4.10.0",