orn-ui 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/atoms/Avatar.js +1 -1
- package/lib/commonjs/atoms/Avatar.js.map +1 -1
- package/lib/commonjs/atoms/Badge.js +10 -8
- package/lib/commonjs/atoms/Badge.js.map +1 -1
- package/lib/commonjs/atoms/Button.js +8 -6
- package/lib/commonjs/atoms/Button.js.map +1 -1
- package/lib/commonjs/atoms/Checkbox.js +4 -1
- package/lib/commonjs/atoms/Checkbox.js.map +1 -1
- package/lib/commonjs/atoms/Fab.js +1 -1
- package/lib/commonjs/atoms/Fab.js.map +1 -1
- package/lib/commonjs/atoms/Image.js +2 -2
- package/lib/commonjs/atoms/Image.js.map +1 -1
- package/lib/commonjs/atoms/Input.js +2 -2
- package/lib/commonjs/atoms/Input.js.map +1 -1
- package/lib/commonjs/molecules/AvatarHeader.js +2 -2
- package/lib/commonjs/molecules/AvatarHeader.js.map +1 -1
- package/lib/commonjs/molecules/OptionCard.js +2 -2
- package/lib/commonjs/molecules/OptionCard.js.map +1 -1
- package/lib/commonjs/molecules/Steps.js +2 -2
- package/lib/commonjs/molecules/Steps.js.map +1 -1
- package/lib/commonjs/molecules/ThemeToggle.js +1 -1
- package/lib/commonjs/molecules/ThemeToggle.js.map +1 -1
- package/lib/commonjs/organisms/Alert.js +6 -5
- package/lib/commonjs/organisms/Alert.js.map +1 -1
- package/lib/commonjs/organisms/DateField.js +2 -2
- package/lib/commonjs/organisms/DateField.js.map +1 -1
- package/lib/commonjs/organisms/DatePicker.js +3 -3
- package/lib/commonjs/organisms/DatePicker.js.map +1 -1
- package/lib/commonjs/organisms/List.js +1 -1
- package/lib/commonjs/organisms/List.js.map +1 -1
- package/lib/commonjs/organisms/SearchList.js +2 -2
- package/lib/commonjs/organisms/SearchList.js.map +1 -1
- package/lib/commonjs/organisms/Select.js +4 -4
- package/lib/commonjs/organisms/Select.js.map +1 -1
- package/lib/commonjs/organisms/Toast.js +12 -3
- package/lib/commonjs/organisms/Toast.js.map +1 -1
- package/lib/commonjs/safe-area/SafeAreaUIProvider.js +65 -0
- package/lib/commonjs/safe-area/SafeAreaUIProvider.js.map +1 -0
- package/lib/commonjs/safe-area/index.js +13 -0
- package/lib/commonjs/safe-area/index.js.map +1 -0
- package/lib/commonjs/theme/UIProvider.js +11 -0
- package/lib/commonjs/theme/UIProvider.js.map +1 -1
- package/lib/commonjs/theme/palettes.js +70 -11
- package/lib/commonjs/theme/palettes.js.map +1 -1
- package/lib/module/atoms/Avatar.js +1 -1
- package/lib/module/atoms/Avatar.js.map +1 -1
- package/lib/module/atoms/Badge.js +10 -8
- package/lib/module/atoms/Badge.js.map +1 -1
- package/lib/module/atoms/Button.js +8 -6
- package/lib/module/atoms/Button.js.map +1 -1
- package/lib/module/atoms/Checkbox.js +4 -1
- package/lib/module/atoms/Checkbox.js.map +1 -1
- package/lib/module/atoms/Fab.js +1 -1
- package/lib/module/atoms/Fab.js.map +1 -1
- package/lib/module/atoms/Image.js +2 -2
- package/lib/module/atoms/Image.js.map +1 -1
- package/lib/module/atoms/Input.js +2 -2
- package/lib/module/atoms/Input.js.map +1 -1
- package/lib/module/molecules/AvatarHeader.js +2 -2
- package/lib/module/molecules/AvatarHeader.js.map +1 -1
- package/lib/module/molecules/OptionCard.js +2 -2
- package/lib/module/molecules/OptionCard.js.map +1 -1
- package/lib/module/molecules/Steps.js +2 -2
- package/lib/module/molecules/Steps.js.map +1 -1
- package/lib/module/molecules/ThemeToggle.js +1 -1
- package/lib/module/molecules/ThemeToggle.js.map +1 -1
- package/lib/module/organisms/Alert.js +6 -5
- package/lib/module/organisms/Alert.js.map +1 -1
- package/lib/module/organisms/DateField.js +2 -2
- package/lib/module/organisms/DateField.js.map +1 -1
- package/lib/module/organisms/DatePicker.js +3 -3
- package/lib/module/organisms/DatePicker.js.map +1 -1
- package/lib/module/organisms/List.js +1 -1
- package/lib/module/organisms/List.js.map +1 -1
- package/lib/module/organisms/SearchList.js +2 -2
- package/lib/module/organisms/SearchList.js.map +1 -1
- package/lib/module/organisms/Select.js +4 -4
- package/lib/module/organisms/Select.js.map +1 -1
- package/lib/module/organisms/Toast.js +12 -3
- package/lib/module/organisms/Toast.js.map +1 -1
- package/lib/module/safe-area/SafeAreaUIProvider.js +60 -0
- package/lib/module/safe-area/SafeAreaUIProvider.js.map +1 -0
- package/lib/module/safe-area/index.js +4 -0
- package/lib/module/safe-area/index.js.map +1 -0
- package/lib/module/theme/UIProvider.js +11 -0
- package/lib/module/theme/UIProvider.js.map +1 -1
- package/lib/module/theme/palettes.js +70 -11
- package/lib/module/theme/palettes.js.map +1 -1
- package/lib/typescript/atoms/Badge.d.ts.map +1 -1
- package/lib/typescript/atoms/Button.d.ts.map +1 -1
- package/lib/typescript/atoms/Checkbox.d.ts.map +1 -1
- package/lib/typescript/organisms/Alert.d.ts.map +1 -1
- package/lib/typescript/organisms/Toast.d.ts.map +1 -1
- package/lib/typescript/safe-area/SafeAreaUIProvider.d.ts +46 -0
- package/lib/typescript/safe-area/SafeAreaUIProvider.d.ts.map +1 -0
- package/lib/typescript/safe-area/index.d.ts +3 -0
- package/lib/typescript/safe-area/index.d.ts.map +1 -0
- package/lib/typescript/theme/UIProvider.d.ts.map +1 -1
- package/lib/typescript/theme/palettes.d.ts +41 -3
- package/lib/typescript/theme/palettes.d.ts.map +1 -1
- package/package.json +36 -14
- package/registry/alert.json +1 -1
- package/registry/avatar-header.json +1 -1
- package/registry/avatar.json +1 -1
- package/registry/badge.json +1 -1
- package/registry/button.json +1 -1
- package/registry/checkbox.json +1 -1
- package/registry/core.json +2 -2
- package/registry/date-field.json +1 -1
- package/registry/date-picker.json +1 -1
- package/registry/fab.json +1 -1
- package/registry/image.json +1 -1
- package/registry/index.json +19 -19
- package/registry/input.json +1 -1
- package/registry/list.json +1 -1
- package/registry/option-card.json +1 -1
- package/registry/search-list.json +1 -1
- package/registry/select.json +1 -1
- package/registry/steps.json +1 -1
- package/registry/theme-toggle.json +1 -1
- package/registry/toast.json +1 -1
- package/src/atoms/Avatar.tsx +1 -1
- package/src/atoms/Badge.tsx +6 -4
- package/src/atoms/Button.tsx +8 -6
- package/src/atoms/Checkbox.tsx +4 -1
- package/src/atoms/Fab.tsx +1 -1
- package/src/atoms/Image.tsx +2 -2
- package/src/atoms/Input.tsx +2 -2
- package/src/molecules/AvatarHeader.tsx +2 -2
- package/src/molecules/OptionCard.tsx +2 -2
- package/src/molecules/Steps.tsx +2 -2
- package/src/molecules/ThemeToggle.tsx +1 -1
- package/src/organisms/Alert.tsx +6 -5
- package/src/organisms/DateField.tsx +2 -2
- package/src/organisms/DatePicker.tsx +3 -3
- package/src/organisms/List.tsx +1 -1
- package/src/organisms/SearchList.tsx +2 -2
- package/src/organisms/Select.tsx +4 -4
- package/src/organisms/Toast.tsx +11 -3
- package/src/safe-area/SafeAreaUIProvider.tsx +67 -0
- package/src/safe-area/index.ts +2 -0
- package/src/theme/UIProvider.tsx +15 -0
- package/src/theme/palettes.ts +105 -11
package/registry/toast.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"files": [
|
|
10
10
|
{
|
|
11
11
|
"path": "organisms/Toast.tsx",
|
|
12
|
-
"content": "import React, { memo, useEffect, useRef } from 'react';\nimport { Animated, Pressable, Text, View, type StyleProp, type ViewStyle } from 'react-native';\nimport { createStyles } from '../theme/createStyles';\nimport { useAllowFontScaling, useColors } from '../theme/UIProvider';\nimport { Icon } from '../icons/Icon';\nimport type { IconName } from '../icons/types';\n\nexport type ToastVariant = 'success' | 'error' | 'warning' | 'info';\n\nexport interface ToastProps {\n title: string;\n message?: string;\n variant?: ToastVariant;\n /** Se dispara al tocar el toast (además de cerrarlo). */\n onPress?: () => void;\n onDismiss?: () => void;\n /** Oculta la X de cerrar. El toast igual se auto-descarta por tiempo. */\n hideCloseButton?: boolean;\n style?: StyleProp<ViewStyle>;\n testID?: string;\n}\n\nconst ICON_BY_VARIANT: Record<ToastVariant, IconName> = {\n success: 'check',\n error: 'alert',\n warning: 'warning',\n info: 'info',\n};\n\nconst useStyles = createStyles((theme) => ({\n container: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.tokens.spacing.md,\n backgroundColor: theme.colors.surface,\n borderRadius: theme.tokens.radius.lg,\n borderWidth: 1,\n borderColor: theme.colors.border,\n paddingVertical: theme.tokens.spacing.md,\n paddingHorizontal: theme.tokens.spacing.lg,\n ...theme.tokens.shadow.lg,\n },\n accent: {\n position: 'absolute',\n left: 0,\n top: 0,\n bottom: 0,\n width: 4,\n borderTopLeftRadius: theme.tokens.radius.lg,\n borderBottomLeftRadius: theme.tokens.radius.lg,\n },\n text: { flex: 1, gap: 2 },\n title: {\n fontSize: theme.tokens.fontSize.md,\n fontWeight: theme.tokens.fontWeight.semibold,\n color: theme.colors.text,\n },\n message: { fontSize: theme.tokens.fontSize.sm, color: theme.colors.textLight, lineHeight: theme.tokens.lineHeight.sm },\n}));\n\n/**\n * Toast\n * Notificación efímera. Normalmente no se usa directo: `ToastProvider` +\n * `useToast()` la montan y la descartan por vos. Se expone igual por si\n * querés colocarla vos mismo dentro de una pantalla concreta.\n */\nexport const Toast = memo(\n ({ title, message, variant = 'info', onPress, onDismiss, hideCloseButton, style, testID }: ToastProps) => {\n const colors = useColors();\n const styles = useStyles();\n const allowFontScaling = useAllowFontScaling();\n\n const
|
|
12
|
+
"content": "import React, { memo, useEffect, useRef } from 'react';\nimport { Animated, Pressable, Text, View, type StyleProp, type ViewStyle } from 'react-native';\nimport { createStyles } from '../theme/createStyles';\nimport { useAllowFontScaling, useColors } from '../theme/UIProvider';\nimport { Icon } from '../icons/Icon';\nimport type { IconName } from '../icons/types';\n\nexport type ToastVariant = 'success' | 'error' | 'warning' | 'info';\n\nexport interface ToastProps {\n title: string;\n message?: string;\n variant?: ToastVariant;\n /** Se dispara al tocar el toast (además de cerrarlo). */\n onPress?: () => void;\n onDismiss?: () => void;\n /** Oculta la X de cerrar. El toast igual se auto-descarta por tiempo. */\n hideCloseButton?: boolean;\n style?: StyleProp<ViewStyle>;\n testID?: string;\n}\n\nconst ICON_BY_VARIANT: Record<ToastVariant, IconName> = {\n success: 'check',\n error: 'alert',\n warning: 'warning',\n info: 'info',\n};\n\nconst useStyles = createStyles((theme) => ({\n container: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.tokens.spacing.md,\n backgroundColor: theme.colors.surface,\n borderRadius: theme.tokens.radius.lg,\n borderWidth: 1,\n borderColor: theme.colors.border,\n paddingVertical: theme.tokens.spacing.md,\n paddingHorizontal: theme.tokens.spacing.lg,\n ...theme.tokens.shadow.lg,\n },\n accent: {\n position: 'absolute',\n left: 0,\n top: 0,\n bottom: 0,\n width: 4,\n borderTopLeftRadius: theme.tokens.radius.lg,\n borderBottomLeftRadius: theme.tokens.radius.lg,\n },\n text: { flex: 1, gap: 2 },\n title: {\n fontSize: theme.tokens.fontSize.md,\n fontWeight: theme.tokens.fontWeight.semibold,\n color: theme.colors.text,\n },\n message: { fontSize: theme.tokens.fontSize.sm, color: theme.colors.textLight, lineHeight: theme.tokens.lineHeight.sm },\n}));\n\n/**\n * Toast\n * Notificación efímera. Normalmente no se usa directo: `ToastProvider` +\n * `useToast()` la montan y la descartan por vos. Se expone igual por si\n * querés colocarla vos mismo dentro de una pantalla concreta.\n */\nexport const Toast = memo(\n ({ title, message, variant = 'info', onPress, onDismiss, hideCloseButton, style, testID }: ToastProps) => {\n const colors = useColors();\n const styles = useStyles();\n const allowFontScaling = useAllowFontScaling();\n\n // La barra lateral es relleno (acento pleno); el ícono es contenido\n // sobre la superficie del toast y necesita el rol `*Text`.\n const barColor: Record<ToastVariant, string> = {\n success: colors.success,\n error: colors.error,\n warning: colors.warning,\n info: colors.secondary,\n };\n const iconColor: Record<ToastVariant, string> = {\n success: colors.successText,\n error: colors.errorText,\n warning: colors.warningText,\n info: colors.secondaryText,\n };\n\n const body = (\n <View style={[styles.container, style]} testID={testID} accessibilityRole=\"alert\">\n <View style={[styles.accent, { backgroundColor: barColor[variant] }]} />\n <Icon name={ICON_BY_VARIANT[variant]} size={22} color={iconColor[variant]} />\n <View style={styles.text}>\n <Text allowFontScaling={allowFontScaling} style={styles.title}>\n {title}\n </Text>\n {!!message && (\n <Text allowFontScaling={allowFontScaling} style={styles.message}>\n {message}\n </Text>\n )}\n </View>\n {!hideCloseButton && !!onDismiss && (\n <Pressable onPress={onDismiss} accessibilityRole=\"button\" accessibilityLabel=\"Dismiss\" hitSlop={8}>\n <Icon name=\"close\" size={18} color={colors.textLight} />\n </Pressable>\n )}\n </View>\n );\n\n if (!onPress) return body;\n\n return (\n <Pressable onPress={onPress} accessibilityRole=\"button\" accessibilityLabel={title}>\n {body}\n </Pressable>\n );\n }\n);\nToast.displayName = 'Toast';\n\n/** Envuelve un Toast con su animación de entrada/salida. Uso interno del provider. */\nexport const AnimatedToast = memo(\n ({ children, onHeight }: { children: React.ReactNode; onHeight?: (h: number) => void }) => {\n const progress = useRef(new Animated.Value(0)).current;\n\n useEffect(() => {\n Animated.spring(progress, { toValue: 1, useNativeDriver: true, speed: 14, bounciness: 4 }).start();\n }, [progress]);\n\n return (\n <Animated.View\n onLayout={(e) => onHeight?.(e.nativeEvent.layout.height)}\n style={{\n opacity: progress,\n transform: [{ translateY: progress.interpolate({ inputRange: [0, 1], outputRange: [-16, 0] }) }],\n }}\n >\n {children}\n </Animated.View>\n );\n }\n);\nAnimatedToast.displayName = 'AnimatedToast';\n"
|
|
13
13
|
}
|
|
14
14
|
],
|
|
15
15
|
"registryDependencies": [
|
package/src/atoms/Avatar.tsx
CHANGED
|
@@ -28,7 +28,7 @@ export const Avatar = memo(({ size = 44, backgroundColor, children, style }: Ava
|
|
|
28
28
|
width: size,
|
|
29
29
|
height: size,
|
|
30
30
|
borderRadius: size / 2,
|
|
31
|
-
backgroundColor: backgroundColor || colors.
|
|
31
|
+
backgroundColor: backgroundColor || colors.primarySoft,
|
|
32
32
|
},
|
|
33
33
|
style,
|
|
34
34
|
]}
|
package/src/atoms/Badge.tsx
CHANGED
|
@@ -37,10 +37,12 @@ export const Badge = memo(({ label, variant = 'neutral', backgroundColor, textCo
|
|
|
37
37
|
const { colors } = theme;
|
|
38
38
|
|
|
39
39
|
const palette: Record<BadgeVariant, { bg: string; fg: string }> = {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
// fg es el rol `*Text`, no el acento pleno: el acento sobre su propio
|
|
41
|
+
// tinte da ~2.2:1 en light — el label quedaba ilegible.
|
|
42
|
+
success: { bg: colors.successSoft, fg: colors.successText },
|
|
43
|
+
error: { bg: colors.errorSoft, fg: colors.errorText },
|
|
44
|
+
warning: { bg: colors.warningSoft, fg: colors.warningText },
|
|
45
|
+
info: { bg: colors.secondarySoft, fg: colors.secondaryText },
|
|
44
46
|
neutral: { bg: colors.inputBackground, fg: colors.textLight },
|
|
45
47
|
};
|
|
46
48
|
|
package/src/atoms/Button.tsx
CHANGED
|
@@ -65,19 +65,21 @@ function resolveColors(variant: ButtonVariant, disabled: boolean, colors: Return
|
|
|
65
65
|
return { background: colors.inputBackground, text: colors.textLight, border: 'transparent' };
|
|
66
66
|
}
|
|
67
67
|
switch (variant) {
|
|
68
|
+
// Las variantes sin relleno pintan texto sobre el fondo de la pantalla:
|
|
69
|
+
// van con el rol `*Text`. Las rellenas van con `on*` sobre el acento.
|
|
68
70
|
case 'outline':
|
|
69
|
-
return { background: 'transparent', text: colors.
|
|
71
|
+
return { background: 'transparent', text: colors.primaryText, border: colors.primary };
|
|
70
72
|
case 'ghost':
|
|
71
|
-
return { background: 'transparent', text: colors.
|
|
73
|
+
return { background: 'transparent', text: colors.primaryText, border: 'transparent' };
|
|
72
74
|
case 'link':
|
|
73
|
-
return { background: 'transparent', text: colors.
|
|
75
|
+
return { background: 'transparent', text: colors.primaryText, border: 'transparent' };
|
|
74
76
|
case 'secondary':
|
|
75
|
-
return { background: colors.secondary, text: colors.
|
|
77
|
+
return { background: colors.secondary, text: colors.onSecondary, border: 'transparent' };
|
|
76
78
|
case 'destructive':
|
|
77
|
-
return { background: colors.error, text: colors.
|
|
79
|
+
return { background: colors.error, text: colors.onError, border: 'transparent' };
|
|
78
80
|
case 'primary':
|
|
79
81
|
default:
|
|
80
|
-
return { background: colors.primary, text: colors.
|
|
82
|
+
return { background: colors.primary, text: colors.onPrimary, border: 'transparent' };
|
|
81
83
|
}
|
|
82
84
|
}
|
|
83
85
|
|
package/src/atoms/Checkbox.tsx
CHANGED
|
@@ -32,6 +32,9 @@ export const Checkbox = memo(({ value, onValueChange, label, color, disabled, te
|
|
|
32
32
|
const styles = useStyles();
|
|
33
33
|
const allowFontScaling = useAllowFontScaling();
|
|
34
34
|
const activeColor = color || colors.primary;
|
|
35
|
+
// El check va encima del relleno: con `color` propio no sabemos qué tono
|
|
36
|
+
// contrasta, así que ahí seguimos con blanco (decisión del consumidor).
|
|
37
|
+
const checkColor = color ? colors.white : colors.onPrimary;
|
|
35
38
|
const progress = useRef(new Animated.Value(value ? 1 : 0)).current;
|
|
36
39
|
const checkScale = useRef(new Animated.Value(value ? 1 : 0)).current;
|
|
37
40
|
|
|
@@ -61,7 +64,7 @@ export const Checkbox = memo(({ value, onValueChange, label, color, disabled, te
|
|
|
61
64
|
>
|
|
62
65
|
<Animated.View style={[styles.box, { backgroundColor, borderColor, opacity: disabled ? 0.5 : 1 }]}>
|
|
63
66
|
<Animated.View style={{ transform: [{ scale: checkScale }] }}>
|
|
64
|
-
<Icon name="check" size={16} color={
|
|
67
|
+
<Icon name="check" size={16} color={checkColor} />
|
|
65
68
|
</Animated.View>
|
|
66
69
|
</Animated.View>
|
|
67
70
|
{label && (
|
package/src/atoms/Fab.tsx
CHANGED
|
@@ -55,7 +55,7 @@ export const Fab = memo(
|
|
|
55
55
|
accessibilityRole="button"
|
|
56
56
|
accessibilityLabel={accessibilityLabel}
|
|
57
57
|
>
|
|
58
|
-
{icon ?? <Icon name={iconName} size={size * 0.5} color={colors.
|
|
58
|
+
{icon ?? <Icon name={iconName} size={size * 0.5} color={colors.onPrimary} />}
|
|
59
59
|
</PressableScale>
|
|
60
60
|
);
|
|
61
61
|
}
|
package/src/atoms/Image.tsx
CHANGED
|
@@ -40,9 +40,9 @@ export interface ImageProps {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
const useStyles = createStyles((theme) => ({
|
|
43
|
-
container: { overflow: 'hidden', backgroundColor: theme.colors.
|
|
43
|
+
container: { overflow: 'hidden', backgroundColor: theme.colors.skeleton },
|
|
44
44
|
overlay: { alignItems: 'center', justifyContent: 'center' },
|
|
45
|
-
fallback: { flex: 1, backgroundColor: theme.colors.
|
|
45
|
+
fallback: { flex: 1, backgroundColor: theme.colors.skeleton },
|
|
46
46
|
}));
|
|
47
47
|
|
|
48
48
|
function sourceUri(source: ImageSourcePropType): string | undefined {
|
package/src/atoms/Input.tsx
CHANGED
|
@@ -37,7 +37,7 @@ const useStyles = createStyles((theme) => ({
|
|
|
37
37
|
fontWeight: theme.tokens.fontWeight.medium,
|
|
38
38
|
color: theme.colors.text,
|
|
39
39
|
},
|
|
40
|
-
required: { color: theme.colors.
|
|
40
|
+
required: { color: theme.colors.errorText },
|
|
41
41
|
inputWrapper: {
|
|
42
42
|
flexDirection: 'row',
|
|
43
43
|
alignItems: 'center',
|
|
@@ -55,7 +55,7 @@ const useStyles = createStyles((theme) => ({
|
|
|
55
55
|
},
|
|
56
56
|
leftIcon: { marginLeft: theme.tokens.spacing.lg, marginRight: -theme.tokens.spacing.xs },
|
|
57
57
|
rightIcon: { padding: theme.tokens.spacing.sm + 2, marginRight: theme.tokens.spacing.xs },
|
|
58
|
-
errorText: { marginTop: theme.tokens.spacing.xs, fontSize: theme.tokens.fontSize.sm, color: theme.colors.
|
|
58
|
+
errorText: { marginTop: theme.tokens.spacing.xs, fontSize: theme.tokens.fontSize.sm, color: theme.colors.errorText },
|
|
59
59
|
}));
|
|
60
60
|
|
|
61
61
|
/**
|
|
@@ -22,12 +22,12 @@ const useStyles = createStyles((theme) => ({
|
|
|
22
22
|
width: 80,
|
|
23
23
|
height: 80,
|
|
24
24
|
borderRadius: 40,
|
|
25
|
-
backgroundColor: theme.colors.
|
|
25
|
+
backgroundColor: theme.colors.primarySoft,
|
|
26
26
|
justifyContent: 'center',
|
|
27
27
|
alignItems: 'center',
|
|
28
28
|
marginBottom: theme.tokens.spacing.md,
|
|
29
29
|
},
|
|
30
|
-
initials: { fontSize: theme.tokens.fontSize.xxl, fontWeight: theme.tokens.fontWeight.bold, color: theme.colors.
|
|
30
|
+
initials: { fontSize: theme.tokens.fontSize.xxl, fontWeight: theme.tokens.fontWeight.bold, color: theme.colors.primaryText },
|
|
31
31
|
title: { fontSize: theme.tokens.fontSize.xl, fontWeight: theme.tokens.fontWeight.bold, textAlign: 'center', color: theme.colors.text, marginBottom: theme.tokens.spacing.xs },
|
|
32
32
|
subtitle: { fontSize: theme.tokens.fontSize.md, color: theme.colors.textLight },
|
|
33
33
|
}));
|
|
@@ -29,14 +29,14 @@ const useStyles = createStyles((theme) => ({
|
|
|
29
29
|
cardVertical: { width: '31%', padding: theme.tokens.spacing.sm, gap: 5, minHeight: 100 },
|
|
30
30
|
cardSelected: {
|
|
31
31
|
borderColor: theme.colors.primary,
|
|
32
|
-
backgroundColor: theme.colors.
|
|
32
|
+
backgroundColor: theme.colors.primarySoft,
|
|
33
33
|
borderWidth: 1.5,
|
|
34
34
|
elevation: 0,
|
|
35
35
|
shadowOpacity: 0,
|
|
36
36
|
},
|
|
37
37
|
label: { color: theme.colors.textLight, fontWeight: theme.tokens.fontWeight.medium },
|
|
38
38
|
labelVertical: { fontSize: theme.tokens.fontSize.xs, textAlign: 'center' },
|
|
39
|
-
labelSelected: { color: theme.colors.
|
|
39
|
+
labelSelected: { color: theme.colors.primaryText },
|
|
40
40
|
}));
|
|
41
41
|
|
|
42
42
|
/**
|
package/src/molecules/Steps.tsx
CHANGED
|
@@ -82,8 +82,8 @@ export const Steps = memo(
|
|
|
82
82
|
const isVertical = orientation === 'vertical';
|
|
83
83
|
|
|
84
84
|
const colorsFor = (status: StepStatus) => {
|
|
85
|
-
if (status === 'completed') return { bg: colors.primary, border: colors.primary, fg: colors.
|
|
86
|
-
if (status === 'current') return { bg: 'transparent', border: colors.primary, fg: colors.
|
|
85
|
+
if (status === 'completed') return { bg: colors.primary, border: colors.primary, fg: colors.onPrimary };
|
|
86
|
+
if (status === 'current') return { bg: 'transparent', border: colors.primary, fg: colors.primaryText };
|
|
87
87
|
return { bg: 'transparent', border: colors.border, fg: colors.textLight };
|
|
88
88
|
};
|
|
89
89
|
|
|
@@ -26,7 +26,7 @@ const useStyles = createStyles((theme) => ({
|
|
|
26
26
|
},
|
|
27
27
|
segmentActive: { backgroundColor: theme.colors.surface, ...theme.tokens.shadow.sm },
|
|
28
28
|
label: { fontSize: theme.tokens.fontSize.sm, fontWeight: theme.tokens.fontWeight.medium, color: theme.colors.textLight },
|
|
29
|
-
labelActive: { color: theme.colors.
|
|
29
|
+
labelActive: { color: theme.colors.primaryText, fontWeight: theme.tokens.fontWeight.semibold },
|
|
30
30
|
}));
|
|
31
31
|
|
|
32
32
|
/**
|
package/src/organisms/Alert.tsx
CHANGED
|
@@ -91,11 +91,12 @@ export const Alert = memo((props: AlertProps) => {
|
|
|
91
91
|
if (!visible) return null;
|
|
92
92
|
|
|
93
93
|
const iconColor: Record<AlertType, string> = {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
94
|
+
// Íconos sobre la superficie del diálogo: rol `*Text`, no el acento pleno.
|
|
95
|
+
success: colors.successText,
|
|
96
|
+
error: colors.errorText,
|
|
97
|
+
warning: colors.warningText,
|
|
98
|
+
question: colors.primaryText,
|
|
99
|
+
info: colors.secondaryText,
|
|
99
100
|
};
|
|
100
101
|
|
|
101
102
|
const effectiveButtons = resolveButtons(props, { confirm: labels.confirm, cancel: labels.cancel, close: labels.close });
|
|
@@ -30,7 +30,7 @@ function defaultFormat(date: Date, monthNames: string[]): string {
|
|
|
30
30
|
const useStyles = createStyles((theme) => ({
|
|
31
31
|
container: { marginBottom: theme.tokens.spacing.lg, width: '100%', gap: theme.tokens.spacing.sm },
|
|
32
32
|
label: { fontSize: theme.tokens.fontSize.md, fontWeight: theme.tokens.fontWeight.medium, color: theme.colors.text },
|
|
33
|
-
required: { color: theme.colors.
|
|
33
|
+
required: { color: theme.colors.errorText },
|
|
34
34
|
field: {
|
|
35
35
|
flexDirection: 'row',
|
|
36
36
|
alignItems: 'center',
|
|
@@ -45,7 +45,7 @@ const useStyles = createStyles((theme) => ({
|
|
|
45
45
|
fieldError: { borderColor: theme.colors.error },
|
|
46
46
|
fieldText: { fontSize: theme.tokens.fontSize.lg, color: theme.colors.text },
|
|
47
47
|
placeholder: { color: theme.colors.textLight },
|
|
48
|
-
errorText: { fontSize: theme.tokens.fontSize.sm, color: theme.colors.
|
|
48
|
+
errorText: { fontSize: theme.tokens.fontSize.sm, color: theme.colors.errorText },
|
|
49
49
|
}));
|
|
50
50
|
|
|
51
51
|
/**
|
|
@@ -110,13 +110,13 @@ const useStyles = createStyles((theme) => ({
|
|
|
110
110
|
dayButton: { width: 36, height: 36, borderRadius: 18, alignItems: 'center', justifyContent: 'center' },
|
|
111
111
|
dayText: { fontSize: theme.tokens.fontSize.md, color: theme.colors.text },
|
|
112
112
|
daySelected: { backgroundColor: theme.colors.primary },
|
|
113
|
-
dayTextSelected: { color: theme.colors.
|
|
113
|
+
dayTextSelected: { color: theme.colors.onPrimary, fontWeight: theme.tokens.fontWeight.bold },
|
|
114
114
|
// El resaltado del tramo intermedio va en la celda (cuadrada, sin gaps) y
|
|
115
115
|
// no en el botón redondo, así la barra del rango se ve continua.
|
|
116
|
-
cellInRange: { backgroundColor: theme.colors.
|
|
116
|
+
cellInRange: { backgroundColor: theme.colors.primarySoft },
|
|
117
117
|
cellRangeStart: { borderTopLeftRadius: 18, borderBottomLeftRadius: 18 },
|
|
118
118
|
cellRangeEnd: { borderTopRightRadius: 18, borderBottomRightRadius: 18 },
|
|
119
|
-
dayTextInRange: { color: theme.colors.
|
|
119
|
+
dayTextInRange: { color: theme.colors.primaryText, fontWeight: theme.tokens.fontWeight.semibold },
|
|
120
120
|
dayToday: { borderWidth: 1, borderColor: theme.colors.primary },
|
|
121
121
|
dayTextDisabled: { color: theme.colors.textLight, opacity: 0.4 },
|
|
122
122
|
}));
|
package/src/organisms/List.tsx
CHANGED
|
@@ -57,7 +57,7 @@ const useStyles = createStyles((theme) => ({
|
|
|
57
57
|
left: 0,
|
|
58
58
|
right: 0,
|
|
59
59
|
bottom: 0,
|
|
60
|
-
backgroundColor: theme.colors.
|
|
60
|
+
backgroundColor: theme.colors.scrim,
|
|
61
61
|
zIndex: 10,
|
|
62
62
|
justifyContent: 'center',
|
|
63
63
|
alignItems: 'center',
|
|
@@ -147,7 +147,7 @@ export function SearchList<T>({
|
|
|
147
147
|
<IconButton
|
|
148
148
|
iconName="search"
|
|
149
149
|
onPress={onScanPress}
|
|
150
|
-
color={colors.
|
|
150
|
+
color={colors.onPrimary}
|
|
151
151
|
style={styles.scanButton}
|
|
152
152
|
accessibilityLabel={scanAccessibilityLabel}
|
|
153
153
|
/>
|
package/src/organisms/Select.tsx
CHANGED
|
@@ -25,7 +25,7 @@ const useStyles = createStyles((theme) => ({
|
|
|
25
25
|
container: { gap: theme.tokens.spacing.sm },
|
|
26
26
|
containerOpen: { zIndex: 20, elevation: 20 },
|
|
27
27
|
label: { fontWeight: theme.tokens.fontWeight.bold, fontSize: theme.tokens.fontSize.md, color: theme.colors.text },
|
|
28
|
-
required: { color: theme.colors.
|
|
28
|
+
required: { color: theme.colors.errorText },
|
|
29
29
|
field: {
|
|
30
30
|
flexDirection: 'row',
|
|
31
31
|
alignItems: 'center',
|
|
@@ -64,10 +64,10 @@ const useStyles = createStyles((theme) => ({
|
|
|
64
64
|
borderBottomColor: theme.colors.border,
|
|
65
65
|
},
|
|
66
66
|
optionRowLast: { borderBottomWidth: 0 },
|
|
67
|
-
optionRowSelected: { backgroundColor: theme.colors.
|
|
67
|
+
optionRowSelected: { backgroundColor: theme.colors.primarySoft },
|
|
68
68
|
optionText: { fontSize: theme.tokens.fontSize.lg - 1, color: theme.colors.text },
|
|
69
|
-
optionTextSelected: { fontWeight: theme.tokens.fontWeight.semibold, color: theme.colors.
|
|
70
|
-
errorText: { fontSize: theme.tokens.fontSize.sm, color: theme.colors.
|
|
69
|
+
optionTextSelected: { fontWeight: theme.tokens.fontWeight.semibold, color: theme.colors.primaryText },
|
|
70
|
+
errorText: { fontSize: theme.tokens.fontSize.sm, color: theme.colors.errorText },
|
|
71
71
|
}));
|
|
72
72
|
|
|
73
73
|
/**
|
package/src/organisms/Toast.tsx
CHANGED
|
@@ -70,17 +70,25 @@ export const Toast = memo(
|
|
|
70
70
|
const styles = useStyles();
|
|
71
71
|
const allowFontScaling = useAllowFontScaling();
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
// La barra lateral es relleno (acento pleno); el ícono es contenido
|
|
74
|
+
// sobre la superficie del toast y necesita el rol `*Text`.
|
|
75
|
+
const barColor: Record<ToastVariant, string> = {
|
|
74
76
|
success: colors.success,
|
|
75
77
|
error: colors.error,
|
|
76
78
|
warning: colors.warning,
|
|
77
79
|
info: colors.secondary,
|
|
78
80
|
};
|
|
81
|
+
const iconColor: Record<ToastVariant, string> = {
|
|
82
|
+
success: colors.successText,
|
|
83
|
+
error: colors.errorText,
|
|
84
|
+
warning: colors.warningText,
|
|
85
|
+
info: colors.secondaryText,
|
|
86
|
+
};
|
|
79
87
|
|
|
80
88
|
const body = (
|
|
81
89
|
<View style={[styles.container, style]} testID={testID} accessibilityRole="alert">
|
|
82
|
-
<View style={[styles.accent, { backgroundColor:
|
|
83
|
-
<Icon name={ICON_BY_VARIANT[variant]} size={22} color={
|
|
90
|
+
<View style={[styles.accent, { backgroundColor: barColor[variant] }]} />
|
|
91
|
+
<Icon name={ICON_BY_VARIANT[variant]} size={22} color={iconColor[variant]} />
|
|
84
92
|
<View style={styles.text}>
|
|
85
93
|
<Text allowFontScaling={allowFontScaling} style={styles.title}>
|
|
86
94
|
{title}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
3
|
+
import { UIProvider, type UIProviderProps } from '../theme/UIProvider';
|
|
4
|
+
|
|
5
|
+
export interface SafeAreaUIProviderProps extends Omit<UIProviderProps, 'insets'> {
|
|
6
|
+
/**
|
|
7
|
+
* Insets explícitos. Ganan sobre los medidos — útil para tests, storybook o
|
|
8
|
+
* una pantalla embebida que no ocupa la ventana entera.
|
|
9
|
+
*/
|
|
10
|
+
insets?: UIProviderProps['insets'];
|
|
11
|
+
/**
|
|
12
|
+
* Montar también el `<SafeAreaProvider>`. Ponelo en false si tu app ya tiene
|
|
13
|
+
* uno arriba (React Navigation lo monta solo en algunas plantillas):
|
|
14
|
+
* un provider anidado mide el frame de *su* View, no el de la ventana, así
|
|
15
|
+
* que ahí adentro los insets darían cero.
|
|
16
|
+
* @default true
|
|
17
|
+
*/
|
|
18
|
+
mountSafeAreaProvider?: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function Measured({ insets: override, children, ...rest }: SafeAreaUIProviderProps) {
|
|
22
|
+
const measured = useSafeAreaInsets();
|
|
23
|
+
return (
|
|
24
|
+
<UIProvider insets={override ?? measured} {...rest}>
|
|
25
|
+
{children}
|
|
26
|
+
</UIProvider>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* SafeAreaUIProvider
|
|
32
|
+
* `UIProvider` con los insets ya cableados desde `react-native-safe-area-context`.
|
|
33
|
+
*
|
|
34
|
+
* Vive en su propio subpath (`orn-ui/safe-area`) a propósito: es el único
|
|
35
|
+
* archivo de la librería que importa un paquete de terceros. Nada del entry
|
|
36
|
+
* principal lo referencia, así que quien hace `import { Button } from 'orn-ui'`
|
|
37
|
+
* nunca lo resuelve y el bundle sigue sin dependencias de runtime.
|
|
38
|
+
*
|
|
39
|
+
* ```tsx
|
|
40
|
+
* import { SafeAreaUIProvider } from 'orn-ui/safe-area';
|
|
41
|
+
*
|
|
42
|
+
* export default function App() {
|
|
43
|
+
* return (
|
|
44
|
+
* <SafeAreaUIProvider defaultMode="system">
|
|
45
|
+
* <RootNavigator />
|
|
46
|
+
* </SafeAreaUIProvider>
|
|
47
|
+
* );
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* El equivalente a mano — pasarle `insets={useSafeAreaInsets()}` a `UIProvider`
|
|
52
|
+
* desde un componente que ya esté dentro de `<SafeAreaProvider>` — sigue
|
|
53
|
+
* siendo válido. Esto sólo evita el error silencioso de olvidarlo: `insets`
|
|
54
|
+
* por defecto es `{0,0,0,0}`, y con ceros el bottom sheet queda pegado contra
|
|
55
|
+
* la barra de gestos y el modal `full` se mete abajo del notch.
|
|
56
|
+
*/
|
|
57
|
+
export function SafeAreaUIProvider({
|
|
58
|
+
mountSafeAreaProvider = true,
|
|
59
|
+
...props
|
|
60
|
+
}: SafeAreaUIProviderProps) {
|
|
61
|
+
if (!mountSafeAreaProvider) return <Measured {...props} />;
|
|
62
|
+
return (
|
|
63
|
+
<SafeAreaProvider>
|
|
64
|
+
<Measured {...props} />
|
|
65
|
+
</SafeAreaProvider>
|
|
66
|
+
);
|
|
67
|
+
}
|
package/src/theme/UIProvider.tsx
CHANGED
|
@@ -21,6 +21,9 @@ interface UIContextValue {
|
|
|
21
21
|
|
|
22
22
|
const UIContext = createContext<UIContextValue | undefined>(undefined);
|
|
23
23
|
|
|
24
|
+
/** Una sola vez por sesión: en un re-render el aviso no aporta nada nuevo. */
|
|
25
|
+
let warnedAboutInsets = false;
|
|
26
|
+
|
|
24
27
|
export interface UIProviderProps {
|
|
25
28
|
children: React.ReactNode;
|
|
26
29
|
/** Par light/dark. Por defecto el theme de marca de la librería (créalo con createTheme()). */
|
|
@@ -70,6 +73,18 @@ export function UIProvider({
|
|
|
70
73
|
[isControlled, onModeChange]
|
|
71
74
|
);
|
|
72
75
|
|
|
76
|
+
// Olvidar `insets` no rompe nada visible al montar: el default de ceros
|
|
77
|
+
// recién se nota cuando abrís un Modal `full` (se mete abajo del notch) o un
|
|
78
|
+
// BottomSheet (queda pegado a la barra de gestos). El aviso llega antes.
|
|
79
|
+
if (__DEV__ && insets === zeroInsets && !warnedAboutInsets) {
|
|
80
|
+
warnedAboutInsets = true;
|
|
81
|
+
console.warn(
|
|
82
|
+
'orn-ui: <UIProvider> sin `insets`, se usan {top:0,bottom:0,left:0,right:0}. ' +
|
|
83
|
+
'Los modales y el Screen quedan sin safe area. Pasá `insets={useSafeAreaInsets()}` ' +
|
|
84
|
+
"o usá <SafeAreaUIProvider> de 'orn-ui/safe-area', que lo cablea solo."
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
73
88
|
const scheme: 'light' | 'dark' =
|
|
74
89
|
mode === 'system' ? (systemScheme === 'dark' ? 'dark' : 'light') : mode;
|
|
75
90
|
|
package/src/theme/palettes.ts
CHANGED
|
@@ -2,15 +2,49 @@
|
|
|
2
2
|
* Cada color es `string`, no un literal (`as const`): light y dark tienen
|
|
3
3
|
* valores distintos para la misma clave, y createTheme() debe poder
|
|
4
4
|
* aceptar cualquier hex/rgba en los overrides — literal typing lo impediría.
|
|
5
|
+
*
|
|
6
|
+
* Cada acento viene en cuatro roles, y no son intercambiables:
|
|
7
|
+
*
|
|
8
|
+
* `primary` relleno sólido (fondo de botón, día seleccionado, FAB).
|
|
9
|
+
* `onPrimary` texto/ícono *encima* de ese relleno.
|
|
10
|
+
* `primarySoft` fondo teñido para estados seleccionados y pills.
|
|
11
|
+
* `primaryText` texto/ícono del acento sobre `surface`, `background`
|
|
12
|
+
* o sobre su propio `primarySoft`.
|
|
13
|
+
*
|
|
14
|
+
* El motivo es el contraste: un acento que se lee bien como relleno no se
|
|
15
|
+
* lee como texto. Antes los componentes usaban `colors.primary` para las dos
|
|
16
|
+
* cosas y lo teñían concatenando alpha al hex (`colors.primary + '15'`), lo
|
|
17
|
+
* que en dark daba 2.6:1 sobre la superficie — muy por debajo del 4.5:1 de
|
|
18
|
+
* WCAG AA. Todos los pares de esta paleta pasan AA en ambos esquemas.
|
|
5
19
|
*/
|
|
6
20
|
export interface ThemeColors {
|
|
7
21
|
primary: string;
|
|
22
|
+
onPrimary: string;
|
|
23
|
+
primarySoft: string;
|
|
24
|
+
primaryText: string;
|
|
25
|
+
|
|
8
26
|
secondary: string;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
27
|
+
onSecondary: string;
|
|
28
|
+
secondarySoft: string;
|
|
29
|
+
secondaryText: string;
|
|
30
|
+
|
|
12
31
|
success: string;
|
|
32
|
+
onSuccess: string;
|
|
33
|
+
successSoft: string;
|
|
34
|
+
successText: string;
|
|
35
|
+
|
|
36
|
+
error: string;
|
|
37
|
+
onError: string;
|
|
38
|
+
errorSoft: string;
|
|
39
|
+
errorText: string;
|
|
40
|
+
|
|
13
41
|
warning: string;
|
|
42
|
+
onWarning: string;
|
|
43
|
+
warningSoft: string;
|
|
44
|
+
warningText: string;
|
|
45
|
+
|
|
46
|
+
white: string;
|
|
47
|
+
black: string;
|
|
14
48
|
background: string;
|
|
15
49
|
surface: string;
|
|
16
50
|
text: string;
|
|
@@ -18,20 +52,45 @@ export interface ThemeColors {
|
|
|
18
52
|
border: string;
|
|
19
53
|
inputBackground: string;
|
|
20
54
|
overlay: string;
|
|
55
|
+
/** Velo semitransparente sobre contenido propio (footer de carga de List). */
|
|
56
|
+
scrim: string;
|
|
57
|
+
/** Fondo de placeholder mientras carga una imagen. */
|
|
58
|
+
skeleton: string;
|
|
21
59
|
}
|
|
22
60
|
|
|
23
|
-
const
|
|
24
|
-
primary: '#004cef',
|
|
25
|
-
secondary: '#00cae1',
|
|
61
|
+
const neutral = {
|
|
26
62
|
white: '#ffffff',
|
|
27
63
|
black: '#000000',
|
|
28
|
-
error: '#ff3b30',
|
|
29
|
-
success: '#34c759',
|
|
30
|
-
warning: '#f59e0b',
|
|
31
64
|
};
|
|
32
65
|
|
|
33
66
|
export const lightPalette: ThemeColors = {
|
|
34
|
-
...
|
|
67
|
+
...neutral,
|
|
68
|
+
|
|
69
|
+
primary: '#004cef',
|
|
70
|
+
onPrimary: '#ffffff',
|
|
71
|
+
primarySoft: '#e6edfe',
|
|
72
|
+
primaryText: '#00369f',
|
|
73
|
+
|
|
74
|
+
secondary: '#00cae1',
|
|
75
|
+
onSecondary: '#00363d',
|
|
76
|
+
secondarySoft: '#dcf6f9',
|
|
77
|
+
secondaryText: '#00707d',
|
|
78
|
+
|
|
79
|
+
success: '#34c759',
|
|
80
|
+
onSuccess: '#00320f',
|
|
81
|
+
successSoft: '#e3f6e9',
|
|
82
|
+
successText: '#116a30',
|
|
83
|
+
|
|
84
|
+
error: '#ff3b30',
|
|
85
|
+
onError: '#3d0300',
|
|
86
|
+
errorSoft: '#fdeaea',
|
|
87
|
+
errorText: '#c62222',
|
|
88
|
+
|
|
89
|
+
warning: '#f59e0b',
|
|
90
|
+
onWarning: '#3d2600',
|
|
91
|
+
warningSoft: '#fdf1de',
|
|
92
|
+
warningText: '#8a4b00',
|
|
93
|
+
|
|
35
94
|
background: '#f8f9fa',
|
|
36
95
|
surface: '#ffffff',
|
|
37
96
|
text: '#333333',
|
|
@@ -39,10 +98,43 @@ export const lightPalette: ThemeColors = {
|
|
|
39
98
|
border: '#e5e7eb',
|
|
40
99
|
inputBackground: '#f5f7fa',
|
|
41
100
|
overlay: 'rgba(0,0,0,0.5)',
|
|
101
|
+
scrim: 'rgba(248,249,250,0.8)',
|
|
102
|
+
skeleton: '#eceef1',
|
|
42
103
|
};
|
|
43
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Los acentos de dark NO son los de light: sobre `#1e1e1e` hay que subir la
|
|
107
|
+
* luminosidad del acento y bajar la del texto que va encima (por eso
|
|
108
|
+
* `onPrimary` es azul oscuro acá y blanco en light).
|
|
109
|
+
*/
|
|
44
110
|
export const darkPalette: ThemeColors = {
|
|
45
|
-
...
|
|
111
|
+
...neutral,
|
|
112
|
+
|
|
113
|
+
primary: '#7ba4ff',
|
|
114
|
+
onPrimary: '#00205c',
|
|
115
|
+
primarySoft: '#1b2740',
|
|
116
|
+
primaryText: '#a9c3ff',
|
|
117
|
+
|
|
118
|
+
secondary: '#4dd8e8',
|
|
119
|
+
onSecondary: '#00363d',
|
|
120
|
+
secondarySoft: '#12333a',
|
|
121
|
+
secondaryText: '#7fe6f2',
|
|
122
|
+
|
|
123
|
+
success: '#5ddb84',
|
|
124
|
+
onSuccess: '#003514',
|
|
125
|
+
successSoft: '#13301e',
|
|
126
|
+
successText: '#7fe6a1',
|
|
127
|
+
|
|
128
|
+
error: '#ff7b72',
|
|
129
|
+
onError: '#4d0500',
|
|
130
|
+
errorSoft: '#3a1c1a',
|
|
131
|
+
errorText: '#ffa9a3',
|
|
132
|
+
|
|
133
|
+
warning: '#f0b458',
|
|
134
|
+
onWarning: '#3d2600',
|
|
135
|
+
warningSoft: '#33260f',
|
|
136
|
+
warningText: '#f5c97e',
|
|
137
|
+
|
|
46
138
|
background: '#121212',
|
|
47
139
|
surface: '#1e1e1e',
|
|
48
140
|
text: '#ecedee',
|
|
@@ -50,4 +142,6 @@ export const darkPalette: ThemeColors = {
|
|
|
50
142
|
border: '#2a2a2e',
|
|
51
143
|
inputBackground: '#232326',
|
|
52
144
|
overlay: 'rgba(0,0,0,0.6)',
|
|
145
|
+
scrim: 'rgba(18,18,18,0.8)',
|
|
146
|
+
skeleton: '#26262a',
|
|
53
147
|
};
|