@ankhorage/surface 1.3.1 → 2.0.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/CHANGELOG.md +35 -0
- package/dist/components/badge/Badge.d.ts +1 -1
- package/dist/components/badge/Badge.d.ts.map +1 -1
- package/dist/components/badge/Badge.js +3 -3
- package/dist/components/badge/Badge.js.map +1 -1
- package/dist/components/badge/types.d.ts +2 -2
- package/dist/components/badge/types.d.ts.map +1 -1
- package/dist/components/badge/types.js.map +1 -1
- package/dist/components/button/Button.d.ts +1 -1
- package/dist/components/button/Button.d.ts.map +1 -1
- package/dist/components/button/Button.js +6 -3
- package/dist/components/button/Button.js.map +1 -1
- package/dist/components/button/types.d.ts +2 -2
- package/dist/components/button/types.d.ts.map +1 -1
- package/dist/components/button/types.js.map +1 -1
- package/dist/components/checkbox/Checkbox.d.ts +1 -1
- package/dist/components/checkbox/Checkbox.d.ts.map +1 -1
- package/dist/components/checkbox/Checkbox.js +7 -4
- package/dist/components/checkbox/Checkbox.js.map +1 -1
- package/dist/components/checkbox/types.d.ts +2 -2
- package/dist/components/checkbox/types.d.ts.map +1 -1
- package/dist/components/checkbox/types.js.map +1 -1
- package/dist/components/field/Field.d.ts.map +1 -1
- package/dist/components/field/Field.js +6 -2
- package/dist/components/field/Field.js.map +1 -1
- package/dist/components/helper-text/HelperText.d.ts +1 -1
- package/dist/components/helper-text/HelperText.d.ts.map +1 -1
- package/dist/components/helper-text/HelperText.js +2 -2
- package/dist/components/helper-text/HelperText.js.map +1 -1
- package/dist/components/helper-text/types.d.ts +3 -2
- package/dist/components/helper-text/types.d.ts.map +1 -1
- package/dist/components/helper-text/types.js.map +1 -1
- package/dist/components/icon-button/IconButton.d.ts +1 -1
- package/dist/components/icon-button/IconButton.d.ts.map +1 -1
- package/dist/components/icon-button/IconButton.js +2 -2
- package/dist/components/icon-button/IconButton.js.map +1 -1
- package/dist/components/icon-button/types.d.ts +2 -2
- package/dist/components/icon-button/types.d.ts.map +1 -1
- package/dist/components/icon-button/types.js.map +1 -1
- package/dist/components/label/Label.d.ts +1 -1
- package/dist/components/label/Label.d.ts.map +1 -1
- package/dist/components/label/Label.js +3 -3
- package/dist/components/label/Label.js.map +1 -1
- package/dist/components/label/types.d.ts +3 -2
- package/dist/components/label/types.d.ts.map +1 -1
- package/dist/components/label/types.js.map +1 -1
- package/dist/components/list-item/ListItem.js +1 -1
- package/dist/components/list-item/ListItem.js.map +1 -1
- package/dist/components/menu/Menu.d.ts.map +1 -1
- package/dist/components/menu/Menu.js +1 -3
- package/dist/components/menu/Menu.js.map +1 -1
- package/dist/components/navigation/NavigationItem.d.ts.map +1 -1
- package/dist/components/navigation/NavigationItem.js +1 -1
- package/dist/components/navigation/NavigationItem.js.map +1 -1
- package/dist/components/navigation/TabBarItem.d.ts.map +1 -1
- package/dist/components/navigation/TabBarItem.js +1 -1
- package/dist/components/navigation/TabBarItem.js.map +1 -1
- package/dist/components/radio/Radio.d.ts +1 -1
- package/dist/components/radio/Radio.d.ts.map +1 -1
- package/dist/components/radio/Radio.js +4 -3
- package/dist/components/radio/Radio.js.map +1 -1
- package/dist/components/radio/types.d.ts +2 -2
- package/dist/components/radio/types.d.ts.map +1 -1
- package/dist/components/radio/types.js.map +1 -1
- package/dist/components/switch/Switch.d.ts +1 -1
- package/dist/components/switch/Switch.d.ts.map +1 -1
- package/dist/components/switch/Switch.js +4 -3
- package/dist/components/switch/Switch.js.map +1 -1
- package/dist/components/switch/types.d.ts +2 -2
- package/dist/components/switch/types.d.ts.map +1 -1
- package/dist/components/switch/types.js.map +1 -1
- package/dist/components/tabs/Tab.d.ts.map +1 -1
- package/dist/components/tabs/Tab.js +1 -1
- package/dist/components/tabs/Tab.js.map +1 -1
- package/dist/components/toast/Toast.d.ts +1 -1
- package/dist/components/toast/Toast.d.ts.map +1 -1
- package/dist/components/toast/Toast.js +34 -9
- package/dist/components/toast/Toast.js.map +1 -1
- package/dist/components/toast/ToastProvider.js +1 -1
- package/dist/components/toast/ToastProvider.js.map +1 -1
- package/dist/components/toast/index.d.ts +1 -1
- package/dist/components/toast/index.d.ts.map +1 -1
- package/dist/components/toast/index.js.map +1 -1
- package/dist/components/toast/types.d.ts +3 -2
- package/dist/components/toast/types.d.ts.map +1 -1
- package/dist/components/toast/types.js.map +1 -1
- package/dist/components/tooltip/Tooltip.js +1 -1
- package/dist/components/tooltip/Tooltip.js.map +1 -1
- package/dist/examples/DocsExamples.js +4 -4
- package/dist/examples/DocsExamples.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/resolvers/index.d.ts +1 -1
- package/dist/internal/resolvers/index.d.ts.map +1 -1
- package/dist/internal/resolvers/index.js +1 -1
- package/dist/internal/resolvers/index.js.map +1 -1
- package/dist/internal/resolvers/resolveFieldPresentation.d.ts +5 -5
- package/dist/internal/resolvers/resolveFieldPresentation.d.ts.map +1 -1
- package/dist/internal/resolvers/resolveFieldPresentation.js +8 -6
- package/dist/internal/resolvers/resolveFieldPresentation.js.map +1 -1
- package/dist/internal/resolvers/resolveInteractiveColors.d.ts +3 -3
- package/dist/internal/resolvers/resolveInteractiveColors.d.ts.map +1 -1
- package/dist/internal/resolvers/resolveInteractiveColors.js +4 -6
- package/dist/internal/resolvers/resolveInteractiveColors.js.map +1 -1
- package/dist/internal/resolvers/resolveSelectionControlColors.d.ts +3 -3
- package/dist/internal/resolvers/resolveSelectionControlColors.d.ts.map +1 -1
- package/dist/internal/resolvers/resolveSelectionControlColors.js +4 -4
- package/dist/internal/resolvers/resolveSelectionControlColors.js.map +1 -1
- package/dist/internal/resolvers/resolveSurfaceColor.d.ts +4 -0
- package/dist/internal/resolvers/resolveSurfaceColor.d.ts.map +1 -0
- package/dist/internal/resolvers/resolveSurfaceColor.js +26 -0
- package/dist/internal/resolvers/resolveSurfaceColor.js.map +1 -0
- package/dist/internal/resolvers/resolveTextColor.d.ts +2 -3
- package/dist/internal/resolvers/resolveTextColor.d.ts.map +1 -1
- package/dist/internal/resolvers/resolveTextColor.js +7 -11
- package/dist/internal/resolvers/resolveTextColor.js.map +1 -1
- package/dist/layout/ScrollArea.d.ts +9 -0
- package/dist/layout/ScrollArea.d.ts.map +1 -0
- package/dist/layout/ScrollArea.js +52 -0
- package/dist/layout/ScrollArea.js.map +1 -0
- package/dist/layout/index.d.ts +2 -0
- package/dist/layout/index.d.ts.map +1 -1
- package/dist/layout/index.js +1 -0
- package/dist/layout/index.js.map +1 -1
- package/dist/primitives/heading/Heading.d.ts.map +1 -1
- package/dist/primitives/heading/Heading.js +2 -2
- package/dist/primitives/heading/Heading.js.map +1 -1
- package/dist/primitives/heading/resolveHeadingStyle.d.ts +2 -1
- package/dist/primitives/heading/resolveHeadingStyle.d.ts.map +1 -1
- package/dist/primitives/heading/resolveHeadingStyle.js +2 -2
- package/dist/primitives/heading/resolveHeadingStyle.js.map +1 -1
- package/dist/primitives/heading/types.d.ts +3 -0
- package/dist/primitives/heading/types.d.ts.map +1 -1
- package/dist/primitives/heading/types.js.map +1 -1
- package/dist/primitives/text/Text.d.ts +1 -1
- package/dist/primitives/text/Text.d.ts.map +1 -1
- package/dist/primitives/text/Text.js +2 -2
- package/dist/primitives/text/Text.js.map +1 -1
- package/dist/primitives/text/types.d.ts +3 -3
- package/dist/primitives/text/types.d.ts.map +1 -1
- package/dist/primitives/text/types.js.map +1 -1
- package/dist/surfaceColor.d.ts +9 -0
- package/dist/surfaceColor.d.ts.map +1 -0
- package/dist/surfaceColor.js +15 -0
- package/dist/surfaceColor.js.map +1 -0
- package/dist/theme/colorEngine.d.ts.map +1 -1
- package/dist/theme/colorEngine.js +9 -1
- package/dist/theme/colorEngine.js.map +1 -1
- package/dist/theme/types.d.ts +5 -0
- package/dist/theme/types.d.ts.map +1 -1
- package/dist/theme/types.js.map +1 -1
- package/package.json +1 -1
- package/src/components/badge/Badge.tsx +8 -3
- package/src/components/badge/types.ts +2 -2
- package/src/components/button/Button.tsx +9 -3
- package/src/components/button/types.ts +2 -2
- package/src/components/checkbox/Checkbox.tsx +13 -4
- package/src/components/checkbox/types.ts +2 -2
- package/src/components/field/Field.tsx +11 -3
- package/src/components/helper-text/HelperText.tsx +2 -2
- package/src/components/helper-text/types.ts +3 -2
- package/src/components/icon-button/IconButton.tsx +2 -2
- package/src/components/icon-button/types.ts +2 -2
- package/src/components/label/Label.tsx +9 -3
- package/src/components/label/types.ts +3 -2
- package/src/components/list-item/ListItem.tsx +1 -1
- package/src/components/menu/Menu.tsx +1 -8
- package/src/components/navigation/NavigationItem.tsx +2 -1
- package/src/components/navigation/TabBarItem.tsx +2 -1
- package/src/components/radio/Radio.tsx +5 -3
- package/src/components/radio/types.ts +2 -2
- package/src/components/switch/Switch.tsx +5 -3
- package/src/components/switch/types.ts +2 -2
- package/src/components/tabs/Tab.tsx +1 -5
- package/src/components/toast/Toast.tsx +38 -10
- package/src/components/toast/ToastProvider.tsx +1 -1
- package/src/components/toast/index.ts +1 -1
- package/src/components/toast/types.ts +4 -2
- package/src/components/tooltip/Tooltip.tsx +1 -1
- package/src/examples/DocsExamples.tsx +4 -4
- package/src/index.test.ts +1 -0
- package/src/index.ts +13 -1
- package/src/internal/resolvers/index.ts +1 -1
- package/src/internal/resolvers/resolveFieldPresentation.test.ts +12 -10
- package/src/internal/resolvers/resolveFieldPresentation.ts +13 -11
- package/src/internal/resolvers/resolveInteractiveColors.test.ts +4 -4
- package/src/internal/resolvers/resolveInteractiveColors.ts +6 -7
- package/src/internal/resolvers/resolveSelectionControlColors.test.ts +8 -8
- package/src/internal/resolvers/resolveSelectionControlColors.ts +6 -5
- package/src/internal/resolvers/resolveSurfaceColor.test.ts +21 -0
- package/src/internal/resolvers/resolveSurfaceColor.ts +31 -0
- package/src/internal/resolvers/resolveTextColor.test.ts +16 -5
- package/src/internal/resolvers/resolveTextColor.ts +10 -22
- package/src/layout/ScrollArea.tsx +115 -0
- package/src/layout/index.ts +2 -0
- package/src/primitives/heading/Heading.tsx +3 -1
- package/src/primitives/heading/resolveHeadingStyle.test.ts +1 -1
- package/src/primitives/heading/resolveHeadingStyle.ts +4 -1
- package/src/primitives/heading/types.ts +4 -0
- package/src/primitives/text/Text.tsx +2 -2
- package/src/primitives/text/types.ts +3 -3
- package/src/surfaceColor.test.ts +46 -0
- package/src/surfaceColor.ts +22 -0
- package/src/theme/colorEngine.test.ts +6 -0
- package/src/theme/colorEngine.ts +9 -1
- package/src/theme/types.ts +5 -0
- package/dist/internal/resolvers/resolveTone.d.ts +0 -4
- package/dist/internal/resolvers/resolveTone.d.ts.map +0 -1
- package/dist/internal/resolvers/resolveTone.js +0 -16
- package/dist/internal/resolvers/resolveTone.js.map +0 -1
- package/src/internal/resolvers/resolveTone.ts +0 -19
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import type { SurfaceStatusColor } from '../../surfaceColor';
|
|
4
|
+
|
|
5
|
+
export type ToastStatus = 'default' | SurfaceStatusColor;
|
|
4
6
|
|
|
5
7
|
export interface ToastProps {
|
|
6
8
|
title?: React.ReactNode;
|
|
7
9
|
description?: React.ReactNode;
|
|
8
|
-
|
|
10
|
+
status?: ToastStatus;
|
|
9
11
|
onDismiss?: (() => void) | undefined;
|
|
10
12
|
testID?: string;
|
|
11
13
|
}
|
|
@@ -42,8 +42,8 @@ export function ProviderExample() {
|
|
|
42
42
|
<ThemeProvider initialConfig={docsThemeConfig}>
|
|
43
43
|
<Stack gap="m" p="l">
|
|
44
44
|
<Text variant="body">Surface starter</Text>
|
|
45
|
-
<Badge
|
|
46
|
-
<Button
|
|
45
|
+
<Badge color="success" content="Foundation" />
|
|
46
|
+
<Button color="warning" variant="soft">
|
|
47
47
|
Continue
|
|
48
48
|
</Button>
|
|
49
49
|
</Stack>
|
|
@@ -66,7 +66,7 @@ export function FormAndOverlayExample() {
|
|
|
66
66
|
<Checkbox defaultChecked>Weekly updates</Checkbox>
|
|
67
67
|
<Radio>Product announcements</Radio>
|
|
68
68
|
<Switch readOnly>Read-only setting</Switch>
|
|
69
|
-
<HelperText
|
|
69
|
+
<HelperText color="error">Invalid fields should reuse the same error color.</HelperText>
|
|
70
70
|
</Stack>
|
|
71
71
|
<Modal visible={false}>
|
|
72
72
|
<Text>Modal content</Text>
|
|
@@ -106,7 +106,7 @@ export function NavigationExample() {
|
|
|
106
106
|
trigger={<Text>Open menu</Text>}
|
|
107
107
|
/>
|
|
108
108
|
<Box>
|
|
109
|
-
<Text
|
|
109
|
+
<Text color="success">Theme overrides can stay semantic.</Text>
|
|
110
110
|
</Box>
|
|
111
111
|
</Stack>
|
|
112
112
|
</ThemeProvider>
|
package/src/index.test.ts
CHANGED
|
@@ -34,6 +34,7 @@ const expectedRootExports = [
|
|
|
34
34
|
"export * from './core/responsive';",
|
|
35
35
|
"export * from './layout';",
|
|
36
36
|
"export { Image } from './primitives/image';",
|
|
37
|
+
"export {\n SURFACE_COLORS,\n SURFACE_EMPHASES,\n SURFACE_PALETTE_COLORS,\n SURFACE_STATUS_COLORS,\n} from './surfaceColor';",
|
|
37
38
|
"export * from './theme';",
|
|
38
39
|
] as const;
|
|
39
40
|
|
package/src/index.ts
CHANGED
|
@@ -50,7 +50,7 @@ export type { TextInputProps } from './components/text-input';
|
|
|
50
50
|
export { TextInput } from './components/text-input';
|
|
51
51
|
export type { TextareaProps } from './components/textarea';
|
|
52
52
|
export { Textarea } from './components/textarea';
|
|
53
|
-
export type { ToastOptions, ToastProps,
|
|
53
|
+
export type { ToastOptions, ToastProps, ToastStatus } from './components/toast';
|
|
54
54
|
export { Toast, ToastProvider, useToast } from './components/toast';
|
|
55
55
|
export type { TooltipProps } from './components/tooltip';
|
|
56
56
|
export { Tooltip } from './components/tooltip';
|
|
@@ -70,6 +70,18 @@ export type { ImageFit, ImageProps, SurfaceImageSource } from './primitives/imag
|
|
|
70
70
|
export { Image } from './primitives/image';
|
|
71
71
|
export type { TextProps } from './primitives/text';
|
|
72
72
|
export { Text } from './primitives/text';
|
|
73
|
+
export type {
|
|
74
|
+
SurfaceColor,
|
|
75
|
+
SurfaceEmphasis,
|
|
76
|
+
SurfacePaletteColor,
|
|
77
|
+
SurfaceStatusColor,
|
|
78
|
+
} from './surfaceColor';
|
|
79
|
+
export {
|
|
80
|
+
SURFACE_COLORS,
|
|
81
|
+
SURFACE_EMPHASES,
|
|
82
|
+
SURFACE_PALETTE_COLORS,
|
|
83
|
+
SURFACE_STATUS_COLORS,
|
|
84
|
+
} from './surfaceColor';
|
|
73
85
|
export * from './theme';
|
|
74
86
|
export { isDeepEqual } from './utils/deepEqual';
|
|
75
87
|
export { deepMerge } from './utils/deepMerge';
|
|
@@ -10,6 +10,6 @@ export * from './resolveOverlayAnimation';
|
|
|
10
10
|
export * from './resolveOverlayZIndex';
|
|
11
11
|
export * from './resolveSelectionControlBehavior';
|
|
12
12
|
export * from './resolveSelectionControlColors';
|
|
13
|
+
export * from './resolveSurfaceColor';
|
|
13
14
|
export * from './resolveTextColor';
|
|
14
15
|
export * from './resolveTextStyles';
|
|
15
|
-
export * from './resolveTone';
|
|
@@ -4,28 +4,30 @@ import { resolveFieldPresentation } from './resolveFieldPresentation';
|
|
|
4
4
|
import { resolveFieldState } from './resolveFieldState';
|
|
5
5
|
|
|
6
6
|
describe('resolveFieldPresentation', () => {
|
|
7
|
-
it('keeps label and helper
|
|
7
|
+
it('keeps label and helper text presentation aligned for default fields', () => {
|
|
8
8
|
expect(resolveFieldPresentation(resolveFieldState({}))).toEqual({
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
helperEmphasis: 'default',
|
|
10
|
+
labelEmphasis: 'default',
|
|
11
11
|
});
|
|
12
12
|
});
|
|
13
13
|
|
|
14
14
|
it('mutes both label and helper text for disabled and read-only fields', () => {
|
|
15
15
|
expect(resolveFieldPresentation(resolveFieldState({ disabled: true }))).toEqual({
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
helperEmphasis: 'muted',
|
|
17
|
+
labelEmphasis: 'muted',
|
|
18
18
|
});
|
|
19
19
|
expect(resolveFieldPresentation(resolveFieldState({ readOnly: true }))).toEqual({
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
helperEmphasis: 'muted',
|
|
21
|
+
labelEmphasis: 'muted',
|
|
22
22
|
});
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
-
it('elevates invalid fields to the
|
|
25
|
+
it('elevates invalid fields to the error color', () => {
|
|
26
26
|
expect(resolveFieldPresentation(resolveFieldState({ invalid: true, readOnly: true }))).toEqual({
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
helperColor: 'error',
|
|
28
|
+
helperEmphasis: 'default',
|
|
29
|
+
labelColor: 'error',
|
|
30
|
+
labelEmphasis: 'default',
|
|
29
31
|
});
|
|
30
32
|
});
|
|
31
33
|
});
|
|
@@ -1,30 +1,32 @@
|
|
|
1
|
+
import type { SurfaceColor, SurfaceEmphasis } from '../../surfaceColor';
|
|
1
2
|
import type { FieldState } from './resolveFieldState';
|
|
2
|
-
import type { TextTone } from './resolveTextColor';
|
|
3
|
-
|
|
4
|
-
type FieldPresentationTone = Extract<TextTone, 'default' | 'muted' | 'danger'>;
|
|
5
3
|
|
|
6
4
|
export interface ResolvedFieldPresentation {
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
helperColor?: Extract<SurfaceColor, 'error'>;
|
|
6
|
+
helperEmphasis: Extract<SurfaceEmphasis, 'default' | 'muted'>;
|
|
7
|
+
labelColor?: Extract<SurfaceColor, 'error'>;
|
|
8
|
+
labelEmphasis: Extract<SurfaceEmphasis, 'default' | 'muted'>;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export function resolveFieldPresentation(fieldState: FieldState): ResolvedFieldPresentation {
|
|
12
12
|
if (fieldState.invalid) {
|
|
13
13
|
return {
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
helperColor: 'error',
|
|
15
|
+
helperEmphasis: 'default',
|
|
16
|
+
labelColor: 'error',
|
|
17
|
+
labelEmphasis: 'default',
|
|
16
18
|
};
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
if (fieldState.disabled || fieldState.readOnly) {
|
|
20
22
|
return {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
helperEmphasis: 'muted',
|
|
24
|
+
labelEmphasis: 'muted',
|
|
23
25
|
};
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
return {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
helperEmphasis: 'default',
|
|
30
|
+
labelEmphasis: 'default',
|
|
29
31
|
};
|
|
30
32
|
}
|
|
@@ -5,11 +5,11 @@ import { resolveFieldState } from './resolveFieldState';
|
|
|
5
5
|
import { resolveButtonColors, resolveInputColors } from './resolveInteractiveColors';
|
|
6
6
|
|
|
7
7
|
describe('resolveInteractiveColors', () => {
|
|
8
|
-
it('maps button variant,
|
|
8
|
+
it('maps button variant, color, and state through semantic slots', () => {
|
|
9
9
|
const theme = createTheme();
|
|
10
10
|
const solid = resolveButtonColors(theme, {
|
|
11
11
|
variant: 'solid',
|
|
12
|
-
|
|
12
|
+
color: 'primary',
|
|
13
13
|
state: {
|
|
14
14
|
disabled: false,
|
|
15
15
|
focused: false,
|
|
@@ -19,7 +19,7 @@ describe('resolveInteractiveColors', () => {
|
|
|
19
19
|
});
|
|
20
20
|
const outline = resolveButtonColors(theme, {
|
|
21
21
|
variant: 'outline',
|
|
22
|
-
|
|
22
|
+
color: 'danger',
|
|
23
23
|
state: {
|
|
24
24
|
disabled: false,
|
|
25
25
|
focused: false,
|
|
@@ -50,7 +50,7 @@ describe('resolveInteractiveColors', () => {
|
|
|
50
50
|
}),
|
|
51
51
|
);
|
|
52
52
|
|
|
53
|
-
expect(focusedInvalid.borderColor).toBe(theme.semantics.
|
|
53
|
+
expect(focusedInvalid.borderColor).toBe(theme.semantics.error.base);
|
|
54
54
|
expect(readOnly.backgroundColor).toBe(theme.semantics.surface.subtle);
|
|
55
55
|
expect(readOnly.placeholderColor).toBe(theme.semantics.content.muted);
|
|
56
56
|
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import type { SurfaceColor } from '../../surfaceColor';
|
|
1
2
|
import type { SurfaceTheme } from '../../theme/types';
|
|
2
3
|
import type { FieldState } from './resolveFieldState';
|
|
3
4
|
import type { InteractionState } from './resolveInteractiveState';
|
|
4
|
-
import {
|
|
5
|
+
import { resolveSurfaceColor } from './resolveSurfaceColor';
|
|
5
6
|
|
|
6
7
|
export type ButtonVariant = 'solid' | 'outline' | 'ghost' | 'soft';
|
|
7
8
|
|
|
@@ -16,11 +17,11 @@ export function resolveButtonColors(
|
|
|
16
17
|
theme: SurfaceTheme,
|
|
17
18
|
{
|
|
18
19
|
variant,
|
|
19
|
-
|
|
20
|
+
color,
|
|
20
21
|
state,
|
|
21
22
|
}: {
|
|
22
23
|
variant: ButtonVariant;
|
|
23
|
-
|
|
24
|
+
color: SurfaceColor;
|
|
24
25
|
state: InteractionState;
|
|
25
26
|
},
|
|
26
27
|
): ResolvedInteractiveColors {
|
|
@@ -33,7 +34,7 @@ export function resolveButtonColors(
|
|
|
33
34
|
};
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
const semanticTone =
|
|
37
|
+
const semanticTone = resolveSurfaceColor(theme, color);
|
|
37
38
|
|
|
38
39
|
switch (variant) {
|
|
39
40
|
case 'outline':
|
|
@@ -99,9 +100,7 @@ export function resolveInputColors(
|
|
|
99
100
|
backgroundColor: fieldState.readOnly
|
|
100
101
|
? theme.semantics.surface.subtle
|
|
101
102
|
: theme.semantics.surface.default,
|
|
102
|
-
borderColor: fieldState.focused
|
|
103
|
-
? theme.semantics.danger.base
|
|
104
|
-
: theme.semantics.danger.outline,
|
|
103
|
+
borderColor: fieldState.focused ? theme.semantics.error.base : theme.semantics.error.outline,
|
|
105
104
|
contentColor: theme.semantics.content.default,
|
|
106
105
|
placeholderColor: theme.semantics.content.muted,
|
|
107
106
|
};
|
|
@@ -5,12 +5,12 @@ import { resolveFieldState } from './resolveFieldState';
|
|
|
5
5
|
import { resolveSelectionControlColors } from './resolveSelectionControlColors';
|
|
6
6
|
|
|
7
7
|
describe('resolveSelectionControlColors', () => {
|
|
8
|
-
it('maps checked controls through the selected
|
|
8
|
+
it('maps checked controls through the selected color semantics', () => {
|
|
9
9
|
const theme = createTheme();
|
|
10
10
|
const colors = resolveSelectionControlColors(theme, {
|
|
11
11
|
checked: true,
|
|
12
12
|
fieldState: resolveFieldState({ focused: true }),
|
|
13
|
-
|
|
13
|
+
color: 'primary',
|
|
14
14
|
});
|
|
15
15
|
|
|
16
16
|
expect(colors.borderColor).toBe(theme.semantics.action.primary.base);
|
|
@@ -18,24 +18,24 @@ describe('resolveSelectionControlColors', () => {
|
|
|
18
18
|
expect(colors.labelColor).toBe(theme.semantics.content.default);
|
|
19
19
|
});
|
|
20
20
|
|
|
21
|
-
it('maps invalid unchecked controls through
|
|
21
|
+
it('maps invalid unchecked controls through error/border semantics', () => {
|
|
22
22
|
const theme = createTheme();
|
|
23
23
|
const colors = resolveSelectionControlColors(theme, {
|
|
24
24
|
checked: false,
|
|
25
25
|
fieldState: resolveFieldState({ invalid: true }),
|
|
26
|
-
|
|
26
|
+
color: 'primary',
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
-
expect(colors.borderColor).toBe(theme.semantics.
|
|
30
|
-
expect(colors.trackColor).toBe(theme.semantics.
|
|
29
|
+
expect(colors.borderColor).toBe(theme.semantics.error.outline);
|
|
30
|
+
expect(colors.trackColor).toBe(theme.semantics.error.outline);
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
-
it('mutes disabled controls regardless of
|
|
33
|
+
it('mutes disabled controls regardless of color', () => {
|
|
34
34
|
const theme = createTheme();
|
|
35
35
|
const colors = resolveSelectionControlColors(theme, {
|
|
36
36
|
checked: true,
|
|
37
37
|
fieldState: resolveFieldState({ disabled: true }),
|
|
38
|
-
|
|
38
|
+
color: 'danger',
|
|
39
39
|
});
|
|
40
40
|
|
|
41
41
|
expect(colors.labelColor).toBe(theme.semantics.content.muted);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import type { SurfaceColor } from '../../surfaceColor';
|
|
1
2
|
import type { SurfaceTheme } from '../../theme/types';
|
|
2
3
|
import type { FieldState } from './resolveFieldState';
|
|
3
|
-
import {
|
|
4
|
+
import { resolveSurfaceColor } from './resolveSurfaceColor';
|
|
4
5
|
|
|
5
6
|
export interface ResolvedSelectionControlColors {
|
|
6
7
|
backgroundColor: string;
|
|
@@ -15,20 +16,20 @@ export interface ResolvedSelectionControlColors {
|
|
|
15
16
|
export function resolveSelectionControlColors(
|
|
16
17
|
theme: SurfaceTheme,
|
|
17
18
|
{
|
|
18
|
-
|
|
19
|
+
color = 'primary',
|
|
19
20
|
fieldState,
|
|
20
21
|
checked,
|
|
21
22
|
hovered = false,
|
|
22
23
|
pressed = false,
|
|
23
24
|
}: {
|
|
24
|
-
|
|
25
|
+
color?: SurfaceColor;
|
|
25
26
|
fieldState: FieldState;
|
|
26
27
|
checked: boolean;
|
|
27
28
|
hovered?: boolean;
|
|
28
29
|
pressed?: boolean;
|
|
29
30
|
},
|
|
30
31
|
): ResolvedSelectionControlColors {
|
|
31
|
-
const semanticTone =
|
|
32
|
+
const semanticTone = resolveSurfaceColor(theme, fieldState.invalid ? 'error' : color);
|
|
32
33
|
const isMuted = fieldState.disabled;
|
|
33
34
|
const isInteractiveReadOnly = fieldState.readOnly && !fieldState.disabled;
|
|
34
35
|
|
|
@@ -47,7 +48,7 @@ export function resolveSelectionControlColors(
|
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
const uncheckedBorderColor = fieldState.invalid
|
|
50
|
-
? theme.semantics.
|
|
51
|
+
? theme.semantics.error.outline
|
|
51
52
|
: fieldState.focused
|
|
52
53
|
? theme.semantics.border.focus
|
|
53
54
|
: theme.semantics.border.strong;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { describe, expect, it } from 'bun:test';
|
|
2
|
+
|
|
3
|
+
import { createTheme } from '../../theme/createTheme';
|
|
4
|
+
import { resolveSurfaceColor } from './resolveSurfaceColor';
|
|
5
|
+
|
|
6
|
+
describe('resolveSurfaceColor', () => {
|
|
7
|
+
it('maps every public surface color to a semantic role', () => {
|
|
8
|
+
const theme = createTheme();
|
|
9
|
+
|
|
10
|
+
expect(resolveSurfaceColor(theme, 'primary')).toBe(theme.semantics.action.primary);
|
|
11
|
+
expect(resolveSurfaceColor(theme, 'secondary')).toBe(theme.semantics.secondary);
|
|
12
|
+
expect(resolveSurfaceColor(theme, 'tertiary')).toBe(theme.semantics.accent);
|
|
13
|
+
expect(resolveSurfaceColor(theme, 'quaternary')).toBe(theme.semantics.highlight);
|
|
14
|
+
expect(resolveSurfaceColor(theme, 'neutral')).toBe(theme.semantics.action.neutral);
|
|
15
|
+
expect(resolveSurfaceColor(theme, 'success')).toBe(theme.semantics.success);
|
|
16
|
+
expect(resolveSurfaceColor(theme, 'warning')).toBe(theme.semantics.warning);
|
|
17
|
+
expect(resolveSurfaceColor(theme, 'error')).toBe(theme.semantics.error);
|
|
18
|
+
expect(resolveSurfaceColor(theme, 'info')).toBe(theme.semantics.info);
|
|
19
|
+
expect(resolveSurfaceColor(theme, 'danger')).toBe(theme.semantics.action.danger);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { SurfaceColor } from '../../surfaceColor';
|
|
2
|
+
import type { RoleSemantics, SurfaceTheme } from '../../theme/types';
|
|
3
|
+
|
|
4
|
+
export function resolveSurfaceColor(
|
|
5
|
+
theme: SurfaceTheme,
|
|
6
|
+
color: SurfaceColor = 'primary',
|
|
7
|
+
): RoleSemantics {
|
|
8
|
+
switch (color) {
|
|
9
|
+
case 'secondary':
|
|
10
|
+
return theme.semantics.secondary;
|
|
11
|
+
case 'tertiary':
|
|
12
|
+
return theme.semantics.accent;
|
|
13
|
+
case 'quaternary':
|
|
14
|
+
return theme.semantics.highlight;
|
|
15
|
+
case 'neutral':
|
|
16
|
+
return theme.semantics.action.neutral;
|
|
17
|
+
case 'error':
|
|
18
|
+
return theme.semantics.error;
|
|
19
|
+
case 'info':
|
|
20
|
+
return theme.semantics.info;
|
|
21
|
+
case 'danger':
|
|
22
|
+
return theme.semantics.action.danger;
|
|
23
|
+
case 'success':
|
|
24
|
+
return theme.semantics.success;
|
|
25
|
+
case 'warning':
|
|
26
|
+
return theme.semantics.warning;
|
|
27
|
+
case 'primary':
|
|
28
|
+
default:
|
|
29
|
+
return theme.semantics.action.primary;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -4,7 +4,7 @@ import { createTheme } from '../../theme/createTheme';
|
|
|
4
4
|
import { resolveTextColor } from './resolveTextColor';
|
|
5
5
|
|
|
6
6
|
describe('resolveTextColor', () => {
|
|
7
|
-
it('maps semantic text
|
|
7
|
+
it('maps semantic text emphases through content aliases', () => {
|
|
8
8
|
const theme = createTheme();
|
|
9
9
|
|
|
10
10
|
expect(resolveTextColor(theme, 'default')).toBe(theme.semantics.content.default);
|
|
@@ -13,11 +13,22 @@ describe('resolveTextColor', () => {
|
|
|
13
13
|
expect(resolveTextColor(theme, 'inverse')).toBe(theme.semantics.content.inverse);
|
|
14
14
|
});
|
|
15
15
|
|
|
16
|
-
it('supports semantic
|
|
16
|
+
it('supports semantic colors for shared field and messaging copy', () => {
|
|
17
17
|
const theme = createTheme();
|
|
18
18
|
|
|
19
|
-
expect(resolveTextColor(theme, 'danger')).toBe(theme.semantics.danger.base);
|
|
20
|
-
expect(resolveTextColor(theme, 'success')).toBe(theme.semantics.success.base);
|
|
21
|
-
expect(resolveTextColor(theme, 'warning')).toBe(theme.semantics.warning.base);
|
|
19
|
+
expect(resolveTextColor(theme, 'default', 'danger')).toBe(theme.semantics.action.danger.base);
|
|
20
|
+
expect(resolveTextColor(theme, 'default', 'success')).toBe(theme.semantics.success.base);
|
|
21
|
+
expect(resolveTextColor(theme, 'default', 'warning')).toBe(theme.semantics.warning.base);
|
|
22
|
+
expect(resolveTextColor(theme, 'default', 'error')).toBe(theme.semantics.error.base);
|
|
23
|
+
expect(resolveTextColor(theme, 'default', 'info')).toBe(theme.semantics.info.base);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('maps inverse emphasis with a semantic color to role foreground text', () => {
|
|
27
|
+
const theme = createTheme();
|
|
28
|
+
|
|
29
|
+
expect(resolveTextColor(theme, 'inverse', 'primary')).toBe(
|
|
30
|
+
theme.semantics.action.primary.onSolidText,
|
|
31
|
+
);
|
|
32
|
+
expect(resolveTextColor(theme, 'inverse', 'error')).toBe(theme.semantics.error.onSolidText);
|
|
22
33
|
});
|
|
23
34
|
});
|
|
@@ -1,39 +1,27 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { SurfaceColor, SurfaceEmphasis } from '../../surfaceColor';
|
|
2
2
|
import type { SurfaceTheme } from '../../theme/types';
|
|
3
|
-
|
|
4
|
-
export type TextTone =
|
|
5
|
-
| 'default'
|
|
6
|
-
| 'muted'
|
|
7
|
-
| 'subtle'
|
|
8
|
-
| 'inverse'
|
|
9
|
-
| 'danger'
|
|
10
|
-
| 'success'
|
|
11
|
-
| 'warning';
|
|
12
|
-
export type TextColorValue = keyof SurfaceTheme['colors'] | string;
|
|
3
|
+
import { resolveSurfaceColor } from './resolveSurfaceColor';
|
|
13
4
|
|
|
14
5
|
export function resolveTextColor(
|
|
15
6
|
theme: SurfaceTheme,
|
|
16
|
-
|
|
17
|
-
color?:
|
|
7
|
+
emphasis: SurfaceEmphasis = 'default',
|
|
8
|
+
color?: SurfaceColor,
|
|
18
9
|
): string {
|
|
19
10
|
if (color) {
|
|
20
|
-
|
|
11
|
+
if (emphasis === 'inverse') {
|
|
12
|
+
return resolveSurfaceColor(theme, color).onSolidText;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return resolveSurfaceColor(theme, color).base;
|
|
21
16
|
}
|
|
22
17
|
|
|
23
|
-
switch (
|
|
18
|
+
switch (emphasis) {
|
|
24
19
|
case 'muted':
|
|
25
20
|
return theme.semantics.content.muted;
|
|
26
21
|
case 'subtle':
|
|
27
22
|
return theme.semantics.content.subtle;
|
|
28
23
|
case 'inverse':
|
|
29
24
|
return theme.semantics.content.inverse;
|
|
30
|
-
case 'danger':
|
|
31
|
-
return theme.semantics.danger.base;
|
|
32
|
-
case 'success':
|
|
33
|
-
return theme.semantics.success.base;
|
|
34
|
-
case 'warning':
|
|
35
|
-
return theme.semantics.warning.base;
|
|
36
|
-
case 'default':
|
|
37
25
|
default:
|
|
38
26
|
return theme.semantics.content.default;
|
|
39
27
|
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
ScrollView,
|
|
4
|
+
type ScrollViewProps as ReactNativeScrollViewProps,
|
|
5
|
+
type StyleProp,
|
|
6
|
+
type ViewStyle,
|
|
7
|
+
} from 'react-native';
|
|
8
|
+
|
|
9
|
+
import { useResponsiveRuntime } from '../core/responsive';
|
|
10
|
+
import { useTheme } from '../theme/ThemeContext';
|
|
11
|
+
import { type BoxStyleProps, resolveBoxStyles } from './helpers';
|
|
12
|
+
|
|
13
|
+
export interface ScrollAreaProps
|
|
14
|
+
extends
|
|
15
|
+
BoxStyleProps,
|
|
16
|
+
Omit<ReactNativeScrollViewProps, 'children' | 'contentContainerStyle' | 'style'> {
|
|
17
|
+
children?: React.ReactNode;
|
|
18
|
+
contentContainerStyle?: StyleProp<ViewStyle>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function ScrollArea({
|
|
22
|
+
children,
|
|
23
|
+
contentContainerStyle,
|
|
24
|
+
p,
|
|
25
|
+
px,
|
|
26
|
+
py,
|
|
27
|
+
pt,
|
|
28
|
+
pb,
|
|
29
|
+
pl,
|
|
30
|
+
pr,
|
|
31
|
+
m,
|
|
32
|
+
mx,
|
|
33
|
+
my,
|
|
34
|
+
mt,
|
|
35
|
+
mb,
|
|
36
|
+
ml,
|
|
37
|
+
mr,
|
|
38
|
+
bg,
|
|
39
|
+
radius,
|
|
40
|
+
borderWidth,
|
|
41
|
+
borderColor,
|
|
42
|
+
width,
|
|
43
|
+
height,
|
|
44
|
+
minWidth,
|
|
45
|
+
maxWidth,
|
|
46
|
+
minHeight,
|
|
47
|
+
maxHeight,
|
|
48
|
+
flex,
|
|
49
|
+
flexGrow,
|
|
50
|
+
flexShrink,
|
|
51
|
+
flexBasis,
|
|
52
|
+
alignSelf,
|
|
53
|
+
position,
|
|
54
|
+
top,
|
|
55
|
+
bottom,
|
|
56
|
+
left,
|
|
57
|
+
right,
|
|
58
|
+
overflow,
|
|
59
|
+
zIndex,
|
|
60
|
+
opacity,
|
|
61
|
+
style,
|
|
62
|
+
...scrollProps
|
|
63
|
+
}: ScrollAreaProps) {
|
|
64
|
+
const { theme } = useTheme();
|
|
65
|
+
const { breakpoint } = useResponsiveRuntime();
|
|
66
|
+
const resolved = resolveBoxStyles(theme, breakpoint, {
|
|
67
|
+
p,
|
|
68
|
+
px,
|
|
69
|
+
py,
|
|
70
|
+
pt,
|
|
71
|
+
pb,
|
|
72
|
+
pl,
|
|
73
|
+
pr,
|
|
74
|
+
m,
|
|
75
|
+
mx,
|
|
76
|
+
my,
|
|
77
|
+
mt,
|
|
78
|
+
mb,
|
|
79
|
+
ml,
|
|
80
|
+
mr,
|
|
81
|
+
bg,
|
|
82
|
+
radius,
|
|
83
|
+
borderWidth,
|
|
84
|
+
borderColor,
|
|
85
|
+
width,
|
|
86
|
+
height,
|
|
87
|
+
minWidth,
|
|
88
|
+
maxWidth,
|
|
89
|
+
minHeight,
|
|
90
|
+
maxHeight,
|
|
91
|
+
flex,
|
|
92
|
+
flexGrow,
|
|
93
|
+
flexShrink,
|
|
94
|
+
flexBasis,
|
|
95
|
+
alignSelf,
|
|
96
|
+
position,
|
|
97
|
+
top,
|
|
98
|
+
bottom,
|
|
99
|
+
left,
|
|
100
|
+
right,
|
|
101
|
+
overflow,
|
|
102
|
+
zIndex,
|
|
103
|
+
opacity,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
return (
|
|
107
|
+
<ScrollView
|
|
108
|
+
{...scrollProps}
|
|
109
|
+
contentContainerStyle={contentContainerStyle}
|
|
110
|
+
style={[resolved, style]}
|
|
111
|
+
>
|
|
112
|
+
{children}
|
|
113
|
+
</ScrollView>
|
|
114
|
+
);
|
|
115
|
+
}
|
package/src/layout/index.ts
CHANGED
|
@@ -12,6 +12,8 @@ export type { GridProps } from './Grid';
|
|
|
12
12
|
export { Grid } from './Grid';
|
|
13
13
|
export type { InlineProps } from './Inline';
|
|
14
14
|
export { Inline } from './Inline';
|
|
15
|
+
export type { ScrollAreaProps } from './ScrollArea';
|
|
16
|
+
export { ScrollArea } from './ScrollArea';
|
|
15
17
|
export type { ShowProps } from './Show';
|
|
16
18
|
export { Show } from './Show';
|
|
17
19
|
export type { SpacerProps } from './Spacer';
|
|
@@ -39,6 +39,8 @@ export const Heading: React.FC<HeadingProps> = ({
|
|
|
39
39
|
children,
|
|
40
40
|
level = 2,
|
|
41
41
|
align,
|
|
42
|
+
color,
|
|
43
|
+
emphasis = 'default',
|
|
42
44
|
numberOfLines,
|
|
43
45
|
i18nKey,
|
|
44
46
|
testID,
|
|
@@ -52,7 +54,7 @@ export const Heading: React.FC<HeadingProps> = ({
|
|
|
52
54
|
accessibilityRole="header"
|
|
53
55
|
testID={testID}
|
|
54
56
|
numberOfLines={numberOfLines}
|
|
55
|
-
style={resolveHeadingTextStyle(theme, level, align)}
|
|
57
|
+
style={resolveHeadingTextStyle(theme, level, align, emphasis, color)}
|
|
56
58
|
>
|
|
57
59
|
{content}
|
|
58
60
|
</Text>
|
|
@@ -22,7 +22,7 @@ describe('resolveHeadingTextStyle', () => {
|
|
|
22
22
|
expect(style.fontFamily).toBe('SpaceGrotesk_700Regular');
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
-
it('shares the default content
|
|
25
|
+
it('shares the default content emphasis with the text primitive', () => {
|
|
26
26
|
const theme = createTheme();
|
|
27
27
|
const style = resolveHeadingTextStyle(theme, 2);
|
|
28
28
|
|