@multiplatform.one/forms 7.54.0 → 7.55.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/dist/cjs/Button/index.cjs +10 -1
- package/dist/cjs/Button/index.native.js +13 -4
- package/dist/cjs/Button/index.native.js.map +1 -1
- package/dist/cjs/fields/Progress/index.cjs +7 -2
- package/dist/cjs/fields/Progress/index.native.js +7 -2
- package/dist/cjs/fields/Progress/index.native.js.map +1 -1
- package/dist/cjs/formSpacing.cjs +1 -1
- package/dist/cjs/formSpacing.native.js +1 -1
- package/dist/esm/Button/index.mjs +11 -2
- package/dist/esm/Button/index.mjs.map +1 -1
- package/dist/esm/Button/index.native.js +14 -5
- package/dist/esm/Button/index.native.js.map +1 -1
- package/dist/esm/fields/Progress/index.mjs +8 -3
- package/dist/esm/fields/Progress/index.mjs.map +1 -1
- package/dist/esm/fields/Progress/index.native.js +8 -3
- package/dist/esm/fields/Progress/index.native.js.map +1 -1
- package/dist/esm/formSpacing.mjs +1 -1
- package/dist/esm/formSpacing.native.js +1 -1
- package/dist/jsx/Button/index.mjs +11 -2
- package/dist/jsx/Button/index.mjs.map +1 -1
- package/dist/jsx/Button/index.native.js +13 -4
- package/dist/jsx/Button/index.native.js.map +1 -1
- package/dist/jsx/fields/Progress/index.mjs +8 -3
- package/dist/jsx/fields/Progress/index.mjs.map +1 -1
- package/dist/jsx/fields/Progress/index.native.js +7 -2
- package/dist/jsx/fields/Progress/index.native.js.map +1 -1
- package/dist/jsx/formSpacing.mjs +1 -1
- package/dist/jsx/formSpacing.native.js +1 -1
- package/package.json +8 -8
- package/src/Button/Button.accentInk.spec.tsx +135 -0
- package/src/Button/index.tsx +14 -0
- package/src/FieldGroup.spec.tsx +4 -4
- package/src/Form/form.spec.tsx +4 -4
- package/src/FormGrid.spec.tsx +15 -14
- package/src/fieldLayout.spec.tsx +7 -7
- package/src/fields/Progress/Progress.spec.tsx +21 -0
- package/src/fields/Progress/index.tsx +18 -3
- package/src/formSpacing.ts +3 -3
- package/types/Button/index.d.ts +8 -1
- package/types/Button/index.d.ts.map +1 -1
- package/types/fields/Progress/index.d.ts.map +1 -1
- package/types/formSpacing.d.ts +3 -3
|
@@ -29,7 +29,7 @@ __export(formSpacing_exports, {
|
|
|
29
29
|
formSectionGap: () => formSectionGap
|
|
30
30
|
});
|
|
31
31
|
module.exports = __toCommonJS(formSpacing_exports);
|
|
32
|
-
var formFieldGap = "$
|
|
32
|
+
var formFieldGap = "$4";
|
|
33
33
|
var formSectionGap = "$8";
|
|
34
34
|
var formReadableMaxWidth = 560;
|
|
35
35
|
//# sourceMappingURL=formSpacing.native.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@multiplatform.one/forms",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.55.0",
|
|
4
4
|
"description": "Cross-platform form components with URL state management",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cross-platform",
|
|
@@ -57,10 +57,10 @@
|
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
59
|
"@floating-ui/react": "^0.27.20",
|
|
60
|
-
"@multiplatform.one/platform": "^7.
|
|
61
|
-
"@multiplatform.one/router": "^7.
|
|
62
|
-
"@multiplatform.one/table-primitives": "^7.
|
|
63
|
-
"@multiplatform.one/theme": "^7.
|
|
60
|
+
"@multiplatform.one/platform": "^7.55.0",
|
|
61
|
+
"@multiplatform.one/router": "^7.55.0",
|
|
62
|
+
"@multiplatform.one/table-primitives": "^7.55.0",
|
|
63
|
+
"@multiplatform.one/theme": "^7.55.0",
|
|
64
64
|
"@phosphor-icons/react": "^2.1.10",
|
|
65
65
|
"@tamagui/get-font-sized": "2.7.6",
|
|
66
66
|
"@tamagui/get-token": "2.7.6",
|
|
@@ -79,9 +79,9 @@
|
|
|
79
79
|
"tamagui": "2.7.6"
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
|
-
"@multiplatform.one/config": "7.
|
|
83
|
-
"@multiplatform.one/storybook": "7.
|
|
84
|
-
"@multiplatform.one/test-utils": "7.
|
|
82
|
+
"@multiplatform.one/config": "7.55.0",
|
|
83
|
+
"@multiplatform.one/storybook": "7.55.0",
|
|
84
|
+
"@multiplatform.one/test-utils": "7.55.0",
|
|
85
85
|
"@tamagui/build": "2.7.6",
|
|
86
86
|
"@tamagui/config": "2.7.6",
|
|
87
87
|
"@tamagui/vite-plugin": "2.7.6",
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vitest-environment jsdom
|
|
3
|
+
*
|
|
4
|
+
* LC-145 (FZ-7993): a chromeless bar button with `accentInk` paints its label
|
|
5
|
+
* and its frame's `color` (currentColor glyphs) in the host's identity ink
|
|
6
|
+
* (`useIdentityInkOnSurface`), the iOS bar-button tint: the hue under a colour
|
|
7
|
+
* theme, the primary ink under the hueless house theme, never the grey accent
|
|
8
|
+
* step. Disabled leaves the tint for its own ink, and without the prop a
|
|
9
|
+
* chromeless button keeps its neutral ink.
|
|
10
|
+
*
|
|
11
|
+
* jsdom cascades no Tamagui CSS, so this reads the atomic `_col-` class and
|
|
12
|
+
* the injected rule behind it.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { cleanup, render, screen } from "@testing-library/react";
|
|
16
|
+
import {
|
|
17
|
+
createDefaultThemeConfig,
|
|
18
|
+
useAccentOnSurface,
|
|
19
|
+
useIdentityInkOnSurface,
|
|
20
|
+
} from "@multiplatform.one/theme";
|
|
21
|
+
import type { ReactElement } from "react";
|
|
22
|
+
import { TamaguiProvider, YStack } from "tamagui";
|
|
23
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
24
|
+
import { Button } from "./index";
|
|
25
|
+
|
|
26
|
+
afterEach(cleanup);
|
|
27
|
+
|
|
28
|
+
const houseConfig = createDefaultThemeConfig();
|
|
29
|
+
const SCHEMES = ["light", "dark"] as const;
|
|
30
|
+
|
|
31
|
+
function AccentProbe() {
|
|
32
|
+
return (
|
|
33
|
+
<span
|
|
34
|
+
data-testid="accent-probe"
|
|
35
|
+
data-ink={useIdentityInkOnSurface()}
|
|
36
|
+
data-accent={useAccentOnSurface()}
|
|
37
|
+
/>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function houseRender(ui: ReactElement, scheme: string) {
|
|
42
|
+
return render(
|
|
43
|
+
<TamaguiProvider config={houseConfig.tamagui} defaultTheme={scheme}>
|
|
44
|
+
<YStack backgroundColor="$background">
|
|
45
|
+
<AccentProbe />
|
|
46
|
+
{ui}
|
|
47
|
+
</YStack>
|
|
48
|
+
</TamaguiProvider>,
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function injectedRuleValue(className: string, property: string): string | null {
|
|
53
|
+
for (const sheet of Array.from(document.styleSheets)) {
|
|
54
|
+
for (const rule of Array.from(sheet.cssRules)) {
|
|
55
|
+
if (!(rule instanceof CSSStyleRule)) continue;
|
|
56
|
+
if (!rule.selectorText.endsWith(`.${className}`)) continue;
|
|
57
|
+
const value = rule.style.getPropertyValue(property);
|
|
58
|
+
if (value) return value.trim();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function paintedColor(el: Element): string | null {
|
|
65
|
+
const cls = Array.from(el.classList).find(
|
|
66
|
+
(c) => c.startsWith("_col-") && !/^_col-0(hover|active|focus|press)/.test(c),
|
|
67
|
+
);
|
|
68
|
+
return cls ? injectedRuleValue(cls, "color") : null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function accentInk(): string {
|
|
72
|
+
return (screen.getByTestId("accent-probe").getAttribute("data-ink") ?? "").toLowerCase();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function greyAccent(): string {
|
|
76
|
+
return (screen.getByTestId("accent-probe").getAttribute("data-accent") ?? "").toLowerCase();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
describe("Button accentInk (LC-145 bar tint)", () => {
|
|
80
|
+
for (const scheme of SCHEMES) {
|
|
81
|
+
it(`${scheme}: a chromeless accentInk button paints label and frame in the identity ink`, () => {
|
|
82
|
+
houseRender(
|
|
83
|
+
<Button chromeless accentInk>
|
|
84
|
+
Components
|
|
85
|
+
</Button>,
|
|
86
|
+
scheme,
|
|
87
|
+
);
|
|
88
|
+
const label = screen.getByText("Components");
|
|
89
|
+
const frame = label.closest("[role=button]") as Element;
|
|
90
|
+
const ink = accentInk();
|
|
91
|
+
expect(ink).toMatch(/^#|^rgb|^hsl/);
|
|
92
|
+
expect(paintedColor(label)?.toLowerCase()).toBe(ink);
|
|
93
|
+
expect(paintedColor(frame)?.toLowerCase()).toBe(ink);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it(`${scheme}: the hueless house theme tints with the primary ink, not the grey accent step`, () => {
|
|
97
|
+
houseRender(
|
|
98
|
+
<Button chromeless accentInk>
|
|
99
|
+
Components
|
|
100
|
+
</Button>,
|
|
101
|
+
scheme,
|
|
102
|
+
);
|
|
103
|
+
expect(greyAccent()).not.toBe(accentInk());
|
|
104
|
+
expect(paintedColor(screen.getByText("Components"))?.toLowerCase()).not.toBe(greyAccent());
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it(`${scheme}: under a hue the tint is the hue`, () => {
|
|
108
|
+
houseRender(
|
|
109
|
+
<Button chromeless accentInk>
|
|
110
|
+
Components
|
|
111
|
+
</Button>,
|
|
112
|
+
`${scheme}_blue`,
|
|
113
|
+
);
|
|
114
|
+
expect(accentInk()).toBe(greyAccent());
|
|
115
|
+
expect(paintedColor(screen.getByText("Components"))?.toLowerCase()).toBe(accentInk());
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it(`${scheme}: without accentInk a chromeless button keeps its neutral ink`, () => {
|
|
119
|
+
houseRender(<Button chromeless>Components</Button>, `${scheme}_blue`);
|
|
120
|
+
const label = screen.getByText("Components");
|
|
121
|
+
expect(paintedColor(label)?.toLowerCase()).not.toBe(accentInk());
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it(`${scheme}: a disabled accentInk button leaves the tint`, () => {
|
|
125
|
+
houseRender(
|
|
126
|
+
<Button chromeless accentInk disabled disabledReason="Nothing to go back to">
|
|
127
|
+
Components
|
|
128
|
+
</Button>,
|
|
129
|
+
scheme,
|
|
130
|
+
);
|
|
131
|
+
const label = screen.getByText("Components");
|
|
132
|
+
expect(paintedColor(label)?.toLowerCase()).not.toBe(accentInk());
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
});
|
package/src/Button/index.tsx
CHANGED
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
solidPaletteThemes,
|
|
32
32
|
useAccentOnSurface,
|
|
33
33
|
useBarSurface,
|
|
34
|
+
useIdentityInkOnSurface,
|
|
34
35
|
useResolvedKnobs,
|
|
35
36
|
useTouchSurface,
|
|
36
37
|
type ControlTier,
|
|
@@ -372,6 +373,13 @@ export interface ButtonProps extends Omit<
|
|
|
372
373
|
* that paints a frame: the frame is what aligns there.
|
|
373
374
|
*/
|
|
374
375
|
edge?: "start" | "end";
|
|
376
|
+
/**
|
|
377
|
+
* LC-145: a chromeless bar button's label and glyphs take the host's
|
|
378
|
+
* identity ink (`useIdentityInkOnSurface`), the iOS bar-button tint: the
|
|
379
|
+
* theme's hue, or the primary ink when the theme has none. No effect on a
|
|
380
|
+
* button that paints a frame, while selected, or disabled.
|
|
381
|
+
*/
|
|
382
|
+
accentInk?: boolean;
|
|
375
383
|
}
|
|
376
384
|
|
|
377
385
|
export function Button({
|
|
@@ -397,6 +405,7 @@ export function Button({
|
|
|
397
405
|
circular,
|
|
398
406
|
chromeless,
|
|
399
407
|
edge,
|
|
408
|
+
accentInk,
|
|
400
409
|
verb,
|
|
401
410
|
noun,
|
|
402
411
|
actionRole,
|
|
@@ -473,6 +482,7 @@ export function Button({
|
|
|
473
482
|
const parentScopeTheme = useTheme();
|
|
474
483
|
const pageOutlineColor = parentScopeTheme.outlineColor?.val as string | undefined;
|
|
475
484
|
const hostAccentInk = useAccentOnSurface();
|
|
485
|
+
const hostIdentityInk = useIdentityInkOnSurface();
|
|
476
486
|
const grouped = useControlGrouped();
|
|
477
487
|
// LC-153 CONTROL-TIERS: a bar paints its neutral buttons plain; content
|
|
478
488
|
// paints them tinted. The scheme picks the wash step.
|
|
@@ -646,6 +656,7 @@ export function Button({
|
|
|
646
656
|
const isSelected =
|
|
647
657
|
selected ?? (ariaPressedProp === true || ariaPressedProp === "true" ? true : undefined);
|
|
648
658
|
const selectedFill = Boolean(isSelected) && !unavailable;
|
|
659
|
+
const barInk = accentInk && chromeless && !selectedFill && !unavailable ? hostIdentityInk : null;
|
|
649
660
|
const iconSize = nested
|
|
650
661
|
? Math.min(recipe.iconSize, Math.max(12, Math.round(knobProps.nestedControl.px * 0.45)))
|
|
651
662
|
: recipe.iconSize;
|
|
@@ -683,6 +694,7 @@ export function Button({
|
|
|
683
694
|
: outlinedInk
|
|
684
695
|
? { color: outlinedInk }
|
|
685
696
|
: undefined)}
|
|
697
|
+
{...(barInk ? { color: barInk } : undefined)}
|
|
686
698
|
// LC-40: on the washed disabled chrome the label leaves the on-fill
|
|
687
699
|
// foreground for the wash's AA ink (keepLabel keeps >=4.5:1).
|
|
688
700
|
{...(unavailable ? disabledText : undefined)}
|
|
@@ -711,6 +723,7 @@ export function Button({
|
|
|
711
723
|
const nativeIconColor =
|
|
712
724
|
props.color ??
|
|
713
725
|
(unavailable ? disabledText.color : undefined) ??
|
|
726
|
+
barInk ??
|
|
714
727
|
(textColor
|
|
715
728
|
? outlinedOnHost
|
|
716
729
|
? hostScoped({ color: textColor }).color
|
|
@@ -868,6 +881,7 @@ export function Button({
|
|
|
868
881
|
// (LC-05); outlined frames sit on the page, so re-anchor inherited
|
|
869
882
|
// text/icon color (currentColor) to the hue's readable text tier.
|
|
870
883
|
{...(outlinedInk ? { color: outlinedInk } : undefined)}
|
|
884
|
+
{...(barInk ? { color: barInk } : undefined)}
|
|
871
885
|
// LC-40 DISABLED-VISIBLE: keepLabel washes the chrome (muted fill/
|
|
872
886
|
// border) while label/glyphs re-anchor to the lowest AA text tier
|
|
873
887
|
// (`color` inherits into currentColor icons); dimWhole dims the
|
package/src/FieldGroup.spec.tsx
CHANGED
|
@@ -36,7 +36,7 @@ describe("FieldGroup design-law (MPO-60)", () => {
|
|
|
36
36
|
expect(["400", "normal"]).toContain(String(weight));
|
|
37
37
|
});
|
|
38
38
|
|
|
39
|
-
it("field gap is the
|
|
39
|
+
it("field gap is the field rhythm role (fieldGap $4, LC-154) at any size token, never sizeToken", () => {
|
|
40
40
|
const result = renderWithProviders(
|
|
41
41
|
<Surface size="$5">
|
|
42
42
|
<FieldGroup legend="Billing">
|
|
@@ -45,11 +45,11 @@ describe("FieldGroup design-law (MPO-60)", () => {
|
|
|
45
45
|
</Surface>,
|
|
46
46
|
);
|
|
47
47
|
const group = result.container.querySelector("[data-mpo-field-group]");
|
|
48
|
-
expect(group?.getAttribute("data-field-gap")).toBe("$
|
|
48
|
+
expect(group?.getAttribute("data-field-gap")).toBe("$4");
|
|
49
49
|
expect(group?.getAttribute("data-size-token")).toBe("$5");
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
-
it("has no compact switch: a smaller Surface changes the token, not the gap", () => {
|
|
52
|
+
it("has no compact switch: a smaller Surface changes the token, not the gap (LC-154)", () => {
|
|
53
53
|
const result = renderWithProviders(
|
|
54
54
|
<Surface size="$3">
|
|
55
55
|
<FieldGroup legend="Small">
|
|
@@ -59,7 +59,7 @@ describe("FieldGroup design-law (MPO-60)", () => {
|
|
|
59
59
|
);
|
|
60
60
|
const group = result.container.querySelector("[data-mpo-field-group]");
|
|
61
61
|
expect(group?.getAttribute("data-size-token")).toBe("$3");
|
|
62
|
-
expect(group?.getAttribute("data-field-gap")).toBe("$
|
|
62
|
+
expect(group?.getAttribute("data-field-gap")).toBe("$4");
|
|
63
63
|
expect(group?.hasAttribute("data-density")).toBe(false);
|
|
64
64
|
});
|
|
65
65
|
});
|
package/src/Form/form.spec.tsx
CHANGED
|
@@ -374,7 +374,7 @@ describe("Form", () => {
|
|
|
374
374
|
});
|
|
375
375
|
|
|
376
376
|
describe("layout recipes (DG-FORM-01/06, LC-73)", () => {
|
|
377
|
-
it("owns vertical rhythm from the
|
|
377
|
+
it("owns vertical rhythm from the field rhythm role (fieldGap $4, LC-154), not sizeToken", () => {
|
|
378
378
|
const result = renderWithProviders(
|
|
379
379
|
<Surface size="$5">
|
|
380
380
|
<Form onSubmit={vi.fn()} aria-label="Layout Form">
|
|
@@ -383,12 +383,12 @@ describe("Form", () => {
|
|
|
383
383
|
</Surface>,
|
|
384
384
|
);
|
|
385
385
|
const layout = result.container.querySelector("[data-mpo-form-layout]");
|
|
386
|
-
expect(layout?.getAttribute("data-gap")).toBe("$
|
|
386
|
+
expect(layout?.getAttribute("data-gap")).toBe("$4");
|
|
387
387
|
expect(layout?.getAttribute("data-size-token")).toBe("$5");
|
|
388
388
|
expect(layout?.hasAttribute("data-density")).toBe(false);
|
|
389
389
|
});
|
|
390
390
|
|
|
391
|
-
it("size forwards a token to every field and keeps the rhythm on the role", () => {
|
|
391
|
+
it("size forwards a token to every field and keeps the rhythm on the fieldGap role (LC-154)", () => {
|
|
392
392
|
const result = renderWithProviders(
|
|
393
393
|
<Form size="$3" onSubmit={vi.fn()}>
|
|
394
394
|
<Button action="submit" size="$5">
|
|
@@ -398,7 +398,7 @@ describe("Form", () => {
|
|
|
398
398
|
);
|
|
399
399
|
const layout = result.container.querySelector("[data-mpo-form-layout]");
|
|
400
400
|
expect(layout?.getAttribute("data-size-token")).toBe("$3");
|
|
401
|
-
expect(layout?.getAttribute("data-gap")).toBe("$
|
|
401
|
+
expect(layout?.getAttribute("data-gap")).toBe("$4");
|
|
402
402
|
expect(result.getByRole("button").getAttribute("data-size-token")).toBe("$3");
|
|
403
403
|
});
|
|
404
404
|
|
package/src/FormGrid.spec.tsx
CHANGED
|
@@ -53,8 +53,8 @@ function stubContainerWidth(width: number) {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
describe("formSpacing tokens", () => {
|
|
56
|
-
it("encodes section gap larger than field gap (DG-FORM-06)", () => {
|
|
57
|
-
expect(formFieldGap).toBe("$
|
|
56
|
+
it("encodes section gap larger than field gap (DG-FORM-06; field rhythm $4, LC-154)", () => {
|
|
57
|
+
expect(formFieldGap).toBe("$4");
|
|
58
58
|
expect(formSectionGap).toBe("$8");
|
|
59
59
|
expect(Number(formSectionGap.slice(1))).toBeGreaterThan(Number(formFieldGap.slice(1)));
|
|
60
60
|
});
|
|
@@ -78,7 +78,8 @@ describe("FormGrid", () => {
|
|
|
78
78
|
expect(grid?.getAttribute("data-columns")).toBe("1");
|
|
79
79
|
expect(grid?.getAttribute("data-requested-columns")).toBe("1");
|
|
80
80
|
expect(grid?.getAttribute("data-max-columns")).toBe("2");
|
|
81
|
-
|
|
81
|
+
// LC-154: fields stack at the fieldGap role.
|
|
82
|
+
expect(grid?.getAttribute("data-gap")).toBe("$4");
|
|
82
83
|
expect(grid?.getAttribute("data-size-token")).toBe("$true");
|
|
83
84
|
});
|
|
84
85
|
|
|
@@ -129,7 +130,7 @@ describe("FormGrid", () => {
|
|
|
129
130
|
expect(grid.style.gridTemplateColumns).toBe("repeat(1, minmax(0, 1fr))");
|
|
130
131
|
});
|
|
131
132
|
|
|
132
|
-
it("gap is the
|
|
133
|
+
it("gap is the field rhythm role (fieldGap $4, LC-154) at any size token, never sizeToken", () => {
|
|
133
134
|
const result = renderWithProviders(
|
|
134
135
|
<Surface size="$5">
|
|
135
136
|
<FormGrid>
|
|
@@ -138,7 +139,7 @@ describe("FormGrid", () => {
|
|
|
138
139
|
</Surface>,
|
|
139
140
|
);
|
|
140
141
|
const grid = result.container.querySelector("[data-mpo-form-grid]");
|
|
141
|
-
expect(grid?.getAttribute("data-gap")).toBe("$
|
|
142
|
+
expect(grid?.getAttribute("data-gap")).toBe("$4");
|
|
142
143
|
expect(grid?.getAttribute("data-size-token")).toBe("$5");
|
|
143
144
|
});
|
|
144
145
|
|
|
@@ -153,10 +154,10 @@ describe("FormGrid", () => {
|
|
|
153
154
|
const grid = result.container.querySelector("[data-mpo-form-grid]");
|
|
154
155
|
expect(grid?.hasAttribute("data-density")).toBe(false);
|
|
155
156
|
expect(grid?.getAttribute("data-size-token")).toBe("$3");
|
|
156
|
-
expect(grid?.getAttribute("data-gap")).toBe("$
|
|
157
|
+
expect(grid?.getAttribute("data-gap")).toBe("$4");
|
|
157
158
|
});
|
|
158
159
|
|
|
159
|
-
it("spreads the role
|
|
160
|
+
it("spreads the fieldGap role fragment (not a raw 16, LC-154)", () => {
|
|
160
161
|
const result = renderWithProviders(
|
|
161
162
|
<Preset>
|
|
162
163
|
<FormGrid>
|
|
@@ -165,7 +166,7 @@ describe("FormGrid", () => {
|
|
|
165
166
|
</Preset>,
|
|
166
167
|
);
|
|
167
168
|
const grid = result.container.querySelector("[data-mpo-form-grid]");
|
|
168
|
-
expect(grid?.getAttribute("data-gap")).toBe("$
|
|
169
|
+
expect(grid?.getAttribute("data-gap")).toBe("$4");
|
|
169
170
|
});
|
|
170
171
|
});
|
|
171
172
|
|
|
@@ -195,7 +196,7 @@ describe("FieldGroup", () => {
|
|
|
195
196
|
).toBe("2");
|
|
196
197
|
});
|
|
197
198
|
|
|
198
|
-
it("field gap is the
|
|
199
|
+
it("field gap is the field rhythm role (fieldGap $4, LC-154), not the size token", () => {
|
|
199
200
|
const result = renderWithProviders(
|
|
200
201
|
<Surface size="$5">
|
|
201
202
|
<FieldGroup legend="Billing">
|
|
@@ -204,7 +205,7 @@ describe("FieldGroup", () => {
|
|
|
204
205
|
</Surface>,
|
|
205
206
|
);
|
|
206
207
|
const group = result.container.querySelector("[data-mpo-field-group]");
|
|
207
|
-
expect(group?.getAttribute("data-field-gap")).toBe("$
|
|
208
|
+
expect(group?.getAttribute("data-field-gap")).toBe("$4");
|
|
208
209
|
expect(group?.getAttribute("data-size-token")).toBe("$5");
|
|
209
210
|
});
|
|
210
211
|
});
|
|
@@ -257,7 +258,7 @@ describe("FormSection", () => {
|
|
|
257
258
|
});
|
|
258
259
|
|
|
259
260
|
describe("FormSection semantic gaps (DG-FORM-06)", () => {
|
|
260
|
-
it("defaults field gap to knobProps.
|
|
261
|
+
it("defaults field gap to knobProps.fieldGap (LC-154) and section gap to knobProps.gapLg", () => {
|
|
261
262
|
const result = renderWithProviders(
|
|
262
263
|
<FormSectionStack>
|
|
263
264
|
<FormSection label="A">
|
|
@@ -267,8 +268,8 @@ describe("FormSection semantic gaps (DG-FORM-06)", () => {
|
|
|
267
268
|
);
|
|
268
269
|
const section = result.container.querySelector("[data-mpo-form-section]");
|
|
269
270
|
const stack = result.container.querySelector("[data-mpo-form-section-stack]");
|
|
270
|
-
// knob defaults:
|
|
271
|
-
expect(section?.getAttribute("data-field-gap")).toBe("$
|
|
271
|
+
// knob defaults: fieldGap $4 (field to field, LC-154), gapLg $5 (between groups)
|
|
272
|
+
expect(section?.getAttribute("data-field-gap")).toBe("$4");
|
|
272
273
|
expect(stack?.getAttribute("data-section-gap")).toBe("$5");
|
|
273
274
|
const fieldStep = Number(section?.getAttribute("data-field-gap")?.slice(1));
|
|
274
275
|
const sectionStep = Number(stack?.getAttribute("data-section-gap")?.slice(1));
|
|
@@ -287,7 +288,7 @@ describe("FormSection semantic gaps (DG-FORM-06)", () => {
|
|
|
287
288
|
);
|
|
288
289
|
const section = result.container.querySelector("[data-mpo-form-section]");
|
|
289
290
|
const stack = result.container.querySelector("[data-mpo-form-section-stack]");
|
|
290
|
-
expect(section?.getAttribute("data-field-gap")).toBe("$
|
|
291
|
+
expect(section?.getAttribute("data-field-gap")).toBe("$4");
|
|
291
292
|
expect(stack?.getAttribute("data-section-gap")).toBe("$5");
|
|
292
293
|
});
|
|
293
294
|
|
package/src/fieldLayout.spec.tsx
CHANGED
|
@@ -266,7 +266,7 @@ describe("FieldLayout banned-error-word DEV warn", () => {
|
|
|
266
266
|
});
|
|
267
267
|
|
|
268
268
|
describe("FieldLayout design-law (MPO-60)", () => {
|
|
269
|
-
it("paints the label at weight
|
|
269
|
+
it("paints the label role at weight 500 (LC-152)", () => {
|
|
270
270
|
const { container } = renderWithProviders(
|
|
271
271
|
<FieldLayout id="w" label="Name">
|
|
272
272
|
<TamaguiInput id="w" />
|
|
@@ -275,7 +275,7 @@ describe("FieldLayout design-law (MPO-60)", () => {
|
|
|
275
275
|
const label = container.querySelector("label") as HTMLElement;
|
|
276
276
|
expect(label).toBeTruthy();
|
|
277
277
|
const weight = label.style.fontWeight || getComputedStyle(label).fontWeight;
|
|
278
|
-
expect(
|
|
278
|
+
expect(String(weight)).toBe("500");
|
|
279
279
|
});
|
|
280
280
|
|
|
281
281
|
it("does not pass a control-height sizeToken to the label (LC-73)", () => {
|
|
@@ -323,12 +323,12 @@ describe("FieldLayout design-law (MPO-60)", () => {
|
|
|
323
323
|
});
|
|
324
324
|
});
|
|
325
325
|
|
|
326
|
-
describe("label
|
|
326
|
+
describe("label role stop and weight knob (LC-152)", () => {
|
|
327
327
|
for (const [fontWeight, expected] of [
|
|
328
|
-
["regular", "
|
|
328
|
+
["regular", "500"],
|
|
329
329
|
["bold", "700"],
|
|
330
330
|
] as const) {
|
|
331
|
-
it(`uses
|
|
331
|
+
it(`uses the label role $2 (13px) and ${fontWeight} weight`, () => {
|
|
332
332
|
const { container } = renderWithProviders(
|
|
333
333
|
<TamaguiProvider config={bodyConfig} defaultTheme="light">
|
|
334
334
|
<Preset overrides={{ fontWeight }}>
|
|
@@ -340,8 +340,8 @@ describe("label body stop and weight knob", () => {
|
|
|
340
340
|
{ tamagui: false },
|
|
341
341
|
);
|
|
342
342
|
const label = container.querySelector("label")!;
|
|
343
|
-
expect(label.className).toContain("_fos-f-size-
|
|
344
|
-
expect(getComputedStyle(label).fontSize).toBe("
|
|
343
|
+
expect(label.className).toContain("_fos-f-size-2");
|
|
344
|
+
expect(getComputedStyle(label).fontSize).toBe("13px");
|
|
345
345
|
expect(getComputedStyle(label).fontWeight).toBe(expected);
|
|
346
346
|
});
|
|
347
347
|
}
|
|
@@ -320,6 +320,27 @@ describe("Progress", () => {
|
|
|
320
320
|
expect(radiusAtoms).not.toContain("_btlr-100000px");
|
|
321
321
|
});
|
|
322
322
|
|
|
323
|
+
it("rounds the fill's leading end at large and full, where the rail is already a capsule (LC-132)", () => {
|
|
324
|
+
const fillRadiusAtoms = (borderRadius: "medium" | "large" | "full") => {
|
|
325
|
+
const { container, unmount } = renderWithProviders(
|
|
326
|
+
<Preset overrides={{ borderRadius }}>
|
|
327
|
+
<Progress label="Fill end" value={50} />
|
|
328
|
+
</Preset>,
|
|
329
|
+
);
|
|
330
|
+
const atoms = String(getIndicator(container)?.className || "")
|
|
331
|
+
.split(" ")
|
|
332
|
+
.filter((c) => c.startsWith("_bbrr-"));
|
|
333
|
+
unmount();
|
|
334
|
+
return atoms;
|
|
335
|
+
};
|
|
336
|
+
const medium = fillRadiusAtoms("medium");
|
|
337
|
+
const large = fillRadiusAtoms("large");
|
|
338
|
+
const full = fillRadiusAtoms("full");
|
|
339
|
+
expect(medium).toContain("_bbrr-t-radius-0");
|
|
340
|
+
expect(large).toContain("_bbrr-t-radius-2");
|
|
341
|
+
expect(full).toContain("_bbrr-t-radius-12");
|
|
342
|
+
});
|
|
343
|
+
|
|
323
344
|
it("skeleton track height matches the live 0.25× size formula, not a 6px leftover", () => {
|
|
324
345
|
const live = renderWithProviders(<Progress label="Upload" value={50} />);
|
|
325
346
|
const bar = live.container.querySelector("[role='progressbar']") as HTMLElement;
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { transitionOrInstant } from "../../shared/instantMotion";
|
|
2
2
|
import type { ReactNode } from "react";
|
|
3
3
|
import type { AnyFormApi } from "../../types";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
Intent,
|
|
6
|
+
radiusStopFromToken,
|
|
7
|
+
railFillRadius,
|
|
8
|
+
transitionProps,
|
|
9
|
+
type MotionRole,
|
|
10
|
+
} from "@multiplatform.one/theme";
|
|
5
11
|
import type { KnobProps } from "@multiplatform.one/theme";
|
|
6
12
|
import { getSize } from "@tamagui/get-token";
|
|
7
13
|
import type { LabelProps, SizeTokens } from "tamagui";
|
|
@@ -86,11 +92,18 @@ function indicatorMotion(role: MotionRole) {
|
|
|
86
92
|
* `ProgressIndicator` component sub-theme. Capturing here keeps the hue
|
|
87
93
|
* scope explicit. useTheme() subscribes, so scheme changes stay live.
|
|
88
94
|
*/
|
|
89
|
-
function HueFillIndicator({
|
|
95
|
+
function HueFillIndicator({
|
|
96
|
+
motion,
|
|
97
|
+
radius,
|
|
98
|
+
}: {
|
|
99
|
+
motion: MotionRole;
|
|
100
|
+
radius: ReturnType<typeof railFillRadius>;
|
|
101
|
+
}) {
|
|
90
102
|
const theme = useTheme();
|
|
91
103
|
const fill = theme.color9?.val;
|
|
92
104
|
return (
|
|
93
105
|
<ProgressIndicator
|
|
106
|
+
borderRadius={radius}
|
|
94
107
|
{...(fill ? { backgroundColor: fill as any } : undefined)}
|
|
95
108
|
{...indicatorMotion(motion)}
|
|
96
109
|
/>
|
|
@@ -176,6 +189,7 @@ function ProgressTrack({
|
|
|
176
189
|
const trackSize = size ?? sizeToken;
|
|
177
190
|
const percent = Math.round((progressValue / max) * 100);
|
|
178
191
|
const motion = indicatorMotion(knobProps.motion.slide);
|
|
192
|
+
const fillRadius = railFillRadius(radiusStopFromToken(knobProps.borderRadius.borderRadius));
|
|
179
193
|
const name = typeof label === "string" && label ? label : t("Progress");
|
|
180
194
|
|
|
181
195
|
const progressElement = (
|
|
@@ -203,12 +217,13 @@ function ProgressTrack({
|
|
|
203
217
|
>
|
|
204
218
|
{intent && intent !== "accent" ? (
|
|
205
219
|
<Intent name={intent}>
|
|
206
|
-
<HueFillIndicator motion={knobProps.motion.slide} />
|
|
220
|
+
<HueFillIndicator motion={knobProps.motion.slide} radius={fillRadius} />
|
|
207
221
|
</Intent>
|
|
208
222
|
) : (
|
|
209
223
|
// Accent fills use the mark channel without a solid sub-theme scope.
|
|
210
224
|
// The default fill must hold 3:1 against both the track and page (DF-06).
|
|
211
225
|
<ProgressIndicator
|
|
226
|
+
borderRadius={fillRadius}
|
|
212
227
|
backgroundColor={
|
|
213
228
|
intent === "accent" ? formSelectedColors.mark : formControlColors.boundary
|
|
214
229
|
}
|
package/src/formSpacing.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Fallback form rhythm tokens (DG-FORM-06). Prefer `knobProps.
|
|
2
|
+
* Fallback form rhythm tokens (DG-FORM-06). Prefer `knobProps.fieldGap` /
|
|
3
3
|
* `knobProps.gapLg` (the spacing roles) at the layout primitives. These are
|
|
4
|
-
* the roles' `$space` keys, not a size mapping.
|
|
4
|
+
* the roles' `$space` keys, not a size mapping; the field step is LC-154's.
|
|
5
5
|
*/
|
|
6
|
-
export const formFieldGap = "$
|
|
6
|
+
export const formFieldGap = "$4" as const;
|
|
7
7
|
export const formSectionGap = "$8" as const;
|
|
8
8
|
|
|
9
9
|
/** Default readable form width (DG-FORM-08 ~480–600px). */
|
package/types/Button/index.d.ts
CHANGED
|
@@ -128,8 +128,15 @@ export interface ButtonProps extends Omit<TamaguiButtonProps, "form" | "icon" |
|
|
|
128
128
|
* that paints a frame: the frame is what aligns there.
|
|
129
129
|
*/
|
|
130
130
|
edge?: "start" | "end";
|
|
131
|
+
/**
|
|
132
|
+
* LC-145: a chromeless bar button's label and glyphs take the host's
|
|
133
|
+
* identity ink (`useIdentityInkOnSurface`), the iOS bar-button tint: the
|
|
134
|
+
* theme's hue, or the primary ink when the theme has none. No effect on a
|
|
135
|
+
* button that paints a frame, while selected, or disabled.
|
|
136
|
+
*/
|
|
137
|
+
accentInk?: boolean;
|
|
131
138
|
}
|
|
132
|
-
export declare function Button({ children, action, form: formProp, loading, accent, error, warning, success, skeleton, outlined, disabled, theme, onPress, onKeyDown, tabIndex, icon, iconAfter, selected, nested, circular, chromeless, edge, verb, noun, actionRole, disabledReason, disabledReasonPlacement, sizeRecipeEscape, recipeFamily, height: heightProp, paddingHorizontal: paddingHorizontalProp, ...props }: ButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
139
|
+
export declare function Button({ children, action, form: formProp, loading, accent, error, warning, success, skeleton, outlined, disabled, theme, onPress, onKeyDown, tabIndex, icon, iconAfter, selected, nested, circular, chromeless, edge, accentInk, verb, noun, actionRole, disabledReason, disabledReasonPlacement, sizeRecipeEscape, recipeFamily, height: heightProp, paddingHorizontal: paddingHorizontalProp, ...props }: ButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
133
140
|
export declare namespace Button {
|
|
134
141
|
var Icon: (props: {
|
|
135
142
|
children: React.ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Button/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EAQL,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Button/index.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fields/Progress/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fields/Progress/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAU9C,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAEL,KAAK,aAAa,IAAI,oBAAoB,EAQ3C,MAAM,SAAS,CAAC;AA8BjB,oEAAoE;AACpE,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;AA0DxE,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,UAAU,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,SAAS,GAAG,KAAK,CAAC,CAAC;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IAClC,aAAa,CAAC,EAAE,IAAI,CAAC,oBAAoB,EAAE,OAAO,GAAG,KAAK,GAAG,IAAI,GAAG,UAAU,CAAC,CAAC;IAChF;;;;;OAKG;IACH,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AA0HD,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,IAAI,EAAE,QAAQ,EACd,UAAU,EACV,KAAK,EACL,UAAU,EACV,UAAU,EACV,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,EAAE,EAAE,MAAM,EACV,KAAK,EACL,YAAY,EACZ,GAAG,EACH,QAAQ,EAAE,SAAS,EACnB,MAAM,EACN,aAAa,EACb,MAAM,EACN,QAAQ,EACR,SAAS,EAAE,aAAa,GACzB,EAAE,aAAa,2CAuGf"}
|
package/types/formSpacing.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Fallback form rhythm tokens (DG-FORM-06). Prefer `knobProps.
|
|
2
|
+
* Fallback form rhythm tokens (DG-FORM-06). Prefer `knobProps.fieldGap` /
|
|
3
3
|
* `knobProps.gapLg` (the spacing roles) at the layout primitives. These are
|
|
4
|
-
* the roles' `$space` keys, not a size mapping.
|
|
4
|
+
* the roles' `$space` keys, not a size mapping; the field step is LC-154's.
|
|
5
5
|
*/
|
|
6
|
-
export declare const formFieldGap: "$
|
|
6
|
+
export declare const formFieldGap: "$4";
|
|
7
7
|
export declare const formSectionGap: "$8";
|
|
8
8
|
/** Default readable form width (DG-FORM-08 ~480–600px). */
|
|
9
9
|
export declare const formReadableMaxWidth = 560;
|