@usefillo/react 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/index.js +150 -111
- package/dist/styles.css +114 -25
- package/dist/styles.unlayered.css +114 -25
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -15,7 +15,6 @@ import {
|
|
|
15
15
|
createClient,
|
|
16
16
|
formSchemasEqual,
|
|
17
17
|
isBuildTimeDevEnv as isBuildTimeDevEnv2,
|
|
18
|
-
isField as isField2,
|
|
19
18
|
isFilloError as isFilloError2,
|
|
20
19
|
isLikelyDevEnv,
|
|
21
20
|
needsExplicitSubmit,
|
|
@@ -25,7 +24,7 @@ import {
|
|
|
25
24
|
reachablePageSequence,
|
|
26
25
|
resolveThemeAppearance
|
|
27
26
|
} from "@usefillo/core";
|
|
28
|
-
import {
|
|
27
|
+
import { resolveStrings, slotClass as slotClass3 } from "@usefillo/core";
|
|
29
28
|
|
|
30
29
|
// src/appearance.tsx
|
|
31
30
|
import { createContext, useContext } from "react";
|
|
@@ -488,6 +487,7 @@ import {
|
|
|
488
487
|
pipeBlock,
|
|
489
488
|
radioGroupStep,
|
|
490
489
|
REQUIRED_FIELD_MESSAGE,
|
|
490
|
+
requiredFieldMessage,
|
|
491
491
|
shouldAutoSubmit,
|
|
492
492
|
slotClass as slotClass2,
|
|
493
493
|
visibleFields
|
|
@@ -1008,6 +1008,76 @@ function uploadFailureMessage(error, strings) {
|
|
|
1008
1008
|
}
|
|
1009
1009
|
return strings.uploadFailed;
|
|
1010
1010
|
}
|
|
1011
|
+
function FileStateIcon({ state }) {
|
|
1012
|
+
if (state === "done") {
|
|
1013
|
+
return /* @__PURE__ */ jsx4("span", { className: "fillo-file-state fillo-file-state--done", "aria-hidden": "true", children: /* @__PURE__ */ jsxs4(
|
|
1014
|
+
"svg",
|
|
1015
|
+
{
|
|
1016
|
+
className: "fillo-file-state-icon",
|
|
1017
|
+
viewBox: "0 0 24 24",
|
|
1018
|
+
width: "22",
|
|
1019
|
+
height: "22",
|
|
1020
|
+
fill: "none",
|
|
1021
|
+
"aria-hidden": "true",
|
|
1022
|
+
focusable: "false",
|
|
1023
|
+
children: [
|
|
1024
|
+
/* @__PURE__ */ jsx4("path", { d: "M3.75 12a8.25 8.25 0 1 0 16.5 0 8.25 8.25 0 1 0-16.5 0" }),
|
|
1025
|
+
/* @__PURE__ */ jsx4("path", { d: "m8.5 12 2.25 2.25 4.75-5" })
|
|
1026
|
+
]
|
|
1027
|
+
}
|
|
1028
|
+
) });
|
|
1029
|
+
}
|
|
1030
|
+
if (state === "failed") {
|
|
1031
|
+
return /* @__PURE__ */ jsx4("span", { className: "fillo-file-state fillo-file-state--failed", "aria-hidden": "true", children: /* @__PURE__ */ jsxs4(
|
|
1032
|
+
"svg",
|
|
1033
|
+
{
|
|
1034
|
+
className: "fillo-file-state-icon",
|
|
1035
|
+
viewBox: "0 0 24 24",
|
|
1036
|
+
width: "22",
|
|
1037
|
+
height: "22",
|
|
1038
|
+
fill: "none",
|
|
1039
|
+
"aria-hidden": "true",
|
|
1040
|
+
focusable: "false",
|
|
1041
|
+
children: [
|
|
1042
|
+
/* @__PURE__ */ jsx4("path", { d: "M3.75 12a8.25 8.25 0 1 0 16.5 0 8.25 8.25 0 1 0-16.5 0" }),
|
|
1043
|
+
/* @__PURE__ */ jsx4("path", { d: "M12 7.75v5.5" }),
|
|
1044
|
+
/* @__PURE__ */ jsx4("path", { d: "M12 16.5h.01" })
|
|
1045
|
+
]
|
|
1046
|
+
}
|
|
1047
|
+
) });
|
|
1048
|
+
}
|
|
1049
|
+
return /* @__PURE__ */ jsx4("span", { className: "fillo-file-state fillo-file-state--uploading", "aria-hidden": "true", children: /* @__PURE__ */ jsxs4(
|
|
1050
|
+
"svg",
|
|
1051
|
+
{
|
|
1052
|
+
className: "fillo-file-state-icon",
|
|
1053
|
+
viewBox: "0 0 24 24",
|
|
1054
|
+
width: "22",
|
|
1055
|
+
height: "22",
|
|
1056
|
+
fill: "none",
|
|
1057
|
+
"aria-hidden": "true",
|
|
1058
|
+
focusable: "false",
|
|
1059
|
+
children: [
|
|
1060
|
+
/* @__PURE__ */ jsx4("path", { d: "M7.25 3.75h6.5l3 3v13.5h-9.5z" }),
|
|
1061
|
+
/* @__PURE__ */ jsx4("path", { d: "M13.75 3.75v3h3" })
|
|
1062
|
+
]
|
|
1063
|
+
}
|
|
1064
|
+
) });
|
|
1065
|
+
}
|
|
1066
|
+
function CloseIcon() {
|
|
1067
|
+
return /* @__PURE__ */ jsx4(
|
|
1068
|
+
"svg",
|
|
1069
|
+
{
|
|
1070
|
+
className: "fillo-file-action-icon",
|
|
1071
|
+
viewBox: "0 0 24 24",
|
|
1072
|
+
width: "16",
|
|
1073
|
+
height: "16",
|
|
1074
|
+
fill: "none",
|
|
1075
|
+
"aria-hidden": "true",
|
|
1076
|
+
focusable: "false",
|
|
1077
|
+
children: /* @__PURE__ */ jsx4("path", { d: "m7 7 10 10M17 7 7 17" })
|
|
1078
|
+
}
|
|
1079
|
+
);
|
|
1080
|
+
}
|
|
1011
1081
|
function FileUploadField({
|
|
1012
1082
|
field,
|
|
1013
1083
|
value,
|
|
@@ -1197,90 +1267,91 @@ function FileUploadField({
|
|
|
1197
1267
|
),
|
|
1198
1268
|
(inFlight.length > 0 || files.length > 0) && /* @__PURE__ */ jsxs4("ul", { className: "fillo-files", children: [
|
|
1199
1269
|
files.map((f) => /* @__PURE__ */ jsxs4("li", { className: "fillo-file fillo-file--done", children: [
|
|
1200
|
-
/* @__PURE__ */ jsx4(
|
|
1201
|
-
/* @__PURE__ */
|
|
1202
|
-
|
|
1203
|
-
|
|
1270
|
+
/* @__PURE__ */ jsx4(FileStateIcon, { state: "done" }),
|
|
1271
|
+
/* @__PURE__ */ jsxs4("span", { className: "fillo-file-content", children: [
|
|
1272
|
+
/* @__PURE__ */ jsx4("span", { className: "fillo-file-name", children: f.name }),
|
|
1273
|
+
/* @__PURE__ */ jsx4("span", { className: "fillo-file-meta", children: strings.uploadedFile(formatBytes(f.size)) })
|
|
1274
|
+
] }),
|
|
1275
|
+
/* @__PURE__ */ jsx4("span", { className: "fillo-file-actions", children: /* @__PURE__ */ jsx4(
|
|
1204
1276
|
"button",
|
|
1205
1277
|
{
|
|
1206
1278
|
type: "button",
|
|
1207
1279
|
className: "fillo-file-remove",
|
|
1208
|
-
"aria-label":
|
|
1280
|
+
"aria-label": `${strings.uploadRemove} ${f.name}`,
|
|
1209
1281
|
onClick: () => removeFile(f.fileId),
|
|
1210
|
-
children:
|
|
1282
|
+
children: /* @__PURE__ */ jsx4(CloseIcon, {})
|
|
1211
1283
|
}
|
|
1212
|
-
)
|
|
1284
|
+
) })
|
|
1213
1285
|
] }, f.fileId)),
|
|
1214
|
-
inFlight.map((f) => /* @__PURE__ */ jsxs4(
|
|
1215
|
-
"
|
|
1216
|
-
{
|
|
1217
|
-
|
|
1218
|
-
...f.error ? {} : {
|
|
1219
|
-
role: "progressbar",
|
|
1220
|
-
"aria-label": `Uploading ${f.name}`,
|
|
1221
|
-
"aria-valuemin": 0,
|
|
1222
|
-
"aria-valuemax": 100,
|
|
1223
|
-
"aria-valuenow": Math.round(f.fraction * 100)
|
|
1224
|
-
},
|
|
1225
|
-
children: [
|
|
1286
|
+
inFlight.map((f) => /* @__PURE__ */ jsxs4("li", { className: `fillo-file${f.error ? " fillo-file--failed" : ""}`, children: [
|
|
1287
|
+
/* @__PURE__ */ jsx4(FileStateIcon, { state: f.error ? "failed" : "uploading" }),
|
|
1288
|
+
f.error ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1289
|
+
/* @__PURE__ */ jsxs4("span", { className: "fillo-file-content", children: [
|
|
1226
1290
|
/* @__PURE__ */ jsx4("span", { className: "fillo-file-name", children: f.name }),
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1291
|
+
/* @__PURE__ */ jsx4("span", { className: "fillo-file-error", role: "alert", children: f.error })
|
|
1292
|
+
] }),
|
|
1293
|
+
/* @__PURE__ */ jsxs4("span", { className: "fillo-file-actions", children: [
|
|
1294
|
+
f.file && !f.tooLarge && remaining > 0 && /* @__PURE__ */ jsx4(
|
|
1295
|
+
"button",
|
|
1296
|
+
{
|
|
1297
|
+
type: "button",
|
|
1298
|
+
className: "fillo-file-retry",
|
|
1299
|
+
"aria-label": `${strings.uploadRetry} ${f.name}`,
|
|
1300
|
+
onClick: () => {
|
|
1301
|
+
const retryFile = f.file;
|
|
1302
|
+
if (!retryFile) return;
|
|
1303
|
+
setInFlight((prev) => prev.filter((x) => x.key !== f.key));
|
|
1304
|
+
void startUpload(retryFile);
|
|
1305
|
+
},
|
|
1306
|
+
children: strings.uploadRetry
|
|
1307
|
+
}
|
|
1308
|
+
),
|
|
1309
|
+
/* @__PURE__ */ jsx4(
|
|
1310
|
+
"button",
|
|
1311
|
+
{
|
|
1312
|
+
type: "button",
|
|
1313
|
+
className: "fillo-file-remove",
|
|
1314
|
+
"aria-label": `${strings.uploadDismiss} ${f.name}`,
|
|
1315
|
+
onClick: () => setInFlight((prev) => prev.filter((x) => x.key !== f.key)),
|
|
1316
|
+
children: /* @__PURE__ */ jsx4(CloseIcon, {})
|
|
1317
|
+
}
|
|
1318
|
+
)
|
|
1319
|
+
] })
|
|
1320
|
+
] }) : /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1321
|
+
/* @__PURE__ */ jsxs4("span", { className: "fillo-file-content", children: [
|
|
1322
|
+
/* @__PURE__ */ jsx4("span", { className: "fillo-file-name", children: f.name }),
|
|
1323
|
+
/* @__PURE__ */ jsx4("span", { className: "fillo-file-meta", children: strings.uploadingFile(Math.round(f.fraction * 100), formatBytes(f.size)) })
|
|
1324
|
+
] }),
|
|
1325
|
+
/* @__PURE__ */ jsx4("span", { className: "fillo-file-actions", children: /* @__PURE__ */ jsx4(
|
|
1326
|
+
"button",
|
|
1327
|
+
{
|
|
1328
|
+
type: "button",
|
|
1329
|
+
className: "fillo-file-remove",
|
|
1330
|
+
"aria-label": `${strings.uploadCancel} ${f.name}`,
|
|
1331
|
+
onClick: () => cancelUpload(f.key),
|
|
1332
|
+
children: /* @__PURE__ */ jsx4(CloseIcon, {})
|
|
1333
|
+
}
|
|
1334
|
+
) }),
|
|
1335
|
+
/* @__PURE__ */ jsx4(
|
|
1336
|
+
"span",
|
|
1337
|
+
{
|
|
1338
|
+
className: "fillo-progress",
|
|
1339
|
+
role: "progressbar",
|
|
1340
|
+
"aria-label": `Uploading ${f.name}`,
|
|
1341
|
+
"aria-valuemin": 0,
|
|
1342
|
+
"aria-valuemax": 100,
|
|
1343
|
+
"aria-valuenow": Math.round(f.fraction * 100),
|
|
1344
|
+
children: /* @__PURE__ */ jsx4(
|
|
1273
1345
|
"span",
|
|
1274
1346
|
{
|
|
1275
1347
|
className: "fillo-progress-bar",
|
|
1276
1348
|
style: { width: `${f.fraction * 100}%` }
|
|
1277
1349
|
}
|
|
1278
|
-
)
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
}
|
|
1282
|
-
|
|
1283
|
-
))
|
|
1350
|
+
)
|
|
1351
|
+
}
|
|
1352
|
+
)
|
|
1353
|
+
] })
|
|
1354
|
+
] }, f.key))
|
|
1284
1355
|
] }),
|
|
1285
1356
|
error && /* @__PURE__ */ jsx4("p", { className: slots.error, "data-fillo": "error", id: ids.errorId, children: error })
|
|
1286
1357
|
]
|
|
@@ -2214,7 +2285,7 @@ function BlockRendererInner({ block, api, components, customComponents }) {
|
|
|
2214
2285
|
Component = components?.[block.kind] ?? DEFAULT_COMPONENTS[block.kind];
|
|
2215
2286
|
}
|
|
2216
2287
|
const rawError = api.errors[block.id];
|
|
2217
|
-
const error = rawError === REQUIRED_FIELD_MESSAGE ? strings
|
|
2288
|
+
const error = rawError === REQUIRED_FIELD_MESSAGE ? requiredFieldMessage(block, strings) : rawError;
|
|
2218
2289
|
return /* @__PURE__ */ jsx5(
|
|
2219
2290
|
Component,
|
|
2220
2291
|
{
|
|
@@ -2414,16 +2485,13 @@ function nextFrame(run) {
|
|
|
2414
2485
|
if (typeof requestAnimationFrame === "function") requestAnimationFrame(run);
|
|
2415
2486
|
else setTimeout(run, 0);
|
|
2416
2487
|
}
|
|
2417
|
-
function
|
|
2488
|
+
function focusFirstInvalid(formEl) {
|
|
2418
2489
|
if (!formEl || typeof window === "undefined") return;
|
|
2419
2490
|
nextFrame(() => {
|
|
2420
|
-
formEl.querySelector(
|
|
2491
|
+
const invalid = formEl.querySelector('[aria-invalid="true"]');
|
|
2492
|
+
resolveFocusable(invalid)?.focus();
|
|
2421
2493
|
});
|
|
2422
2494
|
}
|
|
2423
|
-
function focusField(inputId) {
|
|
2424
|
-
if (typeof document === "undefined") return;
|
|
2425
|
-
resolveFocusable(document.getElementById(inputId))?.focus();
|
|
2426
|
-
}
|
|
2427
2495
|
var HP_STYLE = {
|
|
2428
2496
|
position: "absolute",
|
|
2429
2497
|
left: "-9999px",
|
|
@@ -2986,17 +3054,6 @@ function ResolvedForm(props) {
|
|
|
2986
3054
|
const progressPos = progressSeq.indexOf(api.page.id);
|
|
2987
3055
|
const progressStep = progressPos >= 0 ? progressPos + 1 : Math.min(api.pageIndex + 1, progressTotal);
|
|
2988
3056
|
const submitFixUrl = devChrome && resolutionFailureCode === "form_not_published" && warningCode === "storage_required" ? safeHttpUrl(warningUrl) : null;
|
|
2989
|
-
const invalidFields = [];
|
|
2990
|
-
for (const block of api.blocks) {
|
|
2991
|
-
if (!isField2(block)) continue;
|
|
2992
|
-
const raw = api.errors[block.id];
|
|
2993
|
-
if (!raw) continue;
|
|
2994
|
-
invalidFields.push({
|
|
2995
|
-
field: block,
|
|
2996
|
-
error: raw === REQUIRED_FIELD_MESSAGE2 ? strings.required : raw,
|
|
2997
|
-
inputId: createFilloFieldIds(instanceId, block.id).inputId
|
|
2998
|
-
});
|
|
2999
|
-
}
|
|
3000
3057
|
const rootClass = slotClass3(`fillo-form ${props.className ?? ""}`, appearance, {
|
|
3001
3058
|
slot: "root",
|
|
3002
3059
|
status: api.status
|
|
@@ -3101,24 +3158,6 @@ function ResolvedForm(props) {
|
|
|
3101
3158
|
children: api.page.title
|
|
3102
3159
|
}
|
|
3103
3160
|
),
|
|
3104
|
-
invalidFields.length > 0 && /* @__PURE__ */ jsxs6("div", { className: "fillo-error-summary", role: "alert", tabIndex: -1, "data-fillo": "error-summary", children: [
|
|
3105
|
-
/* @__PURE__ */ jsx7("p", { className: "fillo-error-summary-title", children: strings.errorSummaryTitle }),
|
|
3106
|
-
/* @__PURE__ */ jsx7("ul", { children: invalidFields.map(({ field, error, inputId }) => /* @__PURE__ */ jsx7("li", { children: /* @__PURE__ */ jsxs6(
|
|
3107
|
-
"a",
|
|
3108
|
-
{
|
|
3109
|
-
href: `#${inputId}`,
|
|
3110
|
-
onClick: (e) => {
|
|
3111
|
-
e.preventDefault();
|
|
3112
|
-
focusField(inputId);
|
|
3113
|
-
},
|
|
3114
|
-
children: [
|
|
3115
|
-
field.label,
|
|
3116
|
-
": ",
|
|
3117
|
-
error
|
|
3118
|
-
]
|
|
3119
|
-
}
|
|
3120
|
-
) }, field.id)) })
|
|
3121
|
-
] }),
|
|
3122
3161
|
/* @__PURE__ */ jsx7(
|
|
3123
3162
|
"div",
|
|
3124
3163
|
{
|
|
@@ -3246,11 +3285,11 @@ function ResolvedForm(props) {
|
|
|
3246
3285
|
e.preventDefault();
|
|
3247
3286
|
const formEl = e.currentTarget;
|
|
3248
3287
|
if (api.isLastPage) {
|
|
3249
|
-
void api.submit().then(() =>
|
|
3288
|
+
void api.submit().then(() => focusFirstInvalid(formEl)).catch(() => {
|
|
3250
3289
|
});
|
|
3251
3290
|
} else {
|
|
3252
3291
|
api.next();
|
|
3253
|
-
|
|
3292
|
+
focusFirstInvalid(formEl);
|
|
3254
3293
|
}
|
|
3255
3294
|
},
|
|
3256
3295
|
children: formBody
|
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
|
|
629
|
+
grid-template-columns: auto minmax(0, 1fr) auto;
|
|
582
630
|
align-items: center;
|
|
583
|
-
gap: 0.45rem 0.
|
|
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
|
-
|
|
592
|
-
border-
|
|
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.
|
|
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-
|
|
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.
|
|
731
|
+
padding: 0 0.5rem;
|
|
647
732
|
}
|
|
648
733
|
.fillo-file-retry:hover { text-decoration: underline; }
|
|
649
734
|
.fillo-progress {
|
|
650
|
-
grid-column:
|
|
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
|
|
629
|
+
grid-template-columns: auto minmax(0, 1fr) auto;
|
|
582
630
|
align-items: center;
|
|
583
|
-
gap: 0.45rem 0.
|
|
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
|
-
|
|
592
|
-
border-
|
|
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.
|
|
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-
|
|
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.
|
|
731
|
+
padding: 0 0.5rem;
|
|
647
732
|
}
|
|
648
733
|
.fillo-file-retry:hover { text-decoration: underline; }
|
|
649
734
|
.fillo-progress {
|
|
650
|
-
grid-column:
|
|
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/react",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"description": "Headless React components for embedding Fillo forms natively in your product.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"access": "public"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@usefillo/core": "^0.12.
|
|
37
|
+
"@usefillo/core": "^0.12.1"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"react": "^18.0.0 || ^19.0.0",
|