@multiplatform.one/theme 7.63.3 → 7.64.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/package.json +5 -5
- package/src/keyboardFocusRing.openFocus.spec.ts +96 -0
- package/src/keyboardFocusRing.ts +38 -1
- package/src/theme/createThemes.ts +57 -6
- package/src/theme/focusState.spec.ts +15 -15
- package/src/theme/focusState.ts +18 -42
- package/src/theme/hairlineToken.spec.ts +2 -2
- package/src/theme/motion.spec.ts +137 -0
- package/src/theme/motion.ts +20 -7
- package/src/theme/mpo19Proof.spec.ts +3 -3
- package/src/theme/overlaySurfaces.tsx +9 -4
- package/src/theme/recipes.ts +10 -1
- package/src/theme/resolveKnobs.spec.ts +48 -11
- package/src/theme/resolveKnobs.ts +46 -10
- package/src/theme/transitionProps.native.ts +18 -1
- package/src/theme/transitionProps.spec.ts +2 -2
- package/src/theme/transitionProps.ts +11 -1
- package/types/keyboardFocusRing.d.ts +11 -0
- package/types/keyboardFocusRing.d.ts.map +1 -1
- package/types/theme/createThemes.d.ts.map +1 -1
- package/types/theme/focusState.d.ts +17 -41
- package/types/theme/focusState.d.ts.map +1 -1
- package/types/theme/motion.d.ts +2 -0
- package/types/theme/motion.d.ts.map +1 -1
- package/types/theme/overlaySurfaces.d.ts.map +1 -1
- package/types/theme/recipes.d.ts +9 -1
- package/types/theme/recipes.d.ts.map +1 -1
- package/types/theme/resolveKnobs.d.ts +5 -0
- package/types/theme/resolveKnobs.d.ts.map +1 -1
- package/types/theme/transitionProps.native.d.ts.map +1 -1
package/src/theme/motion.ts
CHANGED
|
@@ -9,9 +9,12 @@ export type MotionRoleName = "control" | "overlay" | "scrim" | "reveal" | "slide
|
|
|
9
9
|
|
|
10
10
|
export interface MotionRole {
|
|
11
11
|
transition: TransitionProp | undefined;
|
|
12
|
+
exit?: TransitionProp | undefined;
|
|
12
13
|
animateOnly: readonly string[];
|
|
13
14
|
}
|
|
14
15
|
|
|
16
|
+
export const motionExitFactor = 2 / 3;
|
|
17
|
+
|
|
15
18
|
export const motionRoleProperties = {
|
|
16
19
|
control: ["backgroundColor", "borderColor", "color", "opacity", "transform"],
|
|
17
20
|
overlay: ["opacity", "transform"],
|
|
@@ -22,8 +25,8 @@ export const motionRoleProperties = {
|
|
|
22
25
|
|
|
23
26
|
const nonBouncyStops = motionStops.filter((stop) => stop !== "superBouncy" && stop !== "bouncy");
|
|
24
27
|
|
|
25
|
-
function nearestStop(duration: number): MotionStop {
|
|
26
|
-
return
|
|
28
|
+
function nearestStop(duration: number, stops: readonly MotionStop[] = nonBouncyStops): MotionStop {
|
|
29
|
+
return stops.reduce((nearest, candidate) =>
|
|
27
30
|
Math.abs(animationDurations[candidate] - duration) <
|
|
28
31
|
Math.abs(animationDurations[nearest] - duration)
|
|
29
32
|
? candidate
|
|
@@ -31,18 +34,28 @@ function nearestStop(duration: number): MotionStop {
|
|
|
31
34
|
);
|
|
32
35
|
}
|
|
33
36
|
|
|
37
|
+
function exitStop(enter: MotionStop): MotionStop {
|
|
38
|
+
const enterMs = animationDurations[enter];
|
|
39
|
+
const shorter = nonBouncyStops.filter((stop) => animationDurations[stop] < enterMs);
|
|
40
|
+
return shorter.length === 0 ? enter : nearestStop(enterMs * motionExitFactor, shorter);
|
|
41
|
+
}
|
|
42
|
+
|
|
34
43
|
export function motionFor(stop: Animation): Record<MotionRoleName, MotionRole> {
|
|
35
44
|
const transition = stop === "none" ? undefined : stop;
|
|
36
45
|
const duration = motionDurationMs(transition);
|
|
37
|
-
const role = (name: MotionRoleName, factor: number): MotionRole =>
|
|
38
|
-
|
|
46
|
+
const role = (name: MotionRoleName, factor: number): MotionRole => {
|
|
47
|
+
const enter =
|
|
39
48
|
transition === undefined
|
|
40
49
|
? undefined
|
|
41
50
|
: name === "control"
|
|
42
51
|
? transition
|
|
43
|
-
: nearestStop(duration * factor)
|
|
44
|
-
|
|
45
|
-
|
|
52
|
+
: nearestStop(duration * factor);
|
|
53
|
+
return {
|
|
54
|
+
transition: enter,
|
|
55
|
+
exit: enter === undefined ? undefined : exitStop(enter),
|
|
56
|
+
animateOnly: motionRoleProperties[name],
|
|
57
|
+
};
|
|
58
|
+
};
|
|
46
59
|
return {
|
|
47
60
|
control: role("control", 1),
|
|
48
61
|
overlay: role("overlay", 0.8),
|
|
@@ -208,9 +208,9 @@ describe("MPO-19 X5/X6 — surfaces address semantic tokens, so sub-themes work"
|
|
|
208
208
|
});
|
|
209
209
|
|
|
210
210
|
describe("MPO-19 X7 — the focus ring is inset only where a clip demands it", () => {
|
|
211
|
-
it("the default sits
|
|
212
|
-
expect(FOCUS_VISIBLE_RING.outlineOffset).toBe(
|
|
213
|
-
expect(ensureFocusVisibleRing().outlineOffset).toBe(
|
|
211
|
+
it("the default sits 2px clear of the border box (FZ-7944 round 2)", () => {
|
|
212
|
+
expect(FOCUS_VISIBLE_RING.outlineOffset).toBe(2);
|
|
213
|
+
expect(ensureFocusVisibleRing().outlineOffset).toBe(2);
|
|
214
214
|
});
|
|
215
215
|
|
|
216
216
|
it("the ring shape itself is unchanged — 2px solid, non-removable", () => {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { focusOnOpen, wasKeyboardFocus } from "../keyboardFocusRing";
|
|
1
2
|
import { transitionProps } from "./transitionProps";
|
|
2
3
|
import { Surface } from "./Surface";
|
|
3
4
|
import { useResolvedKnobs } from "./useResolvedKnobs";
|
|
@@ -40,7 +41,9 @@ const overlayFrameFocusStyle = {
|
|
|
40
41
|
// tamagui's deferred path still runs. Dialog content sits in a native
|
|
41
42
|
// <dialog> whose show() puts focus inside before the check in browsers,
|
|
42
43
|
// so there FocusScope never calls the handler; useDialogShowFocus does
|
|
43
|
-
// when show() left focus on something that is not a tab stop (MPO-470)
|
|
44
|
+
// when show() left focus on something that is not a tab stop (MPO-470), or
|
|
45
|
+
// on any control after a non-keyboard open, which Chromium would ring
|
|
46
|
+
// (LC-71, FZ-7944).
|
|
44
47
|
|
|
45
48
|
function isTabbableWithin(node: HTMLElement, container: HTMLElement): boolean {
|
|
46
49
|
if (node.tabIndex < 0 || node.hidden || node.tagName === "A") return false;
|
|
@@ -67,8 +70,10 @@ function focusFirstTabbableOnOpen(event: Event): void {
|
|
|
67
70
|
);
|
|
68
71
|
if (!first) return;
|
|
69
72
|
event.preventDefault();
|
|
70
|
-
|
|
71
|
-
if (typeof HTMLInputElement !== "undefined" &&
|
|
73
|
+
const focused = focusOnOpen(first, container);
|
|
74
|
+
if (typeof HTMLInputElement !== "undefined" && focused instanceof HTMLInputElement) {
|
|
75
|
+
focused.select();
|
|
76
|
+
}
|
|
72
77
|
}
|
|
73
78
|
|
|
74
79
|
type OpenAutoFocus = (event: Event) => void;
|
|
@@ -100,7 +105,7 @@ function useDialogShowFocus(onOpenAutoFocus: OpenAutoFocus): void {
|
|
|
100
105
|
const content = document.getElementById(contentId);
|
|
101
106
|
const focused = document.activeElement;
|
|
102
107
|
if (!content || typeof HTMLElement === "undefined" || !(focused instanceof HTMLElement)) return;
|
|
103
|
-
if (!content.contains(focused) || focused.tabIndex >= 0) return;
|
|
108
|
+
if (!content.contains(focused) || (focused.tabIndex >= 0 && wasKeyboardFocus())) return;
|
|
104
109
|
content.addEventListener(DIALOG_SHOW_FOCUS_EVENT, onOpenAutoFocus, { once: true });
|
|
105
110
|
content.dispatchEvent(new CustomEvent(DIALOG_SHOW_FOCUS_EVENT, { cancelable: true }));
|
|
106
111
|
}, [open, contentId]);
|
package/src/theme/recipes.ts
CHANGED
|
@@ -69,6 +69,15 @@ export interface ElevationChromeProps extends ElevationPaintProps {
|
|
|
69
69
|
elevation?: number;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
/**
|
|
73
|
+
* A content card's lift (LC-151): an explicit shadow plus Android dp under
|
|
74
|
+
* `elevationAndroid`. Not `elevation`: on native that key is Tamagui's stack
|
|
75
|
+
* variant, which replaces the shadow with its own size-formula one.
|
|
76
|
+
*/
|
|
77
|
+
export interface CardLiftProps extends ElevationPaintProps {
|
|
78
|
+
elevationAndroid?: number;
|
|
79
|
+
}
|
|
80
|
+
|
|
72
81
|
// ── Disabled state recipe (LC-40 DISABLED-VISIBLE) ───────────────────────
|
|
73
82
|
|
|
74
83
|
/** Text-bearing control chrome (Button, Chip, Input.Box): muted fill/border, no opacity. */
|
|
@@ -228,7 +237,7 @@ export interface KnobProps {
|
|
|
228
237
|
borderWidth?: number;
|
|
229
238
|
borderRadius: string | number;
|
|
230
239
|
padding: string;
|
|
231
|
-
} &
|
|
240
|
+
} & CardLiftProps &
|
|
232
241
|
CornerSmoothingCarrier;
|
|
233
242
|
/** Elevated/overlay tier (popovers, dropdowns): border + elevation. */
|
|
234
243
|
elevatedSurface: {
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
resolveKnobs,
|
|
31
31
|
resolvePageTitleScale,
|
|
32
32
|
spacingRoles,
|
|
33
|
+
cardLift,
|
|
33
34
|
sizedElevation,
|
|
34
35
|
} from "./resolveKnobs";
|
|
35
36
|
import { getActiveScaleTokens, setActiveScaleTokens } from "./scale/activeScale";
|
|
@@ -314,7 +315,7 @@ describe("resolveKnobs", () => {
|
|
|
314
315
|
scheme === "dark" ? "$color4" : "$background",
|
|
315
316
|
);
|
|
316
317
|
expect(knobProps.elevatedSurface.borderColor).toBe(
|
|
317
|
-
scheme === "dark" ? "
|
|
318
|
+
scheme === "dark" ? "transparent" : "$borderColor",
|
|
318
319
|
);
|
|
319
320
|
if (!key) {
|
|
320
321
|
expect(knobProps.elevationChrome).toEqual({});
|
|
@@ -362,7 +363,7 @@ describe("resolveKnobs", () => {
|
|
|
362
363
|
});
|
|
363
364
|
|
|
364
365
|
describe("elevation knob (native)", () => {
|
|
365
|
-
it("returns active scale numbers
|
|
366
|
+
it("returns active scale numbers, and every shadow carries its alpha as shadowOpacity on an opaque ink", async () => {
|
|
366
367
|
vi.resetModules();
|
|
367
368
|
vi.doMock("@multiplatform.one/platform", () => ({
|
|
368
369
|
isWeb: false,
|
|
@@ -407,15 +408,33 @@ describe("resolveKnobs", () => {
|
|
|
407
408
|
if (key) {
|
|
408
409
|
const metrics = sizedElevation(active.getActiveScaleTokens().size[key]);
|
|
409
410
|
expect(knobProps.elevationChrome).toEqual({
|
|
410
|
-
shadowColor: "
|
|
411
|
-
shadowOpacity:
|
|
411
|
+
shadowColor: "rgb(0,0,0)",
|
|
412
|
+
shadowOpacity: 0.12,
|
|
412
413
|
shadowOffset: { width: 0, height: metrics.offsetY },
|
|
413
414
|
shadowRadius: metrics.radius,
|
|
414
415
|
elevation: metrics.android,
|
|
415
416
|
});
|
|
416
417
|
} else expect(knobProps.elevationChrome).toEqual({});
|
|
417
418
|
expect(knobProps.thumbShadow.style).toBeUndefined();
|
|
418
|
-
expect(knobProps.thumbShadow.
|
|
419
|
+
expect(knobProps.thumbShadow.shadowOpacity).toBe(0.12);
|
|
420
|
+
const card = knobProps.cardSurface;
|
|
421
|
+
if (scheme === "dark" || stop === "none") {
|
|
422
|
+
expect(card).not.toHaveProperty("shadowColor");
|
|
423
|
+
} else {
|
|
424
|
+
expect(card.shadowColor).toBe("rgb(0,0,0)");
|
|
425
|
+
expect(card.shadowOpacity).toBe(0.08);
|
|
426
|
+
expect(card.style).toBeUndefined();
|
|
427
|
+
}
|
|
428
|
+
expect(knobProps.featureSurface.shadowOpacity).toBeLessThanOrEqual(0.08);
|
|
429
|
+
for (const fragment of [
|
|
430
|
+
knobProps.elevationChrome,
|
|
431
|
+
knobProps.thumbShadow,
|
|
432
|
+
card,
|
|
433
|
+
knobProps.elevatedSurface,
|
|
434
|
+
knobProps.featureSurface,
|
|
435
|
+
]) {
|
|
436
|
+
if ("shadowOpacity" in fragment) expect(fragment.shadowOpacity).toBeLessThan(0.5);
|
|
437
|
+
}
|
|
419
438
|
}
|
|
420
439
|
}
|
|
421
440
|
}
|
|
@@ -668,23 +687,41 @@ describe("resolveKnobs", () => {
|
|
|
668
687
|
// ── surface tiers ─────────────────────────────────────────
|
|
669
688
|
|
|
670
689
|
describe("surface tier recipes", () => {
|
|
671
|
-
it("cardSurface = grouped fill + hairline edge + a
|
|
690
|
+
it("cardSurface = grouped fill + hairline edge + a natural lift (LC-151)", () => {
|
|
672
691
|
const { knobProps } = resolveKnobs(defaultKnobs);
|
|
673
|
-
const { offsetY, radius, android } =
|
|
692
|
+
const { offsetY, radius, android } = cardLift(getActiveScaleTokens().size["$0.25"]);
|
|
674
693
|
expect(knobProps.cardSurface).toEqual({
|
|
675
694
|
backgroundColor: "$background",
|
|
676
695
|
borderColor: edgeColorAt("$borderColor", "small"),
|
|
677
696
|
borderWidth: hairlineBorderWidth,
|
|
678
697
|
borderRadius: "$6",
|
|
679
698
|
padding: "$4",
|
|
680
|
-
shadowColor: "$
|
|
699
|
+
shadowColor: "$shadow2",
|
|
681
700
|
shadowOffset: { width: 0, height: offsetY },
|
|
682
701
|
shadowOpacity: 1,
|
|
683
702
|
shadowRadius: radius,
|
|
684
|
-
|
|
685
|
-
style: {
|
|
703
|
+
elevationAndroid: android,
|
|
704
|
+
style: {
|
|
705
|
+
boxShadow: `0px 1px 2px var(--shadow1), 0px ${offsetY}px ${radius * 2}px var(--shadow2)`,
|
|
706
|
+
},
|
|
686
707
|
});
|
|
687
|
-
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
it("card lift: the blur is three times the drop, and no `elevation` key for Tamagui's variant to replace it", () => {
|
|
711
|
+
for (const elevation of ["small", "medium", "large"] as const) {
|
|
712
|
+
const card = resolveKnobs(knobsWith({ elevation })).knobProps.cardSurface;
|
|
713
|
+
expect(card.shadowRadius! / card.shadowOffset!.height, elevation).toBeGreaterThanOrEqual(
|
|
714
|
+
2.5,
|
|
715
|
+
);
|
|
716
|
+
expect(card.shadowRadius! / card.shadowOffset!.height, elevation).toBeLessThanOrEqual(3.5);
|
|
717
|
+
expect(card, elevation).not.toHaveProperty("elevation");
|
|
718
|
+
}
|
|
719
|
+
});
|
|
720
|
+
|
|
721
|
+
it("card lift is off in dark: the lighter card fill carries the step", () => {
|
|
722
|
+
const card = resolveKnobs(defaultKnobs, undefined, "dark").knobProps.cardSurface;
|
|
723
|
+
expect(card).not.toHaveProperty("shadowColor");
|
|
724
|
+
expect(card).not.toHaveProperty("elevationAndroid");
|
|
688
725
|
});
|
|
689
726
|
|
|
690
727
|
it("cardSurface lift is lower than every overlay stop and gone at elevation none", () => {
|
|
@@ -21,6 +21,7 @@ import { SIZE_KEYS, type SizeKey } from "./scale/scaleInputs";
|
|
|
21
21
|
import type {
|
|
22
22
|
ControlStateProps,
|
|
23
23
|
DisabledRecipe,
|
|
24
|
+
CardLiftProps,
|
|
24
25
|
ElevationChromeProps,
|
|
25
26
|
ElevationPaintProps,
|
|
26
27
|
ElevationStateProps,
|
|
@@ -395,6 +396,15 @@ export function sizedElevation(px: number): { offsetY: number; radius: number; a
|
|
|
395
396
|
return { offsetY, radius: Math.round(px / 2 + 2), android: 2 * offsetY };
|
|
396
397
|
}
|
|
397
398
|
|
|
399
|
+
// Native: Tamagui's normalizeShadow repaints shadowColor at full alpha and
|
|
400
|
+
// keeps only shadowOpacity, so a translucent shadow token at shadowOpacity 1
|
|
401
|
+
// draws solid black. Native gets an opaque ink and the token's alpha.
|
|
402
|
+
function shadowInk(token: string, alpha: number): { shadowColor: string; shadowOpacity: number } {
|
|
403
|
+
return isWeb
|
|
404
|
+
? { shadowColor: token, shadowOpacity: 1 }
|
|
405
|
+
: { shadowColor: "rgb(0,0,0)", shadowOpacity: alpha };
|
|
406
|
+
}
|
|
407
|
+
|
|
398
408
|
function platformElevation(key: SizeKey | undefined): string | number | undefined {
|
|
399
409
|
return key && (isWeb ? key : getActiveScaleTokens().size[key]);
|
|
400
410
|
}
|
|
@@ -403,14 +413,41 @@ function elevationPaint(key: SizeKey | undefined): ElevationPaintProps {
|
|
|
403
413
|
if (!key) return {};
|
|
404
414
|
const { offsetY, radius } = sizedElevation(getActiveScaleTokens().size[key]);
|
|
405
415
|
return {
|
|
406
|
-
|
|
416
|
+
...shadowInk("$shadowColor", 0.12),
|
|
407
417
|
shadowOffset: { width: 0, height: offsetY },
|
|
408
|
-
shadowOpacity: 1,
|
|
409
418
|
shadowRadius: radius,
|
|
410
419
|
...(isWeb ? { style: { boxShadow: `0px ${offsetY}px ${radius}px var(--shadowColor)` } } : {}),
|
|
411
420
|
};
|
|
412
421
|
}
|
|
413
422
|
|
|
423
|
+
// LC-151 card lift, a natural shadow: the blur three times the drop, a faint
|
|
424
|
+
// ink, and on web a tight contact layer under the ambient one. Dark lets the
|
|
425
|
+
// card's lighter fill carry the step; a black shadow on a black page reads as
|
|
426
|
+
// a smudge.
|
|
427
|
+
export function cardLift(px: number): { offsetY: number; radius: number; android: number } {
|
|
428
|
+
const radius = Math.round(8 + px * 2);
|
|
429
|
+
const offsetY = Math.round(radius / 3);
|
|
430
|
+
return { offsetY, radius, android: Math.max(1, Math.round(offsetY / 2)) };
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
function cardLiftFor(key: SizeKey | undefined, scheme: ColorScheme): CardLiftProps {
|
|
434
|
+
if (!key || scheme === "dark") return {};
|
|
435
|
+
const { offsetY, radius, android } = cardLift(getActiveScaleTokens().size[key]);
|
|
436
|
+
return {
|
|
437
|
+
...shadowInk("$shadow2", 0.08),
|
|
438
|
+
shadowOffset: { width: 0, height: offsetY },
|
|
439
|
+
shadowRadius: radius,
|
|
440
|
+
elevationAndroid: android,
|
|
441
|
+
...(isWeb
|
|
442
|
+
? {
|
|
443
|
+
style: {
|
|
444
|
+
boxShadow: `0px 1px 2px var(--shadow1), 0px ${offsetY}px ${radius * 2}px var(--shadow2)`,
|
|
445
|
+
},
|
|
446
|
+
}
|
|
447
|
+
: {}),
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
|
|
414
451
|
function elevationChromeFor(key: SizeKey | undefined): ElevationChromeProps {
|
|
415
452
|
if (!key) return {};
|
|
416
453
|
return {
|
|
@@ -419,10 +456,10 @@ function elevationChromeFor(key: SizeKey | undefined): ElevationChromeProps {
|
|
|
419
456
|
};
|
|
420
457
|
}
|
|
421
458
|
|
|
422
|
-
// v5's surface2 template
|
|
423
|
-
//
|
|
424
|
-
//
|
|
425
|
-
const surface2 = { fill: "$color4"
|
|
459
|
+
// v5's surface2 template step: the fill two palette steps above the base
|
|
460
|
+
// `$background` (color2), one above Card's surface1. A dark overlay separates
|
|
461
|
+
// by this lighter fill and its shadow, with no light edge (HIG, FZ-7944).
|
|
462
|
+
const surface2 = { fill: "$color4" } as const;
|
|
426
463
|
|
|
427
464
|
// `$textMuted` is the theme's secondary ink (LC-152): the most muted ramp
|
|
428
465
|
// step that clears 7:1 on the page and every card tier in its own scheme. A
|
|
@@ -750,7 +787,7 @@ export function resolveKnobs(
|
|
|
750
787
|
borderWidth: knobs.borderWidth === "none" ? 0 : borderWidthMap.small,
|
|
751
788
|
borderRadius: containerRadiusValue,
|
|
752
789
|
padding: paddingToken,
|
|
753
|
-
...
|
|
790
|
+
...cardLiftFor(cardElevationMap[knobs.elevation], scheme),
|
|
754
791
|
...containerSmoothing,
|
|
755
792
|
},
|
|
756
793
|
elevatedSurface: painted
|
|
@@ -764,7 +801,7 @@ export function resolveKnobs(
|
|
|
764
801
|
}
|
|
765
802
|
: {
|
|
766
803
|
backgroundColor: scheme === "dark" ? surface2.fill : "$background",
|
|
767
|
-
borderColor:
|
|
804
|
+
borderColor: scheme === "dark" ? "transparent" : edge("$borderColor", borderWidthValue),
|
|
768
805
|
borderWidth: borderWidthValue,
|
|
769
806
|
borderRadius: radiusToken,
|
|
770
807
|
elevation: platformElevation(overlayElevationToken),
|
|
@@ -777,9 +814,8 @@ export function resolveKnobs(
|
|
|
777
814
|
padding: spacingRoles.featurePadding,
|
|
778
815
|
// Bento marketing/auth card shadow: ~0px 9px 12px rgba(0,0,0,0.02) —
|
|
779
816
|
// softer/wider than any elevationMap token, so explicit shadow props.
|
|
780
|
-
|
|
817
|
+
...shadowInk("rgba(0,0,0,0.02)", 0.02),
|
|
781
818
|
shadowOffset: { width: 0, height: 9 },
|
|
782
|
-
shadowOpacity: 1,
|
|
783
819
|
shadowRadius: 12,
|
|
784
820
|
...containerSmoothing,
|
|
785
821
|
},
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { MotionRole } from "./motion";
|
|
2
2
|
import type { TransitionProp } from "tamagui";
|
|
3
|
+
import { animationConfig as nativeAnimationConfig } from "./animations/reactNative";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Native twin of `transitionProps.ts`.
|
|
@@ -23,12 +24,26 @@ export function transitionProps(
|
|
|
23
24
|
const properties = [...role.animateOnly, ...extra].flatMap(
|
|
24
25
|
(property) => nativeLonghands[property] ?? [property],
|
|
25
26
|
);
|
|
27
|
+
if (typeof transition !== "string") return { transition, animateOnly: properties };
|
|
28
|
+
const exit = typeof role.exit === "string" && role.exit !== transition ? role.exit : undefined;
|
|
29
|
+
const clamp = isSpring(transition) && !presetBounce.has(transition);
|
|
30
|
+
if (!exit && !clamp) return { transition, animateOnly: properties };
|
|
26
31
|
return {
|
|
27
|
-
transition
|
|
32
|
+
transition: [
|
|
33
|
+
transition,
|
|
34
|
+
{ ...(clamp ? { overshootClamping: true } : {}), ...(exit ? { exit } : {}) },
|
|
35
|
+
],
|
|
28
36
|
animateOnly: properties,
|
|
29
37
|
};
|
|
30
38
|
}
|
|
31
39
|
|
|
40
|
+
function isSpring(stop: string): boolean {
|
|
41
|
+
const config = nativeAnimationConfig[stop as keyof typeof nativeAnimationConfig] as
|
|
42
|
+
| { type?: string }
|
|
43
|
+
| undefined;
|
|
44
|
+
return config !== undefined && config.type !== "timing";
|
|
45
|
+
}
|
|
46
|
+
|
|
32
47
|
/**
|
|
33
48
|
* FZ-7919: tamagui expands `borderColor` into its four sides before the React
|
|
34
49
|
* Native driver sees the style, and the driver matches `animateOnly` by exact
|
|
@@ -36,6 +51,8 @@ export function transitionProps(
|
|
|
36
51
|
* (the bubbled focus of a field's text input) animated them. The animated
|
|
37
52
|
* copy outranked the static one and held the previous focus or theme colour.
|
|
38
53
|
*/
|
|
54
|
+
const presetBounce = new Set(["bouncy", "superBouncy"]);
|
|
55
|
+
|
|
39
56
|
const nativeLonghands: Record<string, readonly string[]> = {
|
|
40
57
|
borderColor: [
|
|
41
58
|
"borderColor",
|
|
@@ -24,7 +24,7 @@ describe("role property scopes", () => {
|
|
|
24
24
|
});
|
|
25
25
|
it("hyphenates the control scope and additional properties", () => {
|
|
26
26
|
expect(transitionProps(motionFor("quick").control, ["maxHeight", "left"])).toEqual({
|
|
27
|
-
transition: "quick",
|
|
27
|
+
transition: ["quick", { exit: "quickerLessBouncy" }],
|
|
28
28
|
animateOnly: [
|
|
29
29
|
"background-color",
|
|
30
30
|
"border-color",
|
|
@@ -41,7 +41,7 @@ describe("role property scopes", () => {
|
|
|
41
41
|
expect(nativeTransitionProps(undefined)).toEqual({});
|
|
42
42
|
expect(nativeTransitionProps("quick")).toEqual({ transition: "quick" });
|
|
43
43
|
expect(nativeTransitionProps(motionFor("quick").control, ["maxHeight"])).toEqual({
|
|
44
|
-
transition: "quick",
|
|
44
|
+
transition: ["quick", { overshootClamping: true, exit: "quickerLessBouncy" }],
|
|
45
45
|
animateOnly: [
|
|
46
46
|
"backgroundColor",
|
|
47
47
|
"borderColor",
|
|
@@ -22,13 +22,23 @@ export function transitionProps(
|
|
|
22
22
|
if (!isRole) return { transition };
|
|
23
23
|
const properties = [...role.animateOnly, ...extra];
|
|
24
24
|
return {
|
|
25
|
-
transition,
|
|
25
|
+
transition: withExit(transition, role.exit),
|
|
26
26
|
animateOnly: properties.map((property) =>
|
|
27
27
|
property.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`),
|
|
28
28
|
),
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
function withExit(
|
|
33
|
+
transition: TransitionProp | undefined,
|
|
34
|
+
exit: TransitionProp | undefined,
|
|
35
|
+
): TransitionProp | undefined {
|
|
36
|
+
if (typeof transition !== "string" || typeof exit !== "string" || exit === transition) {
|
|
37
|
+
return transition;
|
|
38
|
+
}
|
|
39
|
+
return [transition, { exit }];
|
|
40
|
+
}
|
|
41
|
+
|
|
32
42
|
function isMotionRole(value: MotionRole | TransitionProp | undefined): value is MotionRole {
|
|
33
43
|
return (
|
|
34
44
|
typeof value === "object" &&
|
|
@@ -22,6 +22,17 @@ export declare function ensureKeyboardModalityTracking(): void;
|
|
|
22
22
|
* false) and during SSR.
|
|
23
23
|
*/
|
|
24
24
|
export declare function wasKeyboardFocus(): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* An overlay's open focus (LC-71, FZ-7944). Only a keyboard open lands on a
|
|
27
|
+
* control and rings it. Any other open (pointer, touch, mounted open) lands on
|
|
28
|
+
* the frame, which paints no ring: Chromium ignores `focusVisible: false` and
|
|
29
|
+
* rings a control focused before any input. A mouse open still puts the caret
|
|
30
|
+
* in a first text field, which shows LC-133's border; a touch open does not,
|
|
31
|
+
* so the keyboard does not rise over a sheet the user only looked at. A frame
|
|
32
|
+
* without a tabindex gets -1, or its focus() is a no-op and the browser's
|
|
33
|
+
* own pick stays. Returns the node that took focus.
|
|
34
|
+
*/
|
|
35
|
+
export declare function focusOnOpen(target: HTMLElement | null, frame: HTMLElement): HTMLElement;
|
|
25
36
|
/**
|
|
26
37
|
* Standard manual ring props — the INSET ring geometry
|
|
27
38
|
* (`FOCUS_VISIBLE_RING_INSET`: 2px solid `$outlineColor`, offset −2), spread
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyboardFocusRing.d.ts","sourceRoot":"","sources":["../src/keyboardFocusRing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"keyboardFocusRing.d.ts","sourceRoot":"","sources":["../src/keyboardFocusRing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH;;;;GAIG;AACH,wBAAgB,8BAA8B,SAY7C;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAG1C;AAWD;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,EAAE,KAAK,EAAE,WAAW,GAAG,WAAW,CAQvF;AAID;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB;;;;;CAEzB,CAAC;AAEX;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,8uCA+BhC,CAAC;AAIH,uEAAuE;AACvE,wBAAgB,wBAAwB,IAAI,IAAI,CAO/C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createThemes.d.ts","sourceRoot":"","sources":["../../src/theme/createThemes.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,YAAY,IAAI,mBAAmB,EACpC,MAAM,wBAAwB,CAAC;AAiEhC,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAG1B,CAAC;AAEF,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAevB,CAAC;AAEX,eAAO,MAAM,wBAAwB;;;;;;;;;;CAI3B,CAAC;AAEX,MAAM,WAAW,OAAO;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB,CACrC,WAAW,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,EACvC,YAAY,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE;IAExC,WAAW,EAAE,WAAW,CAAC;IACzB,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED,MAAM,WAAW,0BAA0B,CACzC,WAAW,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,EACvC,YAAY,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,EACxC,WAAW,SAAS,OAAO,GAAG,OAAO,EACrC,YAAY,SAAS,OAAO,GAAG,OAAO,CACtC,SAAQ,sBAAsB,CAAC,WAAW,EAAE,YAAY,CAAC;IACzD,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,0BAA0B;IACzC,eAAe,CAAC,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC;IAC/E,mBAAmB,CAAC,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC;IACvF,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;CACzF;AA8BD,eAAO,MAAM,YAAY,aA6BvB,CAAC;
|
|
1
|
+
{"version":3,"file":"createThemes.d.ts","sourceRoot":"","sources":["../../src/theme/createThemes.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,26 +16,21 @@ export declare const FOCUS_RING_MIN_CONTRAST = 3;
|
|
|
16
16
|
export declare function focusRingColorMeetsContrast(ringColor: string, surfaceColor: string): boolean;
|
|
17
17
|
/**
|
|
18
18
|
* ONE ring geometry (DG-A11Y-01 / LC-71 §4): 2px solid `$outlineColor` at
|
|
19
|
-
* offset
|
|
20
|
-
* surface behind the control
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* old flat inset (−2) painted
|
|
24
|
-
* 1.17–1.31:1 (
|
|
25
|
-
* the same ring on the page ground clears 5.78–6.50:1 (MPO-41 / MPO-19 X7).
|
|
19
|
+
* offset **+2**, a band clear of the border box with a 2px gap, painted on the
|
|
20
|
+
* surface behind the control. FZ-7944 round 2 moved the default from 0 to +2
|
|
21
|
+
* (the macOS and iPadOS keyboard ring); the ≥3:1 floor stays computable
|
|
22
|
+
* because the band still paints on the page ground, never inside a fill. The
|
|
23
|
+
* old flat inset (−2) painted INSIDE solid intent fills and sank to
|
|
24
|
+
* 1.17–1.31:1 (MPO-41 / MPO-19 X7).
|
|
26
25
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* MPO-92 ratified a second, shape-scoped carve-out on the other side:
|
|
32
|
-
* `FOCUS_VISIBLE_RING_HALO` (+2) for pill/circular thumbs and inline text
|
|
33
|
-
* links. The F1 "not +2" reading was about the DEFAULT — a blanket +2 on
|
|
34
|
-
* every control — and it stands. The halo is a named carve-out with a written
|
|
35
|
-
* shape scope, exactly as the inset is; `SANCTIONED_FOCUS_RING_OFFSETS` below
|
|
36
|
-
* is the closed set of all three.
|
|
26
|
+
* Two carve-outs stay named: `FOCUS_VISIBLE_RING_INSET` (−2) for clipping
|
|
27
|
+
* ancestors, and `FOCUS_RING_FLUSH_OFFSET` (0) for rows and cells that sit
|
|
28
|
+
* edge to edge inside a padded overlay, where a gapped band would collide
|
|
29
|
+
* with the neighbour. `SANCTIONED_FOCUS_RING_OFFSETS` is the closed set.
|
|
37
30
|
*/
|
|
38
31
|
export declare const FOCUS_RING_CLIPPED_OFFSET = -2;
|
|
32
|
+
export declare const FOCUS_RING_FLUSH_OFFSET = 0;
|
|
33
|
+
export declare const FOCUS_RING_HALO_OFFSET = 2;
|
|
39
34
|
export declare const FOCUS_VISIBLE_RING: {
|
|
40
35
|
outlineWidth: number;
|
|
41
36
|
outlineStyle: "solid";
|
|
@@ -62,29 +57,10 @@ export declare const FOCUS_VISIBLE_RING_INSET: {
|
|
|
62
57
|
outlineColor: string;
|
|
63
58
|
};
|
|
64
59
|
/**
|
|
65
|
-
* The
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* Scope is by SHAPE, not by instance, and it is closed at two:
|
|
70
|
-
* - **pill / circular thumbs** — a round handle the user drags (Slider
|
|
71
|
-
* thumb, Rating star, TimeRangeScrubber handle). At offset 0 the band is
|
|
72
|
-
* concentric with the glyph's own edge and reads as a thicker glyph.
|
|
73
|
-
* - **inline text links** — a link inside a run of prose (markdown/mdx
|
|
74
|
-
* `Link`, ErrorSummary's summary link, backoffice "View All"). At offset 0
|
|
75
|
-
* the band crosses the line box and collides with ascenders/descenders of
|
|
76
|
-
* the surrounding text.
|
|
77
|
-
*
|
|
78
|
-
* NOT for standalone rectangles on the page ground — cards, tiles, rows,
|
|
79
|
-
* fields. Those are the default `FOCUS_VISIBLE_RING` (offset 0), which is
|
|
80
|
-
* what makes the Axiom 12 ≥3:1 floor computable against the page ground.
|
|
81
|
-
*
|
|
82
|
-
* Contrast is unaffected: like offset 0 the halo paints OUTSIDE the border
|
|
83
|
-
* box, on the surface behind the control, so it measures against the same
|
|
84
|
-
* page ground the default does — the 1.17–1.31:1 failures MPO-41 retired were
|
|
85
|
-
* the INSET painting inside solid intent fills, a defect the halo cannot have.
|
|
60
|
+
* The halo (MPO-92): pill and circular thumbs and inline text links. Since
|
|
61
|
+
* FZ-7944 round 2 it equals the default ring; the name stays so those call
|
|
62
|
+
* sites keep saying why they hold +2 if the default ever moves again.
|
|
86
63
|
*/
|
|
87
|
-
export declare const FOCUS_RING_HALO_OFFSET = 2;
|
|
88
64
|
export declare const FOCUS_VISIBLE_RING_HALO: {
|
|
89
65
|
outlineOffset: number;
|
|
90
66
|
outlineWidth: number;
|
|
@@ -93,13 +69,13 @@ export declare const FOCUS_VISIBLE_RING_HALO: {
|
|
|
93
69
|
};
|
|
94
70
|
/**
|
|
95
71
|
* The CLOSED set of sanctioned focus-ring offsets (LC-71 §4). Three, and only
|
|
96
|
-
* three: the
|
|
72
|
+
* three: the clipping inset −2, the flush 0, the default +2. A call site
|
|
97
73
|
* that wants any other number is a rule gap, not a preference — file it and
|
|
98
74
|
* amend §4, do not type the number. `focusState.spec.ts` asserts this set is
|
|
99
75
|
* exactly what the repo paints, so a fourth offset fails a test instead of
|
|
100
76
|
* shipping (MPO-92 AC-3).
|
|
101
77
|
*/
|
|
102
|
-
export declare const SANCTIONED_FOCUS_RING_OFFSETS: readonly [-2,
|
|
78
|
+
export declare const SANCTIONED_FOCUS_RING_OFFSETS: readonly [-2, 0, number];
|
|
103
79
|
/** True when `offset` is one of the three offsets LC-71 §4 sanctions. */
|
|
104
80
|
export declare function isSanctionedFocusRingOffset(offset: number): boolean;
|
|
105
81
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"focusState.d.ts","sourceRoot":"","sources":["../../src/theme/focusState.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAEnD;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,IAAI,CAAC;AACtC,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAuBzC;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAO5F;AAED
|
|
1
|
+
{"version":3,"file":"focusState.d.ts","sourceRoot":"","sources":["../../src/theme/focusState.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAEnD;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,IAAI,CAAC;AACtC,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAuBzC;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAO5F;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAC5C,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,sBAAsB,IAAI,CAAC;AACxC,eAAO,MAAM,kBAAkB;;;;;CAKF,CAAC;AAE9B;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,wBAAwB;;;;;CAGR,CAAC;AAE9B;;;;GAIG;AACH,eAAO,MAAM,uBAAuB;;;;;CAGP,CAAC;AAE9B;;;;;;;GAOG;AACH,eAAO,MAAM,6BAA6B,0BAIhC,CAAC;AAEX,yEAAyE;AACzE,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEnE;AAED;;;;GAIG;AACH,eAAO,MAAM,iBAAiB;;CAED,CAAC;AAE9B,eAAO,MAAM,iBAAiB;;CAED,CAAC;AAE9B;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,iBAAiB,EAChE,QAAQ,CAAC,EAAE,CAAC,CAAC,GAAG,iBAAiB,CAAC,GAAG,IAAI,GACxC,CAAC,GAAG,iBAAiB,CAyBvB;AAED,mFAAmF;AACnF,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,iBAAiB,EAC1B,KAAK,EAAE,iBAAiB,GACvB,iBAAiB,CAKnB"}
|
package/types/theme/motion.d.ts
CHANGED
|
@@ -4,8 +4,10 @@ export { motionDurationMs, motionHideDelayMs, motionSeconds, motionSettleMs } fr
|
|
|
4
4
|
export type MotionRoleName = "control" | "overlay" | "scrim" | "reveal" | "slide";
|
|
5
5
|
export interface MotionRole {
|
|
6
6
|
transition: TransitionProp | undefined;
|
|
7
|
+
exit?: TransitionProp | undefined;
|
|
7
8
|
animateOnly: readonly string[];
|
|
8
9
|
}
|
|
10
|
+
export declare const motionExitFactor: number;
|
|
9
11
|
export declare const motionRoleProperties: {
|
|
10
12
|
readonly control: readonly ["backgroundColor", "borderColor", "color", "opacity", "transform"];
|
|
11
13
|
readonly overlay: readonly ["opacity", "transform"];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"motion.d.ts","sourceRoot":"","sources":["../../src/theme/motion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAIzC,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEpG,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAElF,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,cAAc,GAAG,SAAS,CAAC;IACvC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CAChC;AAED,eAAO,MAAM,oBAAoB;;;;;;CAM6B,CAAC;
|
|
1
|
+
{"version":3,"file":"motion.d.ts","sourceRoot":"","sources":["../../src/theme/motion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAIzC,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEpG,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAElF,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,cAAc,GAAG,SAAS,CAAC;IACvC,IAAI,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IAClC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CAChC;AAED,eAAO,MAAM,gBAAgB,QAAQ,CAAC;AAEtC,eAAO,MAAM,oBAAoB;;;;;;CAM6B,CAAC;AAmB/D,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC,cAAc,EAAE,UAAU,CAAC,CAuB7E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overlaySurfaces.d.ts","sourceRoot":"","sources":["../../src/theme/overlaySurfaces.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"overlaySurfaces.d.ts","sourceRoot":"","sources":["../../src/theme/overlaySurfaces.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAML,KAAK,kBAAkB,IAAI,yBAAyB,EAEpD,KAAK,UAAU,EACf,KAAK,cAAc,EAEpB,MAAM,SAAS,CAAC;AA6DjB,KAAK,aAAa,GAAG,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;AAmC5C;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAAE,eAAe,EAAE,EAAE;IAAE,eAAe,CAAC,EAAE,aAAa,CAAA;CAAE,GAAG,IAAI,CAG9F;AAID,MAAM,WAAW,wBAAwB;IACvC,4EAA4E;IAC5E,cAAc,EAAE,OAAO,CAAC;CACzB;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,mDAE9B,CAAC;AAEH,wBAAgB,sBAAsB,IAAI,wBAAwB,CAEjE;AAED,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AAQD,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,yBAAyB,EAAE,MAAM,CAAC,GAAG;IACzE,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB,CAAC;AAEF,eAAO,MAAM,aAAa;eAJb,SAAS;WACb,UAAU;kDAcjB,CAAC;AA0CH;;;;;;GAMG;AACH,eAAO,MAAM,aAAa;;;;;;;;eAEiB,SAAS;kDAelD,CAAC;AAOH,eAAO,MAAM,kBAAkB;eAxFlB,SAAS;WACb,UAAU;kDAiGlB,CAAC;AAgCF,eAAO,MAAM,kBAAkB;;;;;;;;eAEY,SAAS;kDAelD,CAAC;AAiBH,eAAO,MAAM,cAAc;eALd,SAAS;IACpB,iEAAiE;sBAC/C,aAAa;kDA0BhC,CAAC"}
|
package/types/theme/recipes.d.ts
CHANGED
|
@@ -59,6 +59,14 @@ export interface ElevationChromeProps extends ElevationPaintProps {
|
|
|
59
59
|
/** Android dp is twice the size-formula offsetY. */
|
|
60
60
|
elevation?: number;
|
|
61
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* A content card's lift (LC-151): an explicit shadow plus Android dp under
|
|
64
|
+
* `elevationAndroid`. Not `elevation`: on native that key is Tamagui's stack
|
|
65
|
+
* variant, which replaces the shadow with its own size-formula one.
|
|
66
|
+
*/
|
|
67
|
+
export interface CardLiftProps extends ElevationPaintProps {
|
|
68
|
+
elevationAndroid?: number;
|
|
69
|
+
}
|
|
62
70
|
/** Text-bearing control chrome (Button, Chip, Input.Box): muted fill/border, no opacity. */
|
|
63
71
|
export interface DisabledSurfaceProps {
|
|
64
72
|
backgroundColor?: string;
|
|
@@ -224,7 +232,7 @@ export interface KnobProps {
|
|
|
224
232
|
borderWidth?: number;
|
|
225
233
|
borderRadius: string | number;
|
|
226
234
|
padding: string;
|
|
227
|
-
} &
|
|
235
|
+
} & CardLiftProps & CornerSmoothingCarrier;
|
|
228
236
|
/** Elevated/overlay tier (popovers, dropdowns): border + elevation. */
|
|
229
237
|
elevatedSurface: {
|
|
230
238
|
backgroundColor: string;
|