From abbbb4d9c5e95ca0294d235f2c385c24faaae7c4 Mon Sep 17 00:00:00 2001 From: Diogo Mota Date: Fri, 10 Apr 2026 13:00:00 +0000 Subject: [PATCH 01/13] chore: remove md2 support --- .../__fixtures__/rewrite-imports/code.js | 1 - .../__fixtures__/rewrite-imports/output.js | 1 - src/components/ActivityIndicator.tsx | 4 +- src/components/Appbar/Appbar.tsx | 50 +-- src/components/Appbar/AppbarAction.tsx | 12 +- src/components/Appbar/AppbarContent.tsx | 47 +-- src/components/Appbar/AppbarHeader.tsx | 12 +- src/components/Appbar/utils.ts | 39 +- src/components/Badge.tsx | 17 +- src/components/Banner.tsx | 17 +- .../BottomNavigation/BottomNavigation.tsx | 7 +- .../BottomNavigation/BottomNavigationBar.tsx | 207 ++-------- src/components/BottomNavigation/utils.ts | 45 +-- src/components/Button/Button.tsx | 51 +-- src/components/Button/utils.tsx | 119 ++---- src/components/Card/Card.tsx | 25 +- src/components/Card/CardActions.tsx | 13 +- src/components/Card/CardTitle.tsx | 14 +- src/components/Card/utils.tsx | 62 +-- src/components/Checkbox/CheckboxItem.tsx | 16 +- src/components/Checkbox/utils.ts | 42 +- src/components/Chip/Chip.tsx | 63 ++- src/components/Chip/helpers.tsx | 178 +++------ src/components/DataTable/DataTableHeader.tsx | 10 +- .../DataTable/DataTablePagination.tsx | 9 +- src/components/DataTable/DataTableRow.tsx | 10 +- src/components/DataTable/DataTableTitle.tsx | 2 +- src/components/Dialog/Dialog.tsx | 32 +- src/components/Dialog/DialogActions.tsx | 17 +- src/components/Dialog/DialogIcon.tsx | 8 +- src/components/Dialog/DialogScrollArea.tsx | 17 +- src/components/Dialog/DialogTitle.tsx | 19 +- src/components/Divider.tsx | 20 +- src/components/Drawer/DrawerCollapsedItem.tsx | 7 +- src/components/Drawer/DrawerItem.tsx | 30 +- src/components/Drawer/DrawerSection.tsx | 18 +- src/components/FAB/AnimatedFAB.tsx | 39 +- src/components/FAB/FAB.tsx | 16 +- src/components/FAB/FABGroup.tsx | 28 +- src/components/FAB/utils.ts | 151 ++----- src/components/HelperText/utils.ts | 18 +- src/components/Icon.tsx | 3 +- src/components/IconButton/IconButton.tsx | 11 +- src/components/IconButton/utils.ts | 115 +++--- src/components/List/ListAccordion.tsx | 58 +-- src/components/List/ListIcon.tsx | 12 +- src/components/List/ListImage.tsx | 15 +- src/components/List/ListItem.tsx | 38 +- src/components/List/ListSubheader.tsx | 7 +- src/components/List/utils.ts | 55 +-- src/components/Menu/Menu.tsx | 10 +- src/components/Menu/MenuItem.tsx | 39 +- src/components/Menu/utils.ts | 55 +-- src/components/ProgressBar.tsx | 6 +- .../RadioButton/RadioButtonItem.tsx | 16 +- src/components/Searchbar.tsx | 66 ++-- .../SegmentedButtons/SegmentedButtonItem.tsx | 13 +- src/components/SegmentedButtons/utils.ts | 64 +-- src/components/Snackbar.tsx | 22 +- src/components/Surface.tsx | 39 +- src/components/Switch/utils.ts | 11 +- src/components/TextInput/Addons/Outline.tsx | 6 +- src/components/TextInput/Addons/Underline.tsx | 14 +- .../Adornment/TextInputAdornment.tsx | 9 +- .../TextInput/Adornment/TextInputAffix.tsx | 2 +- .../TextInput/Adornment/TextInputIcon.tsx | 5 +- src/components/TextInput/Adornment/utils.ts | 19 +- src/components/TextInput/Label/InputLabel.tsx | 3 +- src/components/TextInput/TextInputFlat.tsx | 9 +- .../TextInput/TextInputOutlined.tsx | 14 +- src/components/TextInput/constants.tsx | 9 - src/components/TextInput/helpers.tsx | 146 ++----- src/components/TextInput/types.tsx | 1 - src/components/ToggleButton/ToggleButton.tsx | 10 +- src/components/ToggleButton/utils.ts | 14 +- src/components/Tooltip/Tooltip.tsx | 4 +- src/components/TouchableRipple/utils.ts | 18 +- src/components/Typography/AnimatedText.tsx | 6 +- src/components/Typography/Text.tsx | 6 +- src/components/Typography/v2/StyledText.tsx | 10 +- src/components/Typography/v2/Text.tsx | 7 +- .../__tests__/Appbar/Appbar.test.tsx | 130 +----- .../Appbar/__snapshots__/Appbar.test.tsx.snap | 1 - src/components/__tests__/Banner.test.tsx | 2 +- .../__tests__/BottomNavigation.test.tsx | 73 ++-- src/components/__tests__/Button.test.tsx | 215 +--------- src/components/__tests__/Card/Card.test.tsx | 71 ---- .../__snapshots__/CheckboxItem.test.tsx.snap | 4 - .../__tests__/Checkbox/utils.test.tsx | 128 ------ src/components/__tests__/Chip.test.tsx | 372 ------------------ src/components/__tests__/FAB.test.tsx | 77 ---- src/components/__tests__/FABGroup.test.tsx | 43 -- src/components/__tests__/IconButton.test.tsx | 33 -- .../__tests__/ListAccordion.test.tsx | 66 ---- src/components/__tests__/ListUtils.test.tsx | 43 +- src/components/__tests__/Menu.test.tsx | 2 +- src/components/__tests__/MenuItem.test.tsx | 81 ---- .../RadioButtonItem.test.tsx.snap | 4 - .../__tests__/SegmentedButton.test.tsx | 81 +--- src/components/__tests__/Switch.test.tsx | 35 +- src/components/__tests__/TextInput.test.tsx | 255 +----------- .../__tests__/ToggleButton.test.tsx | 12 - .../__snapshots__/Banner.test.tsx.snap | 148 ++++--- .../__snapshots__/Button.test.tsx.snap | 13 - .../__snapshots__/DataTable.test.tsx.snap | 1 - .../__snapshots__/DrawerItem.test.tsx.snap | 24 +- .../__snapshots__/Menu.test.tsx.snap | 11 - .../__snapshots__/MenuItem.test.tsx.snap | 14 - .../__snapshots__/Snackbar.test.tsx.snap | 1 - src/core/PaperProvider.tsx | 21 +- src/core/__tests__/PaperProvider.test.tsx | 27 +- src/core/theming.tsx | 34 +- src/index.tsx | 3 - src/styles/__tests__/fonts.test.js | 71 +--- src/styles/fonts.tsx | 85 +--- src/styles/overlay.tsx | 4 +- src/styles/shadow.tsx | 65 +-- src/styles/themes/index.ts | 2 - src/styles/themes/v2/DarkTheme.tsx | 30 -- src/styles/themes/v2/LightTheme.tsx | 30 -- src/types.tsx | 24 +- 121 files changed, 862 insertions(+), 3934 deletions(-) delete mode 100644 src/styles/themes/v2/DarkTheme.tsx delete mode 100644 src/styles/themes/v2/LightTheme.tsx diff --git a/src/babel/__fixtures__/rewrite-imports/code.js b/src/babel/__fixtures__/rewrite-imports/code.js index cc5e6d0b5c..6509ef2f67 100644 --- a/src/babel/__fixtures__/rewrite-imports/code.js +++ b/src/babel/__fixtures__/rewrite-imports/code.js @@ -5,7 +5,6 @@ import { Button, FAB, Appbar, - MD2Colors, MD3Colors, NonExistent, NonExistentSecond as Stuff, diff --git a/src/babel/__fixtures__/rewrite-imports/output.js b/src/babel/__fixtures__/rewrite-imports/output.js index ecaff8d814..7204b0ca33 100644 --- a/src/babel/__fixtures__/rewrite-imports/output.js +++ b/src/babel/__fixtures__/rewrite-imports/output.js @@ -4,7 +4,6 @@ import BottomNavigation from "react-native-paper/lib/module/components/BottomNav import Button from "react-native-paper/lib/module/components/Button/Button"; import FAB from "react-native-paper/lib/module/components/FAB"; import Appbar from "react-native-paper/lib/module/components/Appbar"; -import * as MD2Colors from "react-native-paper/lib/module/styles/themes/v2/colors"; import { MD3Colors } from "react-native-paper/lib/module/styles/themes/v3/tokens"; import { NonExistent, NonExistentSecond as Stuff } from "react-native-paper/lib/module/index.js"; import { ThemeProvider } from "react-native-paper/lib/module/core/theming"; diff --git a/src/components/ActivityIndicator.tsx b/src/components/ActivityIndicator.tsx index 5a3b9f8736..3de4e73d2f 100644 --- a/src/components/ActivityIndicator.tsx +++ b/src/components/ActivityIndicator.tsx @@ -45,10 +45,10 @@ const DURATION = 2400; * ## Usage * ```js * import * as React from 'react'; - * import { ActivityIndicator, MD2Colors } from 'react-native-paper'; + * import { ActivityIndicator, MD3Colors } from 'react-native-paper'; * * const MyComponent = () => ( - * + * * ); * * export default MyComponent; diff --git a/src/components/Appbar/Appbar.tsx b/src/components/Appbar/Appbar.tsx index d59c626769..4934ef7bf6 100644 --- a/src/components/Appbar/Appbar.tsx +++ b/src/components/Appbar/Appbar.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import { Animated, - Platform, StyleProp, StyleSheet, View, @@ -9,12 +8,9 @@ import { ColorValue, } from 'react-native'; -import color from 'color'; - import AppbarContent from './AppbarContent'; import { AppbarModes, - DEFAULT_APPBAR_HEIGHT, getAppbarBackgroundColor, modeAppbarHeight, renderAppbarContent, @@ -165,11 +161,10 @@ const Appbar = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); - const { isV3 } = theme; const flattenedStyle = StyleSheet.flatten(style); const { backgroundColor: customBackground, - elevation = isV3 ? (elevated ? 2 : 0) : 4, + elevation = elevated ? 2 : 0, ...restStyle } = (flattenedStyle || {}) as Exclude & { elevation?: number; @@ -184,28 +179,17 @@ const Appbar = ({ ); const isMode = (modeToCompare: AppbarModes) => { - return isV3 && mode === modeToCompare; + return mode === modeToCompare; }; - let isDark = false; - - if (typeof dark === 'boolean') { - isDark = dark; - } else if (!isV3) { - isDark = - backgroundColor === 'transparent' - ? false - : typeof backgroundColor === 'string' - ? !color(backgroundColor).isLight() - : true; - } + const isDark = typeof dark === 'boolean' ? dark : false; - const isV3CenterAlignedMode = isV3 && isMode('center-aligned'); + const isCenterAlignedMode = isMode('center-aligned'); let shouldCenterContent = false; let shouldAddLeftSpacing = false; let shouldAddRightSpacing = false; - if ((!isV3 && Platform.OS === 'ios') || isV3CenterAlignedMode) { + if (isCenterAlignedMode) { let hasAppbarContent = false; let leftItemsCount = 0; let rightItemsCount = 0; @@ -225,14 +209,12 @@ const Appbar = ({ }); shouldCenterContent = - hasAppbarContent && - leftItemsCount < 2 && - rightItemsCount < (isV3 ? 3 : 2); + hasAppbarContent && leftItemsCount < 2 && rightItemsCount < 3; shouldAddLeftSpacing = shouldCenterContent && leftItemsCount === 0; shouldAddRightSpacing = shouldCenterContent && rightItemsCount === 0; } - const spacingStyle = isV3 ? styles.v3Spacing : styles.spacing; + const spacingStyle = styles.v3Spacing; const insets = { paddingBottom: safeAreaInsets?.bottom, @@ -247,27 +229,25 @@ const Appbar = ({ { backgroundColor }, styles.appbar, { - height: isV3 ? modeAppbarHeight[mode] : DEFAULT_APPBAR_HEIGHT, + height: modeAppbarHeight[mode], }, insets, restStyle, - !theme.isV3 && { elevation }, ]} elevation={elevation as MD3Elevation} container {...rest} > {shouldAddLeftSpacing ? : null} - {(!isV3 || isMode('small') || isMode('center-aligned')) && ( + {(isMode('small') || isMode('center-aligned')) && ( <> {/* Render only the back action at first place */} {renderAppbarContent({ children, isDark, theme, - isV3, renderOnly: ['Appbar.BackAction'], - shouldCenterContent: isV3CenterAlignedMode || shouldCenterContent, + shouldCenterContent: isCenterAlignedMode || shouldCenterContent, })} {/* Render the rest of the content except the back action */} {renderAppbarContent({ @@ -278,9 +258,8 @@ const Appbar = ({ ], isDark, theme, - isV3, renderExcept: ['Appbar.BackAction'], - shouldCenterContent: isV3CenterAlignedMode || shouldCenterContent, + shouldCenterContent: isCenterAlignedMode || shouldCenterContent, })} )} @@ -297,14 +276,12 @@ const Appbar = ({ {renderAppbarContent({ children, isDark, - isV3, renderOnly: ['Appbar.BackAction'], mode, })} {renderAppbarContent({ children: filterAppbarActions(children, true), isDark, - isV3, renderOnly: ['Appbar.Action'], mode, })} @@ -313,7 +290,6 @@ const Appbar = ({ {renderAppbarContent({ children: filterAppbarActions(children), isDark, - isV3, renderExcept: [ 'Appbar', 'Appbar.BackAction', @@ -327,7 +303,6 @@ const Appbar = ({ {renderAppbarContent({ children, isDark, - isV3, renderOnly: ['Appbar.Content'], mode, })} @@ -344,9 +319,6 @@ const styles = StyleSheet.create({ alignItems: 'center', paddingHorizontal: 4, }, - spacing: { - width: 48, - }, v3Spacing: { width: 52, }, diff --git a/src/components/Appbar/AppbarAction.tsx b/src/components/Appbar/AppbarAction.tsx index ab5a72a110..14982cbecb 100644 --- a/src/components/Appbar/AppbarAction.tsx +++ b/src/components/Appbar/AppbarAction.tsx @@ -7,11 +7,10 @@ import type { ViewStyle, } from 'react-native'; -import color from 'color'; import type { ThemeProp } from 'src/types'; import { useInternalTheme } from '../../core/theming'; -import { black } from '../../styles/themes/v2/colors'; +import type { MD3Theme } from '../../types'; import { forwardRef } from '../../utils/forwardRef'; import type { IconSource } from '../Icon'; import IconButton from '../IconButton/IconButton'; @@ -98,14 +97,13 @@ const AppbarAction = forwardRef( ref ) => { const theme = useInternalTheme(themeOverrides); + const { colors } = theme as MD3Theme; const actionIconColor = iconColor ? iconColor - : theme.isV3 - ? isLeading - ? theme.colors.onSurface - : theme.colors.onSurfaceVariant - : color(black).alpha(0.54).rgb().string(); + : isLeading + ? colors.onSurface + : colors.onSurfaceVariant; return ( & { */ const AppbarContent = ({ color: titleColor, - subtitle, - subtitleStyle, onPress, disabled, style, @@ -117,15 +117,9 @@ const AppbarContent = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); - const { isV3, colors } = theme; - - const titleTextColor = titleColor - ? titleColor - : isV3 - ? colors.onSurface - : white; + const { colors, fonts } = theme as MD3Theme; - const subtitleColor = color(titleTextColor).alpha(0.7).rgb().string(); + const titleTextColor = titleColor ? titleColor : colors.onSurface; const modeContainerStyles = { small: styles.v3DefaultContainer, @@ -138,7 +132,7 @@ const AppbarContent = ({ const contentWrapperProps = { pointerEvents: 'box-none' as ViewProps['pointerEvents'], - style: [styles.container, isV3 && modeContainerStyles[mode], style], + style: [styles.container, modeContainerStyles[mode], style], testID, ...rest, }; @@ -147,18 +141,13 @@ const AppbarContent = ({ <> {typeof title === 'string' ? ( - {subtitle} - - ) : null} ); @@ -233,12 +214,6 @@ const styles = StyleSheet.create({ justifyContent: 'flex-end', paddingBottom: 28, }, - title: { - fontSize: Platform.OS === 'ios' ? 17 : 20, - }, - subtitle: { - fontSize: Platform.OS === 'ios' ? 11 : 14, - }, }); const touchableRole: AccessibilityRole = 'button'; diff --git a/src/components/Appbar/AppbarHeader.tsx b/src/components/Appbar/AppbarHeader.tsx index e0eb6386d7..9efe81bba1 100644 --- a/src/components/Appbar/AppbarHeader.tsx +++ b/src/components/Appbar/AppbarHeader.tsx @@ -13,7 +13,6 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { Appbar } from './Appbar'; import { - DEFAULT_APPBAR_HEIGHT, getAppbarBackgroundColor, modeAppbarHeight, getAppbarBorders, @@ -104,14 +103,13 @@ const AppbarHeader = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); - const { isV3 } = theme; const flattenedStyle = StyleSheet.flatten(style); const { - height = isV3 ? modeAppbarHeight[mode] : DEFAULT_APPBAR_HEIGHT, - elevation = isV3 ? (elevated ? 2 : 0) : 4, + height = modeAppbarHeight[mode], + elevation = elevated ? 2 : 0, backgroundColor: customBackground, - zIndex = isV3 && elevated ? 1 : 0, + zIndex = elevated ? 1 : 0, ...restStyle } = (flattenedStyle || {}) as Exclude & { height?: number; @@ -150,10 +148,8 @@ const AppbarHeader = ({ testID={testID} style={[{ height, backgroundColor }, styles.appbar, restStyle]} dark={dark} - {...(isV3 && { - mode, - })} {...rest} + mode={mode} theme={theme} /> diff --git a/src/components/Appbar/utils.ts b/src/components/Appbar/utils.ts index a6c68af2a5..fbf4fe438e 100644 --- a/src/components/Appbar/utils.ts +++ b/src/components/Appbar/utils.ts @@ -2,9 +2,8 @@ import React from 'react'; import type { ColorValue, StyleProp, ViewStyle } from 'react-native'; import { StyleSheet, Animated } from 'react-native'; -import overlay from '../../styles/overlay'; -import { black, white } from '../../styles/themes/v2/colors'; -import type { InternalTheme, ThemeProp } from '../../types'; +import { white } from '../../styles/themes/v2/colors'; +import type { InternalTheme, MD3Theme, ThemeProp } from '../../types'; export type AppbarModes = 'small' | 'medium' | 'large' | 'center-aligned'; @@ -24,26 +23,17 @@ const borderStyleProperties = [ export const getAppbarBackgroundColor = ( theme: InternalTheme, - elevation: number, + _elevation: number, customBackground?: ColorValue, elevated?: boolean ) => { - const { isV3, dark: isDarkTheme, mode, colors } = theme; - const isAdaptiveMode = mode === 'adaptive'; + const { colors } = theme as MD3Theme; if (customBackground) { return customBackground; } - if (!isV3) { - if (isDarkTheme && isAdaptiveMode) { - return overlay(elevation, colors?.surface); - } - - return colors.primary; - } - if (elevated) { - return theme.colors.elevation.level2; + return colors.elevation.level2; } return colors.surface; @@ -52,7 +42,6 @@ export const getAppbarBackgroundColor = ( export const getAppbarColor = ({ color, isDark, - isV3, }: BaseProps & { color: string }) => { if (typeof color !== 'undefined') { return color; @@ -62,11 +51,7 @@ export const getAppbarColor = ({ return white; } - if (isV3) { - return undefined; - } - - return black; + return undefined; }; export const getAppbarBorders = ( @@ -89,13 +74,11 @@ export const getAppbarBorders = ( type BaseProps = { isDark: boolean; - isV3: boolean; }; type RenderAppbarContentProps = BaseProps & { children: React.ReactNode; shouldCenterContent?: boolean; - isV3: boolean; renderOnly?: (string | boolean)[]; renderExcept?: string[]; mode?: AppbarModes; @@ -133,7 +116,6 @@ export const renderAppbarContent = ({ children, isDark, shouldCenterContent = false, - isV3, renderOnly, renderExcept, mode = 'small', @@ -172,16 +154,14 @@ export const renderAppbarContent = ({ theme?: ThemeProp; } = { theme, - color: getAppbarColor({ color: child.props.color, isDark, isV3 }), + color: getAppbarColor({ color: child.props.color, isDark }), }; // @ts-expect-error: TypeScript complains about the type of type but it doesn't matter if (child.type.displayName === 'Appbar.Content') { props.mode = mode; props.style = [ - isV3 - ? i === 0 && !shouldCenterContent && styles.v3Spacing - : i !== 0 && styles.v2Spacing, + i === 0 && !shouldCenterContent && styles.v3Spacing, shouldCenterContent && styles.centerAlignedContent, child.props.style, ]; @@ -195,9 +175,6 @@ const styles = StyleSheet.create({ centerAlignedContent: { alignItems: 'center', }, - v2Spacing: { - marginLeft: 8, - }, v3Spacing: { marginLeft: 12, }, diff --git a/src/components/Badge.tsx b/src/components/Badge.tsx index 54c70770f2..d8bf38015b 100644 --- a/src/components/Badge.tsx +++ b/src/components/Badge.tsx @@ -8,9 +8,7 @@ import { } from 'react-native'; import { useInternalTheme } from '../core/theming'; -import { black, white } from '../styles/themes/v2/colors'; import type { ThemeProp } from '../types'; -import getContrastingColor from '../utils/getContrastingColor'; const defaultSize = 20; @@ -85,20 +83,14 @@ const Badge = ({ }).start(); }, [visible, opacity, scale]); - const { - backgroundColor = theme.isV3 - ? theme.colors.error - : theme.colors?.notification, - ...restStyle - } = (StyleSheet.flatten(style) || {}) as TextStyle; + const { backgroundColor = theme.colors.error, ...restStyle } = + (StyleSheet.flatten(style) || {}) as TextStyle; - const textColor = theme.isV3 - ? theme.colors.onError - : getContrastingColor(backgroundColor, white, black); + const textColor = theme.colors.onError; const borderRadius = size / 2; - const paddingHorizontal = theme.isV3 ? 3 : 4; + const paddingHorizontal = 3; return ( { const theme = useInternalTheme(themeOverrides); + const { colors } = theme as MD3Theme; const { current: position } = React.useRef( new Animated.Value(visible ? 1 : 0) ); @@ -192,10 +193,10 @@ const Banner = ({ return ( @@ -222,12 +223,11 @@ const Banner = ({ ) : null} @@ -292,9 +292,6 @@ const styles = StyleSheet.create({ button: { margin: 4, }, - elevation: { - elevation: 1, - }, transparent: { opacity: 0, }, diff --git a/src/components/BottomNavigation/BottomNavigation.tsx b/src/components/BottomNavigation/BottomNavigation.tsx index c4e9b71a60..54df09d236 100644 --- a/src/components/BottomNavigation/BottomNavigation.tsx +++ b/src/components/BottomNavigation/BottomNavigation.tsx @@ -353,9 +353,8 @@ const BottomNavigation = ({ }: Props) => { const theme = useInternalTheme(themeOverrides); const { scale } = theme.animation; - const compact = compactProp ?? !theme.isV3; - let shifting = - shiftingProp ?? (theme.isV3 ? false : navigationState.routes.length > 3); + const compact = compactProp ?? false; + let shifting = shiftingProp ?? false; if (shifting && navigationState.routes.length < 2) { shifting = false; @@ -404,7 +403,7 @@ const BottomNavigation = ({ ...navigationState.routes.map((_, i) => Animated.timing(tabsPositionAnims[i], { toValue: i === index ? 0 : i >= index ? 1 : -1, - duration: theme.isV3 || shifting ? 150 * scale : 0, + duration: 150 * scale, useNativeDriver: true, easing: sceneAnimationEasing, }) diff --git a/src/components/BottomNavigation/BottomNavigationBar.tsx b/src/components/BottomNavigation/BottomNavigationBar.tsx index 05264c610a..3d315aea70 100644 --- a/src/components/BottomNavigation/BottomNavigationBar.tsx +++ b/src/components/BottomNavigation/BottomNavigationBar.tsx @@ -11,7 +11,6 @@ import { ViewStyle, } from 'react-native'; -import color from 'color'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { @@ -20,9 +19,7 @@ import { getLabelColor, } from './utils'; import { useInternalTheme } from '../../core/theming'; -import overlay from '../../styles/overlay'; -import { black, white } from '../../styles/themes/v2/colors'; -import type { ThemeProp } from '../../types'; +import type { MD3Theme, ThemeProp } from '../../types'; import useAnimatedValue from '../../utils/useAnimatedValue'; import useAnimatedValueArray from '../../utils/useAnimatedValueArray'; import useIsKeyboardShown from '../../utils/useIsKeyboardShown'; @@ -212,7 +209,6 @@ export type Props = { testID?: string; }; -const MIN_RIPPLE_SCALE = 0.001; // Minimum scale is not 0 due to bug with animation const MIN_TAB_WIDTH = 96; const MAX_TAB_WIDTH = 168; const BAR_HEIGHT = 56; @@ -321,7 +317,7 @@ const BottomNavigationBar = ({ ), getLabelText = ({ route }: { route: Route }) => route.title, getBadge = ({ route }: { route: Route }) => route.badge, - getColor = ({ route }: { route: Route }) => route.color, + getColor: _getColor = ({ route }: { route: Route }) => route.color, getAccessibilityLabel = ({ route }: { route: Route }) => route.accessibilityLabel, getTestID = ({ route }: { route: Route }) => route.testID, @@ -342,11 +338,11 @@ const BottomNavigationBar = ({ theme: themeOverrides, }: Props) => { const theme = useInternalTheme(themeOverrides); + const { colors } = theme as MD3Theme; const { bottom, left, right } = useSafeAreaInsets(); const { scale } = theme.animation; - const compact = compactProp ?? !theme.isV3; - let shifting = - shiftingProp ?? (theme.isV3 ? false : navigationState.routes.length > 3); + const compact = compactProp ?? false; + let shifting = shiftingProp ?? false; if (shifting && navigationState.routes.length < 2) { shifting = false; @@ -371,18 +367,7 @@ const BottomNavigationBar = ({ ); /** - * Index of the currently active tab. Used for setting the background color. - * We don't use the color as an animated value directly, because `setValue` seems to be buggy with colors?. - */ - const indexAnim = useAnimatedValue(navigationState.index); - - /** - * Animation for the background color ripple, used to determine it's scale and opacity. - */ - const rippleAnim = useAnimatedValue(MIN_RIPPLE_SCALE); - - /** - * Layout of the navigation bar. The width is used to determine the size and position of the ripple. + * Layout of the navigation bar. */ const [layout, onLayout] = useLayout(); @@ -412,42 +397,21 @@ const BottomNavigationBar = ({ const animateToIndex = React.useCallback( (index: number) => { - // Reset the ripple to avoid glitch if it's currently animating - rippleAnim.setValue(MIN_RIPPLE_SCALE); - - Animated.parallel([ - Animated.timing(rippleAnim, { - toValue: 1, - duration: theme.isV3 || shifting ? 400 * scale : 0, - useNativeDriver: true, - }), - ...navigationState.routes.map((_, i) => + Animated.parallel( + navigationState.routes.map((_, i) => Animated.timing(tabsAnims[i], { toValue: i === index ? 1 : 0, - duration: theme.isV3 || shifting ? 150 * scale : 0, + duration: 150 * scale, useNativeDriver: true, easing: animationEasing, }) - ), - ]).start(() => { + ) + ).start(() => { // Workaround a bug in native animations where this is reset after first animation tabsAnims.map((tab, i) => tab.setValue(i === index ? 1 : 0)); - - // Update the index to change bar's background color and then hide the ripple - indexAnim.setValue(index); - rippleAnim.setValue(MIN_RIPPLE_SCALE); }); }, - [ - rippleAnim, - theme.isV3, - shifting, - scale, - navigationState.routes, - tabsAnims, - animationEasing, - indexAnim, - ] + [scale, navigationState.routes, tabsAnims, animationEasing] ); React.useEffect(() => { @@ -479,62 +443,28 @@ const BottomNavigationBar = ({ }; const { routes } = navigationState; - const { colors, dark: isDarkTheme, mode, isV3 } = theme; - const { backgroundColor: customBackground, elevation = 4 } = - (StyleSheet.flatten(style) || {}) as { - elevation?: number; - backgroundColor?: ColorValue; - }; + const { backgroundColor: customBackground } = (StyleSheet.flatten(style) || + {}) as { + elevation?: number; + backgroundColor?: ColorValue; + }; - const approxBackgroundColor = customBackground - ? customBackground - : isDarkTheme && mode === 'adaptive' - ? overlay(elevation, colors?.surface) - : colors?.primary; - - const v2BackgroundColorInterpolation = shifting - ? indexAnim.interpolate({ - inputRange: routes.map((_, i) => i), - // FIXME: does outputRange support ColorValue or just strings? - // @ts-expect-error - outputRange: routes.map( - (route) => getColor({ route }) || approxBackgroundColor - ), - }) - : approxBackgroundColor; - - const backgroundColor = isV3 - ? customBackground || theme.colors.elevation.level2 - : shifting - ? v2BackgroundColorInterpolation - : approxBackgroundColor; - - const isDark = - typeof approxBackgroundColor === 'string' - ? !color(approxBackgroundColor).isLight() - : true; - - const textColor = isDark ? white : black; + const backgroundColor = customBackground || colors.elevation.level2; const activeTintColor = getActiveTintColor({ activeColor, - defaultColor: textColor, theme, }); const inactiveTintColor = getInactiveTintColor({ inactiveColor, - defaultColor: textColor, theme, }); - const touchColor = color(activeTintColor).alpha(0.12).rgb().string(); const maxTabWidth = routes.length > 3 ? MIN_TAB_WIDTH : MAX_TAB_WIDTH; const maxTabBarWidth = maxTabWidth * routes.length; - const rippleSize = layout.width / 4; - const insets = { left: safeAreaInsets?.left ?? left, right: safeAreaInsets?.right ?? right, @@ -543,10 +473,9 @@ const BottomNavigationBar = ({ return ( ({ accessibilityRole={'tablist'} testID={`${testID}-content-wrapper`} > - {shifting && !isV3 ? ( - - ) : null} {routes.map((route, index) => { const focused = navigationState.index === index; const active = tabsAnims[index]; - // Scale the label up - const scale = - labeled && shifting - ? active.interpolate({ - inputRange: [0, 1], - outputRange: [0.5, 1], - }) - : 1; - // Move down the icon to account for no-label in shifting and smaller label in non-shifting. const translateY = labeled ? shifting @@ -684,7 +567,6 @@ const BottomNavigationBar = ({ tintColor: activeTintColor, hasColor: Boolean(activeColor), focused, - defaultColor: textColor, theme, }); @@ -692,55 +574,53 @@ const BottomNavigationBar = ({ tintColor: inactiveTintColor, hasColor: Boolean(inactiveColor), focused, - defaultColor: textColor, theme, }); const badgeStyle = { - top: !isV3 ? -2 : typeof badge === 'boolean' ? 4 : 2, + top: typeof badge === 'boolean' ? 4 : 2, right: - (badge != null && typeof badge !== 'boolean' + badge != null && typeof badge !== 'boolean' ? String(badge).length * -2 - : 0) - (!isV3 ? 2 : 0), + : 0, }; - const isLegacyOrV3Shifting = !isV3 || (isV3 && shifting && labeled); + const isLegacyOrV3Shifting = shifting && labeled; - const font = isV3 ? theme.fonts.labelMedium : {}; + const font = (theme as MD3Theme).fonts.labelMedium; return renderTouchable({ key: route.key, route, borderless: true, centered: true, - rippleColor: isV3 ? 'transparent' : touchColor, + rippleColor: 'transparent', onPress: () => onTabPress(eventForIndex(index)), onLongPress: () => onTabLongPress?.(eventForIndex(index)), testID: getTestID({ route }), accessibilityLabel: getAccessibilityLabel({ route }), accessibilityRole: Platform.OS === 'ios' ? 'button' : 'tab', accessibilityState: { selected: focused }, - style: [styles.item, isV3 && styles.v3Item], + style: [styles.item, styles.v3Item], children: ( - {isV3 && focused && ( + {focused && ( ({ scaleX: outlineScale, }, ], - backgroundColor: theme.colors.secondaryContainer, + backgroundColor: colors.secondaryContainer, }, activeIndicatorStyle, ]} @@ -759,7 +639,7 @@ const BottomNavigationBar = ({ ({ ({ ) : ( ({ {typeof badge === 'boolean' ? ( - + ) : ( {badge} @@ -821,12 +701,7 @@ const BottomNavigationBar = ({ {labeled ? ( - + ({ )} - ) : ( - !isV3 && - )} + ) : null} ), }); @@ -939,9 +812,6 @@ const styles = StyleSheet.create({ v3Item: { paddingVertical: 0, }, - ripple: { - position: 'absolute', - }, iconContainer: { height: 24, width: 24, @@ -1002,7 +872,4 @@ const styles = StyleSheet.create({ borderRadius: OUTLINE_WIDTH / 4, alignSelf: 'center', }, - elevation: { - elevation: 4, - }, }); diff --git a/src/components/BottomNavigation/utils.ts b/src/components/BottomNavigation/utils.ts index 93a4d95091..20208d4b7d 100644 --- a/src/components/BottomNavigation/utils.ts +++ b/src/components/BottomNavigation/utils.ts @@ -1,70 +1,51 @@ -import color from 'color'; -import type { InternalTheme } from 'src/types'; - -import type { black, white } from '../../styles/themes/v2/colors'; - -type BaseProps = { - defaultColor: typeof black | typeof white; - theme: InternalTheme; -}; +import type { InternalTheme, MD3Theme } from '../../types'; export const getActiveTintColor = ({ activeColor, - defaultColor, theme, -}: BaseProps & { +}: { activeColor: string | undefined; + theme: InternalTheme; }) => { if (typeof activeColor === 'string') { return activeColor; } - if (theme.isV3) { - return theme.colors.onSecondaryContainer; - } - - return defaultColor; + return (theme as MD3Theme).colors.onSecondaryContainer; }; export const getInactiveTintColor = ({ inactiveColor, - defaultColor, theme, -}: BaseProps & { +}: { inactiveColor: string | undefined; + theme: InternalTheme; }) => { if (typeof inactiveColor === 'string') { return inactiveColor; } - if (theme.isV3) { - return theme.colors.onSurfaceVariant; - } - - return color(defaultColor).alpha(0.5).rgb().string(); + return (theme as MD3Theme).colors.onSurfaceVariant; }; export const getLabelColor = ({ tintColor, hasColor, focused, - defaultColor, theme, -}: BaseProps & { +}: { tintColor: string; hasColor: boolean; focused: boolean; + theme: InternalTheme; }) => { + const { colors } = theme as MD3Theme; if (hasColor) { return tintColor; } - if (theme.isV3) { - if (focused) { - return theme.colors.onSurface; - } - return theme.colors.onSurfaceVariant; + if (focused) { + return colors.onSurface; } - - return defaultColor; + return colors.onSurfaceVariant; }; diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx index 2e4d2cf519..1d1d0d3002 100644 --- a/src/components/Button/Button.tsx +++ b/src/components/Button/Button.tsx @@ -21,7 +21,7 @@ import { getButtonTouchableRippleStyle, } from './utils'; import { useInternalTheme } from '../../core/theming'; -import type { $Omit, ThemeProp } from '../../types'; +import type { $Omit, MD3Theme, ThemeProp } from '../../types'; import { forwardRef } from '../../utils/forwardRef'; import hasTouchHandler from '../../utils/hasTouchHandler'; import { splitStyles } from '../../utils/splitStyles'; @@ -218,8 +218,8 @@ const Button = ( }, [mode] ); - const { roundness, isV3, animation } = theme; - const uppercase = uppercaseProp ?? !theme.isV3; + const { roundness, animation } = theme; + const uppercase = uppercaseProp ?? false; const isWeb = Platform.OS === 'web'; const hasPassedTouchHandler = hasTouchHandler({ @@ -229,10 +229,9 @@ const Button = ( onLongPress, }); - const isElevationEntitled = - !disabled && (isV3 ? isMode('elevated') : isMode('contained')); - const initialElevation = isV3 ? 1 : 2; - const activeElevation = isV3 ? 2 : 8; + const isElevationEntitled = !disabled && isMode('elevated'); + const initialElevation = 1; + const activeElevation = 2; const { current: elevation } = React.useRef( new Animated.Value(isElevationEntitled ? initialElevation : 0) @@ -250,7 +249,7 @@ const Button = ( const handlePressIn = (e: GestureResponderEvent) => { onPressIn?.(e); - if (isV3 ? isMode('elevated') : isMode('contained')) { + if (isMode('elevated')) { const { scale } = animation; Animated.timing(elevation, { toValue: activeElevation, @@ -263,7 +262,7 @@ const Button = ( const handlePressOut = (e: GestureResponderEvent) => { onPressOut?.(e); - if (isV3 ? isMode('elevated') : isMode('contained')) { + if (isMode('elevated')) { const { scale } = animation; Animated.timing(elevation, { toValue: initialElevation, @@ -280,8 +279,8 @@ const Button = ( (style) => style.startsWith('border') && style.endsWith('Radius') ); - const borderRadius = (isV3 ? 5 : 1) * roundness; - const iconSize = isV3 ? 18 : 16; + const borderRadius = 5 * roundness; + const iconSize = 18; const { backgroundColor, borderColor, textColor, borderWidth } = getButtonColors({ @@ -311,7 +310,7 @@ const Button = ( const { color: customLabelColor, fontSize: customLabelSize } = StyleSheet.flatten(labelStyle) || {}; - const font = isV3 ? theme.fonts.labelLarge : theme.fonts.medium; + const font = (theme as MD3Theme).fonts.labelLarge; const textStyle = { color: textColor, @@ -322,16 +321,14 @@ const Button = ( StyleSheet.flatten(contentStyle)?.flexDirection === 'row-reverse' ? [ styles.iconReverse, - isV3 && styles[`md3IconReverse${compact ? 'Compact' : ''}`], - isV3 && - isMode('text') && + styles[`md3IconReverse${compact ? 'Compact' : ''}`], + isMode('text') && styles[`md3IconReverseTextMode${compact ? 'Compact' : ''}`], ] : [ styles.icon, - isV3 && styles[`md3Icon${compact ? 'Compact' : ''}`], - isV3 && - isMode('text') && + styles[`md3Icon${compact ? 'Compact' : ''}`], + isMode('text') && styles[`md3IconTextMode${compact ? 'Compact' : ''}`], ]; @@ -346,10 +343,9 @@ const Button = ( compact && styles.compact, buttonStyle, style, - !isV3 && !disabled && { elevation }, ] as Animated.WithAnimatedValue> } - {...(isV3 && { elevation: elevation })} + elevation={elevation} container > { + const { colors } = theme as MD3Theme; if (customButtonColor && !disabled) { return customButtonColor; } - if (theme.isV3) { - if (disabled) { - if (isMode('outlined') || isMode('text')) { - return 'transparent'; - } - - return theme.colors.surfaceDisabled; - } - - if (isMode('elevated')) { - return theme.colors.elevation.level1; + if (disabled) { + if (isMode('outlined') || isMode('text')) { + return 'transparent'; } - if (isMode('contained')) { - return theme.colors.primary; - } + return colors.surfaceDisabled; + } - if (isMode('contained-tonal')) { - return theme.colors.secondaryContainer; - } + if (isMode('elevated')) { + return colors.elevation.level1; } if (isMode('contained')) { - if (disabled) { - return color(theme.dark ? white : black) - .alpha(0.12) - .rgb() - .string(); - } + return colors.primary; + } - return theme.colors.primary; + if (isMode('contained-tonal')) { + return colors.secondaryContainer; } return 'transparent'; @@ -101,85 +89,56 @@ const getButtonTextColor = ({ backgroundColor: string; dark?: boolean; }) => { + const { colors } = theme as MD3Theme; if (customTextColor && !disabled) { return customTextColor; } - if (theme.isV3) { - if (disabled) { - return theme.colors.onSurfaceDisabled; - } - - if (typeof dark === 'boolean') { - if ( - isMode('contained') || - isMode('contained-tonal') || - isMode('elevated') - ) { - return isDark({ dark, backgroundColor }) ? white : black; - } - } - - if (isMode('outlined') || isMode('text') || isMode('elevated')) { - return theme.colors.primary; - } - - if (isMode('contained')) { - return theme.colors.onPrimary; - } + if (disabled) { + return colors.onSurfaceDisabled; + } - if (isMode('contained-tonal')) { - return theme.colors.onSecondaryContainer; + if (typeof dark === 'boolean') { + if ( + isMode('contained') || + isMode('contained-tonal') || + isMode('elevated') + ) { + return isDark({ dark, backgroundColor }) ? white : black; } } - if (disabled) { - return color(theme.dark ? white : black) - .alpha(0.32) - .rgb() - .string(); + if (isMode('outlined') || isMode('text') || isMode('elevated')) { + return colors.primary; } if (isMode('contained')) { - return isDark({ dark, backgroundColor }) ? white : black; + return colors.onPrimary; + } + + if (isMode('contained-tonal')) { + return colors.onSecondaryContainer; } - return theme.colors.primary; + return colors.primary; }; const getButtonBorderColor = ({ isMode, disabled, theme }: BaseProps) => { - if (theme.isV3) { - if (disabled && isMode('outlined')) { - return theme.colors.surfaceDisabled; - } - - if (isMode('outlined')) { - return theme.colors.outline; - } + const { colors } = theme as MD3Theme; + if (disabled && isMode('outlined')) { + return colors.surfaceDisabled; } if (isMode('outlined')) { - return color(theme.dark ? white : black) - .alpha(0.29) - .rgb() - .string(); + return colors.outline; } return 'transparent'; }; -const getButtonBorderWidth = ({ - isMode, - theme, -}: Omit) => { - if (theme.isV3) { - if (isMode('outlined')) { - return 1; - } - } - +const getButtonBorderWidth = ({ isMode }: Omit) => { if (isMode('outlined')) { - return StyleSheet.hairlineWidth; + return 1; } return 0; diff --git a/src/components/Card/Card.tsx b/src/components/Card/Card.tsx index 848be9fa13..422101b4e8 100644 --- a/src/components/Card/Card.tsx +++ b/src/components/Card/Card.tsx @@ -181,7 +181,7 @@ const Card = ( const { current: elevationDarkAdaptive } = React.useRef( new Animated.Value(cardElevation) ); - const { animation, dark, mode, roundness, isV3 } = theme; + const { animation, dark, mode, roundness } = theme; const prevDarkRef = React.useRef(dark); React.useEffect(() => { @@ -213,20 +213,20 @@ const Card = ( ]); const runElevationAnimation = (pressType: HandlePressType) => { - if (isV3 && isMode('contained')) { + if (isMode('contained')) { return; } const isPressTypeIn = pressType === 'in'; if (dark && isAdaptiveMode) { Animated.timing(elevationDarkAdaptive, { - toValue: isPressTypeIn ? (isV3 ? 2 : 8) : cardElevation, + toValue: isPressTypeIn ? 2 : cardElevation, duration: animationDuration, useNativeDriver: false, }).start(); } else { Animated.timing(elevation, { - toValue: isPressTypeIn ? (isV3 ? 2 : 8) : cardElevation, + toValue: isPressTypeIn ? 2 : cardElevation, duration: animationDuration, useNativeDriver: false, }).start(); @@ -267,7 +267,7 @@ const Card = ( ); const borderRadiusCombinedStyles = { - borderRadius: (isV3 ? 3 : 1) * roundness, + borderRadius: 3 * roundness, ...borderRadiusStyles, }; @@ -290,20 +290,12 @@ const Card = ( & { * ``` */ const CardActions = ({ theme, style, children, ...rest }: Props) => { - const { isV3 } = useInternalTheme(theme); + useInternalTheme(theme); - const justifyContent = ( - isV3 ? 'flex-end' : 'flex-start' - ) as ViewStyle['justifyContent']; + const justifyContent = 'flex-end' as ViewStyle['justifyContent']; const containerStyle = [styles.container, { justifyContent }, style]; return ( @@ -50,11 +48,10 @@ const CardActions = ({ theme, style, children, ...rest }: Props) => { return child; } - const compact = !isV3 && child.props.compact !== false; + const compact = child.props.compact; const mode = - child.props.mode ?? - (isV3 ? (index === 0 ? 'outlined' : 'contained') : undefined); - const childStyle = [isV3 && styles.button, child.props.style]; + child.props.mode ?? (index === 0 ? 'outlined' : 'contained'); + const childStyle = [styles.button, child.props.style]; return React.cloneElement(child, { ...child.props, diff --git a/src/components/Card/CardTitle.tsx b/src/components/Card/CardTitle.tsx index b3d78fc259..f24809c405 100644 --- a/src/components/Card/CardTitle.tsx +++ b/src/components/Card/CardTitle.tsx @@ -10,8 +10,6 @@ import { import { useInternalTheme } from '../../core/theming'; import type { MD3TypescaleKey, ThemeProp } from '../../types'; import Text from '../Typography/Text'; -import Caption from '../Typography/v2/Caption'; -import Title from '../Typography/v2/Title'; export type Props = React.ComponentPropsWithRef & { /** @@ -151,9 +149,7 @@ const CardTitle = ({ style, theme: themeOverrides, }: Props) => { - const theme = useInternalTheme(themeOverrides); - const TitleComponent = theme.isV3 ? Text : Title; - const SubtitleComponent = theme.isV3 ? Text : Caption; + useInternalTheme(themeOverrides); const minHeight = subtitle || left || right ? 72 : 50; const marginBottom = subtitle ? 0 : 2; @@ -170,24 +166,24 @@ const CardTitle = ({ {title && ( - {title} - + )} {subtitle && ( - {subtitle} - + )} {right ? right({ size: 24 }) : null} diff --git a/src/components/Card/utils.tsx b/src/components/Card/utils.tsx index c0f10951c5..9a4ed5df7d 100644 --- a/src/components/Card/utils.tsx +++ b/src/components/Card/utils.tsx @@ -1,9 +1,6 @@ import type { StyleProp, ViewStyle } from 'react-native'; -import color from 'color'; - -import { black, white } from '../../styles/themes/v2/colors'; -import type { InternalTheme } from '../../types'; +import type { InternalTheme, MD3Theme } from '../../types'; type CardMode = 'elevated' | 'outlined' | 'contained'; @@ -20,8 +17,8 @@ export type CardActionChildProps = { export const getCardCoverStyle = ({ theme, - index, - total, + index: _index, + total: _total, borderRadiusStyles, }: { theme: InternalTheme; @@ -29,7 +26,7 @@ export const getCardCoverStyle = ({ index?: number; total?: number; }) => { - const { isV3, roundness } = theme; + const { roundness } = theme; if (Object.keys(borderRadiusStyles).length > 0) { return { @@ -38,43 +35,13 @@ export const getCardCoverStyle = ({ }; } - if (isV3) { - return { - borderRadius: 3 * roundness, - }; - } - - if (index === 0) { - if (total === 1) { - return { - borderRadius: roundness, - }; - } - - return { - borderTopLeftRadius: roundness, - borderTopRightRadius: roundness, - }; - } - - if (typeof total === 'number' && index === total - 1) { - return { - borderBottomLeftRadius: roundness, - }; - } - - return undefined; + return { + borderRadius: 3 * roundness, + }; }; const getBorderColor = ({ theme }: { theme: InternalTheme }) => { - if (theme.isV3) { - return theme.colors.outline; - } - - if (theme.dark) { - return color(white).alpha(0.12).rgb().string(); - } - return color(black).alpha(0.12).rgb().string(); + return (theme as MD3Theme).colors.outline; }; const getBackgroundColor = ({ @@ -84,13 +51,12 @@ const getBackgroundColor = ({ theme: InternalTheme; isMode: (mode: CardMode) => boolean; }) => { - if (theme.isV3) { - if (isMode('contained')) { - return theme.colors.surfaceVariant; - } - if (isMode('outlined')) { - return theme.colors.surface; - } + const { colors } = theme as MD3Theme; + if (isMode('contained')) { + return colors.surfaceVariant; + } + if (isMode('outlined')) { + return colors.surface; } return undefined; }; diff --git a/src/components/Checkbox/CheckboxItem.tsx b/src/components/Checkbox/CheckboxItem.tsx index 92ea124e62..869edd674a 100644 --- a/src/components/Checkbox/CheckboxItem.tsx +++ b/src/components/Checkbox/CheckboxItem.tsx @@ -166,10 +166,8 @@ const CheckboxItem = ({ checkbox = ; } - const textColor = theme.isV3 ? theme.colors.onSurface : theme.colors.text; - const disabledTextColor = theme.isV3 - ? theme.colors.onSurfaceDisabled - : theme.colors.disabled; + const textColor = theme.colors.onSurface; + const disabledTextColor = theme.colors.onSurfaceDisabled; const textAlign = isLeading ? 'right' : 'left'; const computedStyle = { @@ -204,12 +202,7 @@ const CheckboxItem = ({ variant={labelVariant} testID={`${testID}-text`} maxFontSizeMultiplier={labelMaxFontSizeMultiplier} - style={[ - styles.label, - !theme.isV3 && styles.font, - computedStyle, - labelStyle, - ]} + style={[styles.label, computedStyle, labelStyle]} > {label} @@ -238,7 +231,4 @@ const styles = StyleSheet.create({ flexShrink: 1, flexGrow: 1, }, - font: { - fontSize: 16, - }, }); diff --git a/src/components/Checkbox/utils.ts b/src/components/Checkbox/utils.ts index 81677d46b2..4ba3615836 100644 --- a/src/components/Checkbox/utils.ts +++ b/src/components/Checkbox/utils.ts @@ -13,11 +13,7 @@ const getAndroidCheckedColor = ({ return customColor; } - if (theme.isV3) { - return theme.colors.primary; - } - - return theme.colors.accent; + return theme.colors.primary; }; const getAndroidUncheckedColor = ({ @@ -31,15 +27,7 @@ const getAndroidUncheckedColor = ({ return customUncheckedColor; } - if (theme.isV3) { - return theme.colors.onSurfaceVariant; - } - - if (theme.dark) { - return color(theme.colors.text).alpha(0.7).rgb().string(); - } - - return color(theme.colors.text).alpha(0.54).rgb().string(); + return theme.colors.onSurfaceVariant; }; const getAndroidRippleColor = ({ @@ -52,10 +40,7 @@ const getAndroidRippleColor = ({ disabled?: boolean; }) => { if (disabled) { - if (theme.isV3) { - return color(theme.colors.onSurface).alpha(0.16).rgb().string(); - } - return color(theme.colors.text).alpha(0.16).rgb().string(); + return color(theme.colors.onSurface).alpha(0.16).rgb().string(); } return color(checkedColor).fade(0.32).rgb().string(); @@ -75,10 +60,7 @@ const getAndroidControlColor = ({ disabled?: boolean; }) => { if (disabled) { - if (theme.isV3) { - return theme.colors.onSurfaceDisabled; - } - return theme.colors.disabled; + return theme.colors.onSurfaceDisabled; } if (checked) { @@ -127,21 +109,14 @@ const getIOSCheckedColor = ({ disabled?: boolean; }) => { if (disabled) { - if (theme.isV3) { - return theme.colors.onSurfaceDisabled; - } - return theme.colors.disabled; + return theme.colors.onSurfaceDisabled; } if (customColor) { return customColor; } - if (theme.isV3) { - return theme.colors.primary; - } - - return theme.colors.accent; + return theme.colors.primary; }; const getIOSRippleColor = ({ @@ -154,10 +129,7 @@ const getIOSRippleColor = ({ disabled?: boolean; }) => { if (disabled) { - if (theme.isV3) { - return color(theme.colors.onSurface).alpha(0.16).rgb().string(); - } - return color(theme.colors.text).alpha(0.16).rgb().string(); + return color(theme.colors.onSurface).alpha(0.16).rgb().string(); } return color(checkedColor).fade(0.32).rgb().string(); }; diff --git a/src/components/Chip/Chip.tsx b/src/components/Chip/Chip.tsx index 0e48e5c145..3706239b71 100644 --- a/src/components/Chip/Chip.tsx +++ b/src/components/Chip/Chip.tsx @@ -19,7 +19,7 @@ import useLatestCallback from 'use-latest-callback'; import { ChipAvatarProps, getChipColors } from './helpers'; import { useInternalTheme } from '../../core/theming'; import { white } from '../../styles/themes/v2/colors'; -import type { $Omit, EllipsizeProp, ThemeProp } from '../../types'; +import type { $Omit, EllipsizeProp, MD3Theme, ThemeProp } from '../../types'; import hasTouchHandler from '../../utils/hasTouchHandler'; import type { IconSource } from '../Icon'; import Icon from '../Icon'; @@ -212,11 +212,11 @@ const Chip = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); - const { isV3, roundness } = theme; + const { roundness } = theme; const isWeb = Platform.OS === 'web'; const { current: elevation } = React.useRef( - new Animated.Value(isV3 && elevated ? 1 : 0) + new Animated.Value(elevated ? 1 : 0) ); const hasPassedTouchHandler = hasTouchHandler({ @@ -232,7 +232,7 @@ const Chip = ({ const { scale } = theme.animation; onPressIn?.(e); Animated.timing(elevation, { - toValue: isV3 ? (elevated ? 2 : 0) : 4, + toValue: elevated ? 2 : 0, duration: 200 * scale, useNativeDriver: isWeb || Platform.constants.reactNativeVersion.minor <= 72, @@ -243,16 +243,16 @@ const Chip = ({ const { scale } = theme.animation; onPressOut?.(e); Animated.timing(elevation, { - toValue: isV3 && elevated ? 1 : 0, + toValue: elevated ? 1 : 0, duration: 150 * scale, useNativeDriver: isWeb || Platform.constants.reactNativeVersion.minor <= 72, }).start(); }); - const opacity = isV3 ? 0.38 : 0.26; - const defaultBorderRadius = roundness * (isV3 ? 2 : 4); - const iconSize = isV3 ? 18 : 16; + const opacity = 0.38; + const defaultBorderRadius = roundness * 2; + const iconSize = 18; const { backgroundColor: customBackgroundColor, @@ -281,8 +281,8 @@ const Chip = ({ disabled, }; - const elevationStyle = isV3 || Platform.OS === 'android' ? elevation : 0; - const multiplier = isV3 ? (compact ? 1.5 : 2) : 1; + const elevationStyle = elevation; + const multiplier = compact ? 1.5 : 2; const labelSpacings = { marginRight: onClose ? 0 : 8 * multiplier, marginLeft: @@ -291,20 +291,17 @@ const Chip = ({ : 8 * multiplier, }; const contentSpacings = { - paddingRight: isV3 ? (onClose ? 34 : 0) : onClose ? 32 : 4, + paddingRight: onClose ? 34 : 0, }; const labelTextStyle = { color: textColor, - ...(isV3 ? theme.fonts.labelLarge : theme.fonts.regular), + ...(theme as MD3Theme).fonts.labelLarge, }; return ( - + {avatar && !icon ? ( @@ -358,12 +353,12 @@ const Chip = ({ - + {closeIcon ? ( ) : ( theme as MD3Theme; export type ChipAvatarProps = { style?: StyleProp; @@ -20,40 +21,25 @@ const getBorderColor = ({ isOutlined, disabled, selectedColor, - backgroundColor, + backgroundColor: _backgroundColor, }: BaseProps & { backgroundColor: string; selectedColor?: string }) => { const isSelectedColor = selectedColor !== undefined; + const { colors } = md3(theme); - if (theme.isV3) { - if (!isOutlined) { - // If the Chip mode is "flat", set border color to transparent - return 'transparent'; - } - - if (disabled) { - return color(theme.colors.onSurfaceVariant).alpha(0.12).rgb().string(); - } - - if (isSelectedColor) { - return color(selectedColor).alpha(0.29).rgb().string(); - } - - return theme.colors.outline; + if (!isOutlined) { + // If the Chip mode is "flat", set border color to transparent + return 'transparent'; } - if (isOutlined) { - if (isSelectedColor) { - return color(selectedColor).alpha(0.29).rgb().string(); - } - - if (theme.dark) { - return color(white).alpha(0.29).rgb().string(); - } + if (disabled) { + return color(colors.onSurfaceVariant).alpha(0.12).rgb().string(); + } - return color(black).alpha(0.29).rgb().string(); + if (isSelectedColor) { + return color(selectedColor).alpha(0.29).rgb().string(); } - return backgroundColor; + return colors.outline; }; const getTextColor = ({ @@ -65,54 +51,32 @@ const getTextColor = ({ selectedColor?: string; }) => { const isSelectedColor = selectedColor !== undefined; - if (theme.isV3) { - if (disabled) { - return theme.colors.onSurfaceDisabled; - } - - if (isSelectedColor) { - return selectedColor; - } - - if (isOutlined) { - return theme.colors.onSurfaceVariant; - } - - return theme.colors.onSecondaryContainer; - } - + const { colors } = md3(theme); if (disabled) { - return theme.colors.disabled; + return colors.onSurfaceDisabled; } if (isSelectedColor) { - return color(selectedColor).alpha(0.87).rgb().string(); + return selectedColor; + } + + if (isOutlined) { + return colors.onSurfaceVariant; } - return color(theme.colors.text).alpha(0.87).rgb().string(); + return colors.onSecondaryContainer; }; const getDefaultBackgroundColor = ({ theme, isOutlined, }: Omit) => { - if (theme.isV3) { - if (isOutlined) { - return theme.colors.surface; - } - - return theme.colors.secondaryContainer; - } - + const { colors } = md3(theme); if (isOutlined) { - return theme.colors?.surface; - } - - if (theme.dark) { - return '#383838'; + return colors.surface; } - return '#ebebeb'; + return colors.secondaryContainer; }; const getBackgroundColor = ({ @@ -123,17 +87,16 @@ const getBackgroundColor = ({ }: BaseProps & { customBackgroundColor?: ColorValue; }) => { + const { colors } = md3(theme); if (typeof customBackgroundColor === 'string') { return customBackgroundColor; } - if (theme.isV3) { - if (disabled) { - if (isOutlined) { - return 'transparent'; - } - return color(theme.colors.onSurfaceVariant).alpha(0.12).rgb().string(); + if (disabled) { + if (isOutlined) { + return 'transparent'; } + return color(colors.onSurfaceVariant).alpha(0.12).rgb().string(); } return getDefaultBackgroundColor({ theme, isOutlined }); @@ -149,6 +112,7 @@ const getSelectedBackgroundColor = ({ customBackgroundColor?: ColorValue; showSelectedOverlay?: boolean; }) => { + const { colors } = md3(theme); const backgroundColor = getBackgroundColor({ theme, disabled, @@ -156,45 +120,30 @@ const getSelectedBackgroundColor = ({ customBackgroundColor, }); - if (theme.isV3) { - if (isOutlined) { - if (showSelectedOverlay) { - return color(backgroundColor) - .mix(color(theme.colors.onSurfaceVariant), 0.12) - .rgb() - .string(); - } - return color(backgroundColor) - .mix(color(theme.colors.onSurfaceVariant), 0) - .rgb() - .string(); - } - + if (isOutlined) { if (showSelectedOverlay) { return color(backgroundColor) - .mix(color(theme.colors.onSecondaryContainer), 0.12) + .mix(color(colors.onSurfaceVariant), 0.12) .rgb() .string(); } - return color(backgroundColor) - .mix(color(theme.colors.onSecondaryContainer), 0) + .mix(color(colors.onSurfaceVariant), 0) .rgb() .string(); } - if (theme.dark) { - if (isOutlined) { - return color(backgroundColor).lighten(0.2).rgb().string(); - } - return color(backgroundColor).lighten(0.4).rgb().string(); - } - - if (isOutlined) { - return color(backgroundColor).darken(0.08).rgb().string(); + if (showSelectedOverlay) { + return color(backgroundColor) + .mix(color(colors.onSecondaryContainer), 0.12) + .rgb() + .string(); } - return color(backgroundColor).darken(0.2).rgb().string(); + return color(backgroundColor) + .mix(color(colors.onSecondaryContainer), 0) + .rgb() + .string(); }; const getIconColor = ({ @@ -206,31 +155,20 @@ const getIconColor = ({ selectedColor?: string; }) => { const isSelectedColor = selectedColor !== undefined; - if (theme.isV3) { - if (disabled) { - return theme.colors.onSurfaceDisabled; - } - - if (isSelectedColor) { - return selectedColor; - } - - if (isOutlined) { - return theme.colors.onSurfaceVariant; - } - - return theme.colors.onSecondaryContainer; - } - + const { colors } = md3(theme); if (disabled) { - return theme.colors.disabled; + return colors.onSurfaceDisabled; } if (isSelectedColor) { - return color(selectedColor).alpha(0.54).rgb().string(); + return selectedColor; + } + + if (isOutlined) { + return colors.onSurfaceVariant; } - return color(theme.colors.text).alpha(0.54).rgb().string(); + return colors.onSecondaryContainer; }; const getRippleColor = ({ @@ -238,7 +176,7 @@ const getRippleColor = ({ isOutlined, disabled, selectedColor, - selectedBackgroundColor, + selectedBackgroundColor: _selectedBackgroundColor, customRippleColor, }: BaseProps & { selectedBackgroundColor: string; @@ -257,19 +195,11 @@ const getRippleColor = ({ isOutlined, }); - if (theme.isV3) { - if (isSelectedColor) { - return color(selectedColor).alpha(0.12).rgb().string(); - } - - return color(textColor).alpha(0.12).rgb().string(); - } - if (isSelectedColor) { - return color(selectedColor).fade(0.5).rgb().string(); + return color(selectedColor).alpha(0.12).rgb().string(); } - return selectedBackgroundColor; + return color(textColor).alpha(0.12).rgb().string(); }; export const getChipColors = ({ diff --git a/src/components/DataTable/DataTableHeader.tsx b/src/components/DataTable/DataTableHeader.tsx index a4619ebb99..1fee2a02ab 100644 --- a/src/components/DataTable/DataTableHeader.tsx +++ b/src/components/DataTable/DataTableHeader.tsx @@ -1,10 +1,7 @@ import * as React from 'react'; import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native'; -import color from 'color'; - import { useInternalTheme } from '../../core/theming'; -import { black, white } from '../../styles/themes/v2/colors'; import type { ThemeProp } from '../../types'; export type Props = React.ComponentPropsWithRef & { @@ -52,12 +49,7 @@ const DataTableHeader = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); - const borderBottomColor = theme.isV3 - ? theme.colors.surfaceVariant - : color(theme.dark ? white : black) - .alpha(0.12) - .rgb() - .string(); + const borderBottomColor = theme.colors.surfaceVariant; return ( diff --git a/src/components/DataTable/DataTablePagination.tsx b/src/components/DataTable/DataTablePagination.tsx index dd72dbe54f..c7a5375f82 100644 --- a/src/components/DataTable/DataTablePagination.tsx +++ b/src/components/DataTable/DataTablePagination.tsx @@ -108,7 +108,7 @@ const PaginationControls = ({ }: PaginationControlsProps) => { const theme = useInternalTheme(themeOverrides); - const textColor = theme.isV3 ? theme.colors.onSurface : theme.colors.text; + const textColor = theme.colors.onSurface; return ( <> @@ -310,12 +310,7 @@ const DataTablePagination = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); - const labelColor = color( - theme.isV3 ? theme.colors.onSurface : theme?.colors.text - ) - .alpha(0.6) - .rgb() - .string(); + const labelColor = color(theme.colors.onSurface).alpha(0.6).rgb().string(); return ( { const theme = useInternalTheme(themeOverrides); - const borderBottomColor = theme.isV3 - ? theme.colors.surfaceVariant - : color(theme.dark ? white : black) - .alpha(0.12) - .rgb() - .string(); + const borderBottomColor = theme.colors.surfaceVariant; return ( { const { right, left } = useSafeAreaInsets(); const theme = useInternalTheme(themeOverrides); - const { isV3, dark, mode, colors, roundness } = theme; - const borderRadius = (isV3 ? 7 : 1) * roundness; + const { roundness, colors } = theme as MD3Theme; + const borderRadius = 7 * roundness; - const backgroundColorV2 = - dark && mode === 'adaptive' - ? overlay(DIALOG_ELEVATION, colors?.surface) - : colors?.surface; - const backgroundColor = isV3 - ? theme.colors.elevation.level3 - : backgroundColorV2; + const backgroundColor = colors.elevation.level3; return ( child != null && typeof child !== 'boolean') .map((child, i) => { - if (isV3) { - if (i === 0 && React.isValidElement(child)) { - return React.cloneElement(child, { - style: [{ marginTop: 24 }, child.props.style], - }); - } - } - - if ( - i === 0 && - React.isValidElement(child) && - child.type === DialogContent - ) { - // Dialog content is the first item, so we add a top padding + if (i === 0 && React.isValidElement(child)) { return React.cloneElement(child, { - style: [{ paddingTop: 24 }, child.props.style], + style: [{ marginTop: 24 }, child.props.style], }); } diff --git a/src/components/Dialog/DialogActions.tsx b/src/components/Dialog/DialogActions.tsx index cabebd2fe2..7b34739da5 100644 --- a/src/components/Dialog/DialogActions.tsx +++ b/src/components/Dialog/DialogActions.tsx @@ -47,21 +47,18 @@ export type Props = React.ComponentPropsWithRef & { * ``` */ const DialogActions = (props: Props) => { - const { isV3 } = useInternalTheme(props.theme); + useInternalTheme(props.theme); const actionsLength = React.Children.toArray(props.children).length; return ( - + {React.Children.map(props.children, (child, i) => React.isValidElement(child) ? React.cloneElement(child, { compact: true, - uppercase: !isV3, + uppercase: false, style: [ - isV3 && { + { marginRight: i + 1 === actionsLength ? 0 : 8, }, child.props.style, @@ -76,12 +73,6 @@ const DialogActions = (props: Props) => { DialogActions.displayName = 'Dialog.Actions'; const styles = StyleSheet.create({ - container: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'flex-end', - padding: 8, - }, v3Container: { flexDirection: 'row', flexGrow: 1, diff --git a/src/components/Dialog/DialogIcon.tsx b/src/components/Dialog/DialogIcon.tsx index ad5841b93a..7682054003 100644 --- a/src/components/Dialog/DialogIcon.tsx +++ b/src/components/Dialog/DialogIcon.tsx @@ -4,6 +4,7 @@ import { StyleSheet, View } from 'react-native'; import type { ThemeProp } from 'src/types'; import { useInternalTheme } from '../../core/theming'; +import type { MD3Theme } from '../../types'; import Icon, { IconSource } from '../Icon'; export type Props = { @@ -69,13 +70,10 @@ const DialogIcon = ({ theme: themeOverrides, }: Props) => { const theme = useInternalTheme(themeOverrides); - - if (!theme.isV3) { - return null; - } + const { colors } = theme as MD3Theme; //@ts-ignore - const iconColor = color || theme.colors.secondary; + const iconColor = color || colors.secondary; return ( diff --git a/src/components/Dialog/DialogScrollArea.tsx b/src/components/Dialog/DialogScrollArea.tsx index 66fdcef6a0..5deeb4a5e6 100644 --- a/src/components/Dialog/DialogScrollArea.tsx +++ b/src/components/Dialog/DialogScrollArea.tsx @@ -4,6 +4,7 @@ import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native'; import type { ThemeProp } from 'src/types'; import { useInternalTheme } from '../../core/theming'; +import type { MD3Theme } from '../../types'; export type Props = React.ComponentPropsWithRef & { /** @@ -50,22 +51,16 @@ export type Props = React.ComponentPropsWithRef & { */ const DialogScrollArea = (props: Props) => { const theme = useInternalTheme(props.theme); + const { colors } = theme as MD3Theme; const borderStyles = { - borderColor: theme.isV3 - ? theme.colors.surfaceVariant - : 'rgba(0, 0, 0, .12)', - borderTopWidth: theme.isV3 ? 1 : StyleSheet.hairlineWidth, - borderBottomWidth: theme.isV3 ? 1 : StyleSheet.hairlineWidth, + borderColor: colors.surfaceVariant, + borderTopWidth: 1, + borderBottomWidth: 1, }; return ( {props.children} diff --git a/src/components/Dialog/DialogTitle.tsx b/src/components/Dialog/DialogTitle.tsx index 9953fc506c..407acb68b3 100644 --- a/src/components/Dialog/DialogTitle.tsx +++ b/src/components/Dialog/DialogTitle.tsx @@ -2,11 +2,10 @@ import * as React from 'react'; import { StyleProp, StyleSheet, TextStyle } from 'react-native'; import { useInternalTheme } from '../../core/theming'; -import type { ThemeProp } from '../../types'; +import type { MD3Theme, ThemeProp } from '../../types'; import Text from '../Typography/Text'; -import Title from '../Typography/v2/Title'; -export type Props = React.ComponentPropsWithRef & { +export type Props = React.ComponentPropsWithRef & { /** * Title text for the `DialogTitle`. */ @@ -53,24 +52,22 @@ const DialogTitle = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); - const { isV3, colors, fonts } = theme; - - const TextComponent = isV3 ? Text : Title; + const { colors, fonts } = theme as MD3Theme; const headerTextStyle = { - color: isV3 ? colors.onSurface : colors?.text, - ...(isV3 ? fonts.headlineSmall : {}), + color: colors.onSurface, + ...fonts.headlineSmall, }; return ( - {children} - + ); }; diff --git a/src/components/Divider.tsx b/src/components/Divider.tsx index be30d94c7c..c697a2a04a 100644 --- a/src/components/Divider.tsx +++ b/src/components/Divider.tsx @@ -1,10 +1,7 @@ import * as React from 'react'; import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native'; -import color from 'color'; - import { useInternalTheme } from '../core/theming'; -import { black, white } from '../styles/themes/v2/colors'; import type { $RemoveChildren, ThemeProp } from '../types'; export type Props = $RemoveChildren & { @@ -60,23 +57,17 @@ const Divider = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); - const { dark: isDarkTheme, isV3 } = theme; - const dividerColor = isV3 - ? theme.colors.outlineVariant - : color(isDarkTheme ? white : black) - .alpha(0.12) - .rgb() - .string(); + const dividerColor = theme.colors.outlineVariant; return ( @@ -84,9 +75,6 @@ const Divider = ({ }; const styles = StyleSheet.create({ - leftInset: { - marginLeft: 72, - }, v3LeftInset: { marginLeft: 16, }, diff --git a/src/components/Drawer/DrawerCollapsedItem.tsx b/src/components/Drawer/DrawerCollapsedItem.tsx index 9fb461e9c5..c10c7ac0b6 100644 --- a/src/components/Drawer/DrawerCollapsedItem.tsx +++ b/src/components/Drawer/DrawerCollapsedItem.tsx @@ -111,7 +111,6 @@ const DrawerCollapsedItem = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); - const { isV3 } = theme; const { scale } = theme.animation; const [numOfLines, setNumOfLines] = React.useState(1); @@ -126,10 +125,6 @@ const DrawerCollapsedItem = ({ } }, [animScale, active]); - if (!isV3) { - return null; - } - const handlePressOut = () => { Animated.timing(animScale, { toValue: 1, @@ -163,7 +158,7 @@ const DrawerCollapsedItem = ({ const labelTextStyle = { color: labelColor, - ...(isV3 ? theme.fonts.labelMedium : {}), + ...theme.fonts.labelMedium, }; const icon = diff --git a/src/components/Drawer/DrawerItem.tsx b/src/components/Drawer/DrawerItem.tsx index 604df1b83b..7af3d9fcf4 100644 --- a/src/components/Drawer/DrawerItem.tsx +++ b/src/components/Drawer/DrawerItem.tsx @@ -108,27 +108,17 @@ const DrawerItem = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); - const { roundness, isV3 } = theme; + const { roundness } = theme; - const backgroundColor = active - ? isV3 - ? theme.colors.secondaryContainer - : color(theme.colors.primary).alpha(0.12).rgb().string() - : undefined; + const backgroundColor = active ? theme.colors.secondaryContainer : undefined; const contentColor = active - ? isV3 - ? theme.colors.onSecondaryContainer - : theme.colors.primary - : isV3 - ? theme.colors.onSurfaceVariant - : color(theme.colors.text).alpha(0.68).rgb().string(); + ? theme.colors.onSecondaryContainer + : theme.colors.onSurfaceVariant; - const labelMargin = icon ? (isV3 ? 12 : 32) : 0; - const borderRadius = (isV3 ? 7 : 1) * roundness; - const rippleColor = isV3 - ? color(contentColor).alpha(0.12).rgb().string() - : undefined; - const font = isV3 ? theme.fonts.labelLarge : theme.fonts.medium; + const labelMargin = icon ? 12 : 0; + const borderRadius = 7 * roundness; + const rippleColor = color(contentColor).alpha(0.12).rgb().string(); + const font = theme.fonts.labelLarge; return ( @@ -139,8 +129,8 @@ const DrawerItem = ({ onPress={onPress} style={[ styles.container, + styles.v3Container, { backgroundColor, borderRadius }, - isV3 && styles.v3Container, style, ]} accessibilityRole="button" @@ -150,7 +140,7 @@ const DrawerItem = ({ theme={theme} hitSlop={hitSlop} > - + {icon ? ( diff --git a/src/components/Drawer/DrawerSection.tsx b/src/components/Drawer/DrawerSection.tsx index ed79c5e054..a701d38ad6 100644 --- a/src/components/Drawer/DrawerSection.tsx +++ b/src/components/Drawer/DrawerSection.tsx @@ -1,8 +1,6 @@ import * as React from 'react'; import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native'; -import color from 'color'; - import { useInternalTheme } from '../../core/theming'; import { MD3Colors } from '../../styles/themes/v3/tokens'; import type { ThemeProp } from '../../types'; @@ -73,17 +71,14 @@ const DrawerSection = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); - const { isV3 } = theme; - const titleColor = isV3 - ? theme.colors.onSurfaceVariant - : color(theme.colors.text).alpha(0.54).rgb().string(); - const titleMargin = isV3 ? 28 : 16; - const font = isV3 ? theme.fonts.titleSmall : theme.fonts.medium; + const titleColor = theme.colors.onSurfaceVariant; + const titleMargin = 28; + const font = theme.fonts.titleSmall; return ( {title && ( - + {title && ( )} diff --git a/src/components/FAB/AnimatedFAB.tsx b/src/components/FAB/AnimatedFAB.tsx index ecfe7e1c60..6b6964a4a9 100644 --- a/src/components/FAB/AnimatedFAB.tsx +++ b/src/components/FAB/AnimatedFAB.tsx @@ -129,7 +129,6 @@ export type Props = $Omit<$RemoveChildren, 'mode'> & { }; const SIZE = 56; -const SCALE = 0.9; /** * An animated, extending horizontally floating action button represents the primary action in an application. @@ -233,7 +232,7 @@ const AnimatedFAB = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); - const uppercase: boolean = uppercaseProp ?? !theme.isV3; + const uppercase: boolean = uppercaseProp ?? false; const isIOS = Platform.OS === 'ios'; const isWeb = Platform.OS === 'web'; const isAnimatedFromRight = animateFrom === 'right'; @@ -246,7 +245,7 @@ const AnimatedFAB = ({ const { current: animFAB } = React.useRef( new Animated.Value(0) ); - const { isV3, animation } = theme; + const { animation } = theme; const { scale } = animation; const labelSize = isWeb ? getLabelSizeWeb(labelRef) : null; @@ -257,7 +256,7 @@ const AnimatedFAB = ({ labelSize?.height ?? 0 ); - const borderRadius = SIZE / (isV3 ? 3.5 : 2); + const borderRadius = SIZE / 3.5; React.useEffect(() => { if (!isWeb) { @@ -364,17 +363,16 @@ const AnimatedFAB = ({ animFAB, }); - const font = isV3 ? theme.fonts.labelLarge : theme.fonts.medium; + const font = theme.fonts.labelLarge; const textStyle = { color: foregroundColor, ...font, }; - const md2Elevation = disabled || !isIOS ? 0 : 6; const md3Elevation = disabled || !isIOS ? 0 : 3; - const shadowStyle = isV3 ? styles.v3Shadow : styles.shadow; + const shadowStyle = styles.v3Shadow; const baseStyle = [ StyleSheet.absoluteFill, disabled ? styles.disabled : shadowStyle, @@ -396,32 +394,14 @@ const AnimatedFAB = ({ ], borderRadius, }, - !isV3 && { - elevation: md2Elevation, - }, styles.container, restStyle, ]} - {...(isV3 && { elevation: md3Elevation })} + elevation={md3Elevation} theme={theme} container > - + ( ref ) => { const theme = useInternalTheme(themeOverrides); - const uppercase = uppercaseProp ?? !theme.isV3; + const uppercase = uppercaseProp ?? false; const { current: visibility } = React.useRef( new Animated.Value(visible ? 1 : 0) ); - const { isV3, animation } = theme; + const { animation } = theme; const { scale } = animation; React.useEffect(() => { @@ -255,7 +255,7 @@ const FAB = forwardRef( const isFlatMode = mode === 'flat'; const iconSize = isLargeSize ? 36 : 24; const loadingIndicatorSize = isLargeSize ? 24 : 18; - const font = isV3 ? theme.fonts.labelLarge : theme.fonts.medium; + const font = theme.fonts.labelLarge; const extendedStyle = getExtendedFabStyle({ customSize, theme }); const textStyle = { @@ -282,13 +282,11 @@ const FAB = forwardRef( }, ], }, - !isV3 && styles.elevated, - !isV3 && disabled && styles.disabled, style, ]} pointerEvents={visible ? 'auto' : 'none'} testID={`${testID}-container`} - {...(isV3 && { elevation: md3Elevation })} + elevation={md3Elevation} container > ( ); const styles = StyleSheet.create({ - elevated: { - elevation: 6, - }, content: { flexDirection: 'row', alignItems: 'center', @@ -361,9 +356,6 @@ const styles = StyleSheet.create({ uppercaseLabel: { textTransform: 'uppercase', }, - disabled: { - elevation: 0, - }, }); export default FAB; diff --git a/src/components/FAB/FABGroup.tsx b/src/components/FAB/FABGroup.tsx index ca263e3499..de88de8185 100644 --- a/src/components/FAB/FABGroup.tsx +++ b/src/components/FAB/FABGroup.tsx @@ -250,7 +250,6 @@ const FABGroup = ({ >(null); const { scale } = theme.animation; - const { isV3 } = theme; React.useEffect(() => { if (open) { @@ -262,7 +261,7 @@ const FABGroup = ({ useNativeDriver: true, }), Animated.stagger( - isV3 ? 15 : 50 * scale, + 15, animations.current .map((animation) => Animated.timing(animation, { @@ -294,7 +293,7 @@ const FABGroup = ({ } }); } - }, [open, actions, backdrop, scale, isV3]); + }, [open, actions, backdrop, scale]); const close = () => onStateChange({ open: false }); const toggle = () => onStateChange({ open: !open }); @@ -326,14 +325,6 @@ const FABGroup = ({ : backdrop; const opacities = animations.current; - const scales = opacities.map((opacity) => - open - ? opacity.interpolate({ - inputRange: [0, 1], - outputRange: [0.5, 1], - }) - : 1 - ); const translations = opacities.map((opacity) => open @@ -395,7 +386,7 @@ const FABGroup = ({ {actions.map((it, i) => { const labelTextStyle = { color: it.labelTextColor ?? labelColor, - ...(isV3 ? theme.fonts.titleMedium : {}), + ...theme.fonts.titleMedium, }; const marginHorizontal = typeof it.size === 'undefined' || it.size === 'small' ? 24 : 16; @@ -430,7 +421,7 @@ const FABGroup = ({ {it.label && ( @@ -467,11 +454,10 @@ const FABGroup = ({ color={it.color} style={[ { - transform: [{ scale: scales[i] }], + transform: [{ translateY: translations[i] }], opacity: opacities[i], backgroundColor: stackedFABBackgroundColor, }, - isV3 && { transform: [{ translateY: translations[i] }] }, it.style, ]} accessibilityElementsHidden={true} diff --git a/src/components/FAB/utils.ts b/src/components/FAB/utils.ts index e87d24019f..42dd05ff7e 100644 --- a/src/components/FAB/utils.ts +++ b/src/components/FAB/utils.ts @@ -9,9 +9,7 @@ import { import color from 'color'; -import { black, white } from '../../styles/themes/v2/colors'; import type { InternalTheme } from '../../types'; -import getContrastingColor from '../../utils/getContrastingColor'; type GetCombinedStylesProps = { isAnimatedFromRight: boolean; @@ -174,88 +172,60 @@ const getBackgroundColor = ({ return customBackgroundColor; } - if (theme.isV3) { - if (disabled) { - return theme.colors.surfaceDisabled; - } - - if (isVariant('primary')) { - return theme.colors.primaryContainer; - } + if (disabled) { + return theme.colors.surfaceDisabled; + } - if (isVariant('secondary')) { - return theme.colors.secondaryContainer; - } + if (isVariant('primary')) { + return theme.colors.primaryContainer; + } - if (isVariant('tertiary')) { - return theme.colors.tertiaryContainer; - } + if (isVariant('secondary')) { + return theme.colors.secondaryContainer; + } - if (isVariant('surface')) { - return theme.colors.elevation.level3; - } + if (isVariant('tertiary')) { + return theme.colors.tertiaryContainer; } - if (disabled) { - if (theme.dark) { - return color(white).alpha(0.12).rgb().string(); - } - return color(black).alpha(0.12).rgb().string(); + if (isVariant('surface')) { + return theme.colors.elevation.level3; } - //@ts-ignore - return theme.colors?.accent; + return theme.colors.primaryContainer; }; const getForegroundColor = ({ theme, isVariant, disabled, - backgroundColor, customColor, -}: BaseProps & { backgroundColor: string; customColor?: string }) => { +}: BaseProps & { customColor?: string }) => { if (typeof customColor !== 'undefined' && !disabled) { return customColor; } - if (theme.isV3) { - if (disabled) { - return theme.colors.onSurfaceDisabled; - } - - if (isVariant('primary')) { - return theme.colors.onPrimaryContainer; - } - - if (isVariant('secondary')) { - return theme.colors.onSecondaryContainer; - } + if (disabled) { + return theme.colors.onSurfaceDisabled; + } - if (isVariant('tertiary')) { - return theme.colors.onTertiaryContainer; - } + if (isVariant('primary')) { + return theme.colors.onPrimaryContainer; + } - if (isVariant('surface')) { - return theme.colors.primary; - } + if (isVariant('secondary')) { + return theme.colors.onSecondaryContainer; } - if (disabled) { - if (theme.dark) { - return color(white).alpha(0.32).rgb().string(); - } - return color(black).alpha(0.32).rgb().string(); + if (isVariant('tertiary')) { + return theme.colors.onTertiaryContainer; } - if (backgroundColor) { - return getContrastingColor( - backgroundColor || white, - white, - 'rgba(0, 0, 0, .54)' - ); + if (isVariant('surface')) { + return theme.colors.primary; } - return getContrastingColor(white, white, 'rgba(0, 0, 0, .54)'); + return theme.colors.onPrimaryContainer; }; export const getFABColors = ({ @@ -287,7 +257,6 @@ export const getFABColors = ({ const foregroundColor = getForegroundColor({ ...baseFABColorProps, customColor, - backgroundColor, }); return { @@ -299,15 +268,7 @@ export const getFABColors = ({ }; const getLabelColor = ({ theme }: { theme: InternalTheme }) => { - if (theme.isV3) { - return theme.colors.onSurface; - } - - if (theme.dark) { - return theme.colors.text; - } - - return color(theme.colors.text).fade(0.54).rgb().string(); + return theme.colors.onSurface; }; const getBackdropColor = ({ @@ -320,17 +281,11 @@ const getBackdropColor = ({ if (customBackdropColor) { return customBackdropColor; } - if (theme.isV3) { - return color(theme.colors.background).alpha(0.95).rgb().string(); - } - return theme.colors?.backdrop; + return color(theme.colors.background).alpha(0.95).rgb().string(); }; const getStackedFABBackgroundColor = ({ theme }: { theme: InternalTheme }) => { - if (theme.isV3) { - return theme.colors.elevation.level3; - } - return theme.colors.surface; + return theme.colors.elevation.level3; }; export const getFABGroupColors = ({ @@ -347,16 +302,6 @@ export const getFABGroupColors = ({ }; }; -const standardSize = { - height: 56, - width: 56, - borderRadius: 28, -}; -const smallSize = { - height: 40, - width: 40, - borderRadius: 28, -}; const v3SmallSize = { height: 40, width: 40, @@ -385,30 +330,18 @@ export const getFabStyle = ({ size: 'small' | 'medium' | 'large'; theme: InternalTheme; }) => { - const { isV3, roundness } = theme; + const { roundness } = theme; if (customSize) return getCustomFabSize(customSize, roundness); - if (isV3) { - switch (size) { - case 'small': - return { ...v3SmallSize, borderRadius: 3 * roundness }; - case 'medium': - return { ...v3MediumSize, borderRadius: 4 * roundness }; - case 'large': - return { ...v3LargeSize, borderRadius: 7 * roundness }; - } - } - - if (size === 'small') { - return smallSize; + switch (size) { + case 'small': + return { ...v3SmallSize, borderRadius: 3 * roundness }; + case 'medium': + return { ...v3MediumSize, borderRadius: 4 * roundness }; + case 'large': + return { ...v3LargeSize, borderRadius: 7 * roundness }; } - return standardSize; -}; - -const extended = { - height: 48, - paddingHorizontal: 16, }; const v3Extended = { @@ -424,16 +357,14 @@ const getExtendedFabDimensions = (customSize: number) => ({ export const getExtendedFabStyle = ({ customSize, - theme, + theme: _theme, }: { customSize?: number; theme: InternalTheme; }) => { if (customSize) return getExtendedFabDimensions(customSize); - const { isV3 } = theme; - - return isV3 ? v3Extended : extended; + return v3Extended; }; let cachedContext: CanvasRenderingContext2D | null = null; diff --git a/src/components/HelperText/utils.ts b/src/components/HelperText/utils.ts index 4134175416..ab9d2dde8e 100644 --- a/src/components/HelperText/utils.ts +++ b/src/components/HelperText/utils.ts @@ -1,5 +1,3 @@ -import color from 'color'; - import type { InternalTheme } from '../../types'; type BaseProps = { @@ -9,22 +7,14 @@ type BaseProps = { }; export function getTextColor({ theme, disabled, type }: BaseProps) { - const { colors, dark } = theme; + const { colors } = theme; if (type === 'error') { return colors?.error; } - if (theme.isV3) { - if (disabled) { - return theme.colors.onSurfaceDisabled; - } else { - return theme.colors.onSurfaceVariant; - } + if (disabled) { + return theme.colors.onSurfaceDisabled; } - - return color(theme?.colors?.text) - .alpha(dark ? 0.7 : 0.54) - .rgb() - .string(); + return theme.colors.onSurfaceVariant; } diff --git a/src/components/Icon.tsx b/src/components/Icon.tsx index b3d26c699d..b886e06fe2 100644 --- a/src/components/Icon.tsx +++ b/src/components/Icon.tsx @@ -122,8 +122,7 @@ const Icon = ({ typeof source === 'object' && source.direction && source.source ? source.source : source; - const iconColor = - color || (theme.isV3 ? theme.colors.onSurface : theme.colors.text); + const iconColor = color || theme.colors.onSurface; if (isImageSource(s)) { return ( diff --git a/src/components/IconButton/IconButton.tsx b/src/components/IconButton/IconButton.tsx index 47a87901ca..2da6e12fcf 100644 --- a/src/components/IconButton/IconButton.tsx +++ b/src/components/IconButton/IconButton.tsx @@ -138,7 +138,6 @@ const IconButton = forwardRef( ref ) => { const theme = useInternalTheme(themeOverrides); - const { isV3 } = theme; const IconComponent = animated ? CrossFadeIcon : Icon; @@ -153,10 +152,10 @@ const IconButton = forwardRef( customRippleColor, }); - const buttonSize = isV3 ? size + 2 * PADDING : size * 1.5; + const buttonSize = size + 2 * PADDING; const { - borderWidth = isV3 && mode === 'outlined' && !selected ? 1 : 0, + borderWidth = mode === 'outlined' && !selected ? 1 : 0, borderRadius = buttonSize / 2, } = (StyleSheet.flatten(style) || {}) as ViewStyle; @@ -178,11 +177,10 @@ const IconButton = forwardRef( }, styles.container, borderStyles, - !isV3 && disabled && styles.disabled, style, ]} container - {...(isV3 && { elevation: 0 })} + elevation={0} > { - if (theme.isV3) { - if (disabled) { - return theme.colors.surfaceDisabled; - } - - return theme.colors.outline; + if (disabled) { + return theme.colors.surfaceDisabled; } - return undefined; + return theme.colors.outline; }; const getBackgroundColor = ({ @@ -38,40 +34,34 @@ const getBackgroundColor = ({ selected, customContainerColor, }: BaseProps & { customContainerColor?: string }) => { - if (theme.isV3) { - if (disabled) { - if (isMode('contained') || isMode('contained-tonal')) { - return theme.colors.surfaceDisabled; - } - } - - if (typeof customContainerColor !== 'undefined') { - return customContainerColor; + if (disabled) { + if (isMode('contained') || isMode('contained-tonal')) { + return theme.colors.surfaceDisabled; } + } - if (isMode('contained')) { - if (selected) { - return theme.colors.primary; - } - return theme.colors.surfaceVariant; - } + if (typeof customContainerColor !== 'undefined') { + return customContainerColor; + } - if (isMode('contained-tonal')) { - if (selected) { - return theme.colors.secondaryContainer; - } - return theme.colors.surfaceVariant; + if (isMode('contained')) { + if (selected) { + return theme.colors.primary; } + return theme.colors.surfaceVariant; + } - if (isMode('outlined')) { - if (selected) { - return theme.colors.inverseSurface; - } + if (isMode('contained-tonal')) { + if (selected) { + return theme.colors.secondaryContainer; } + return theme.colors.surfaceVariant; } - if (typeof customContainerColor !== 'undefined') { - return customContainerColor; + if (isMode('outlined')) { + if (selected) { + return theme.colors.inverseSurface; + } } return undefined; @@ -84,65 +74,52 @@ const getIconColor = ({ selected, customIconColor, }: BaseProps & { customIconColor?: string }) => { - if (theme.isV3) { - if (disabled) { - return theme.colors.onSurfaceDisabled; - } - - if (typeof customIconColor !== 'undefined') { - return customIconColor; - } + if (disabled) { + return theme.colors.onSurfaceDisabled; + } - if (isMode('contained')) { - if (selected) { - return theme.colors.onPrimary; - } - return theme.colors.primary; - } + if (typeof customIconColor !== 'undefined') { + return customIconColor; + } - if (isMode('contained-tonal')) { - if (selected) { - return theme.colors.onSecondaryContainer; - } - return theme.colors.onSurfaceVariant; + if (isMode('contained')) { + if (selected) { + return theme.colors.onPrimary; } + return theme.colors.primary; + } - if (isMode('outlined')) { - if (selected) { - return theme.colors.inverseOnSurface; - } - return theme.colors.onSurfaceVariant; + if (isMode('contained-tonal')) { + if (selected) { + return theme.colors.onSecondaryContainer; } + return theme.colors.onSurfaceVariant; + } + if (isMode('outlined')) { if (selected) { - return theme.colors.primary; + return theme.colors.inverseOnSurface; } return theme.colors.onSurfaceVariant; } - if (typeof customIconColor !== 'undefined') { - return customIconColor; + if (selected) { + return theme.colors.primary; } - - return theme.colors.text; + return theme.colors.onSurfaceVariant; }; const getRippleColor = ({ - theme, iconColor, customRippleColor, }: { - theme: InternalTheme; iconColor: string; customRippleColor?: ColorValue; }) => { if (customRippleColor) { return customRippleColor; } - if (theme.isV3) { - return color(iconColor).alpha(0.12).rgb().string(); - } - return color(iconColor).alpha(0.32).rgb().string(); + return color(iconColor).alpha(0.12).rgb().string(); }; export const getIconButtonColor = ({ @@ -184,7 +161,7 @@ export const getIconButtonColor = ({ ...baseIconColorProps, customContainerColor, }), - rippleColor: getRippleColor({ theme, iconColor, customRippleColor }), + rippleColor: getRippleColor({ iconColor, customRippleColor }), borderColor: getBorderColor({ theme, disabled }), }; }; diff --git a/src/components/List/ListAccordion.tsx b/src/components/List/ListAccordion.tsx index 75505c7367..ace8810a71 100644 --- a/src/components/List/ListAccordion.tsx +++ b/src/components/List/ListAccordion.tsx @@ -212,9 +212,6 @@ const ListAccordion = ({ const onDescriptionTextLayout = ( event: NativeSyntheticEvent ) => { - if (!theme.isV3) { - return; - } const { nativeEvent } = event; setAlignToTop(nativeEvent.lines.length >= 2); }; @@ -241,12 +238,11 @@ const ListAccordion = ({ ? groupContext.expandedId === id : expandedInternal; - const { titleColor, descriptionColor, titleTextColor, rippleColor } = - getAccordionColors({ - theme, - isExpanded, - customRippleColor, - }); + const { descriptionColor, titleTextColor, rippleColor } = getAccordionColors({ + theme, + isExpanded, + customRippleColor, + }); const handlePress = groupContext && id !== undefined @@ -256,7 +252,7 @@ const ListAccordion = ({ {left ? left({ color: isExpanded ? theme.colors?.primary : descriptionColor, - style: getLeftStyles(alignToTop, description, theme.isV3), + style: getLeftStyles(alignToTop, description), }) : null} - + {right ? ( right({ @@ -329,7 +322,7 @@ const ListAccordion = ({ ) : ( @@ -348,10 +341,7 @@ const ListAccordion = ({ !child.props.right ) { return React.cloneElement(child, { - style: [ - theme.isV3 ? styles.childV3 : styles.child, - child.props.style, - ], + style: [styles.child, child.props.style], theme, }); } @@ -367,17 +357,10 @@ ListAccordion.displayName = 'List.Accordion'; const styles = StyleSheet.create({ container: { - padding: 8, - }, - containerV3: { paddingVertical: 8, paddingRight: 24, }, row: { - flexDirection: 'row', - alignItems: 'center', - }, - rowV3: { flexDirection: 'row', marginVertical: 6, }, @@ -392,17 +375,14 @@ const styles = StyleSheet.create({ description: { fontSize: 14, }, - item: { + contentItem: { + paddingLeft: 16, + }, + trailingItem: { marginVertical: 6, paddingLeft: 8, }, - itemV3: { - paddingLeft: 16, - }, child: { - paddingLeft: 64, - }, - childV3: { paddingLeft: 40, }, content: { diff --git a/src/components/List/ListIcon.tsx b/src/components/List/ListIcon.tsx index f1c7194c43..108d642383 100644 --- a/src/components/List/ListIcon.tsx +++ b/src/components/List/ListIcon.tsx @@ -51,10 +51,7 @@ const ListIcon = ({ const theme = useInternalTheme(themeOverrides); return ( - + ); @@ -62,13 +59,6 @@ const ListIcon = ({ const styles = StyleSheet.create({ item: { - margin: 8, - height: 40, - width: 40, - alignItems: 'center', - justifyContent: 'center', - }, - itemV3: { alignItems: 'center', justifyContent: 'center', }, diff --git a/src/components/List/ListImage.tsx b/src/components/List/ListImage.tsx index 9839be7b02..8eb887bddc 100644 --- a/src/components/List/ListImage.tsx +++ b/src/components/List/ListImage.tsx @@ -7,7 +7,6 @@ import { ImageStyle, } from 'react-native'; -import { useInternalTheme } from '../../core/theming'; import type { ThemeProp } from '../../types'; export type Props = { @@ -42,16 +41,11 @@ const ListImage = ({ style, source, variant = 'image', - theme: themeOverrides, + theme: _theme, }: Props) => { - const theme = useInternalTheme(themeOverrides); const getStyles = () => { if (variant === 'video') { - if (!theme.isV3) { - return [style, styles.video]; - } - - return [style, styles.videoV3]; + return [style, styles.video]; } return [style, styles.image]; @@ -73,11 +67,6 @@ const styles = StyleSheet.create({ height: 56, }, video: { - width: 100, - height: 64, - marginLeft: 0, - }, - videoV3: { width: 114, height: 64, marginLeft: 0, diff --git a/src/components/List/ListItem.tsx b/src/components/List/ListItem.tsx index 467eb9b67a..c50d075744 100644 --- a/src/components/List/ListItem.tsx +++ b/src/components/List/ListItem.tsx @@ -10,8 +10,6 @@ import { ViewStyle, } from 'react-native'; -import color from 'color'; - import { Style, getLeftStyles, getRightStyles } from './utils'; import { useInternalTheme } from '../../core/theming'; import type { $RemoveChildren, EllipsizeProp, ThemeProp } from '../../types'; @@ -169,9 +167,6 @@ const ListItem = ( const onDescriptionTextLayout = ( event: NativeSyntheticEvent ) => { - if (!theme.isV3) { - return; - } const { nativeEvent } = event; setAlignToTop(nativeEvent.lines.length >= 2); }; @@ -206,9 +201,7 @@ const ListItem = ( }; const renderTitle = () => { - const titleColor = theme.isV3 - ? theme.colors.onSurface - : color(theme.colors.text).alpha(0.87).rgb().string(); + const titleColor = theme.colors.onSurface; return typeof title === 'function' ? ( title({ @@ -230,32 +223,26 @@ const ListItem = ( ); }; - const descriptionColor = theme.isV3 - ? theme.colors.onSurfaceVariant - : color(theme.colors.text).alpha(0.54).rgb().string(); + const descriptionColor = theme.colors.onSurfaceVariant; return ( - + {left ? left({ color: descriptionColor, - style: getLeftStyles(alignToTop, description, theme.isV3), + style: getLeftStyles(alignToTop, description), }) : null} {renderTitle()} @@ -267,7 +254,7 @@ const ListItem = ( {right ? right({ color: descriptionColor, - style: getRightStyles(alignToTop, description, theme.isV3), + style: getRightStyles(alignToTop, description), }) : null} @@ -280,19 +267,12 @@ const Component = forwardRef(ListItem); const styles = StyleSheet.create({ container: { - padding: 8, - }, - containerV3: { paddingVertical: 8, paddingRight: 24, }, row: { width: '100%', flexDirection: 'row', - }, - rowV3: { - width: '100%', - flexDirection: 'row', marginVertical: 6, }, title: { @@ -302,10 +282,6 @@ const styles = StyleSheet.create({ fontSize: 14, }, item: { - marginVertical: 6, - paddingLeft: 8, - }, - itemV3: { paddingLeft: 16, }, content: { diff --git a/src/components/List/ListSubheader.tsx b/src/components/List/ListSubheader.tsx index 038b86a86e..38e0a9d41f 100644 --- a/src/components/List/ListSubheader.tsx +++ b/src/components/List/ListSubheader.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import { StyleProp, StyleSheet, TextStyle } from 'react-native'; -import color from 'color'; import type { ThemeProp } from 'src/types'; import { useInternalTheme } from '../../core/theming'; @@ -43,11 +42,9 @@ const ListSubheader = ({ }: Props) => { const theme = useInternalTheme(overrideTheme); - const textColor = theme.isV3 - ? theme.colors.onSurfaceVariant - : color(theme.colors.text).alpha(0.54).rgb().string(); + const textColor = theme.colors.onSurfaceVariant; - const font = theme.isV3 ? theme.fonts.bodyMedium : theme.fonts.medium; + const font = theme.fonts.bodyMedium; return ( { - const stylesV3 = { - marginRight: 0, - marginLeft: 16, + const stylesV3: Style = { + ...stylesV3Left, alignSelf: alignToTop ? 'flex-start' : 'center', }; @@ -47,14 +48,10 @@ export const getLeftStyles = ( return { ...styles.iconMarginLeft, ...styles.marginVerticalNone, - ...(isV3 && { ...stylesV3 }), + ...stylesV3, }; } - if (!isV3) { - return styles.iconMarginLeft; - } - return { ...styles.iconMarginLeft, ...stylesV3, @@ -63,11 +60,10 @@ export const getLeftStyles = ( export const getRightStyles = ( alignToTop: boolean, - description: Description, - isV3: boolean + description: Description ) => { - const stylesV3 = { - marginLeft: 16, + const stylesV3: Style = { + ...stylesV3Right, alignSelf: alignToTop ? 'flex-start' : 'center', }; @@ -75,14 +71,10 @@ export const getRightStyles = ( return { ...styles.iconMarginRight, ...styles.marginVerticalNone, - ...(isV3 && { ...stylesV3 }), + ...stylesV3, }; } - if (!isV3) { - return styles.iconMarginRight; - } - return { ...styles.iconMarginRight, ...stylesV3, @@ -104,13 +96,9 @@ export const getAccordionColors = ({ isExpanded?: boolean; customRippleColor?: ColorValue; }) => { - const titleColor = theme.isV3 - ? theme.colors.onSurface - : color(theme.colors.text).alpha(0.87).rgb().string(); + const titleColor = theme.colors.onSurface; - const descriptionColor = theme.isV3 - ? theme.colors.onSurfaceVariant - : color(theme.colors.text).alpha(0.54).rgb().string(); + const descriptionColor = theme.colors.onSurfaceVariant; const titleTextColor = isExpanded ? theme.colors?.primary : titleColor; @@ -118,7 +106,6 @@ export const getAccordionColors = ({ customRippleColor || color(titleTextColor).alpha(0.12).rgb().string(); return { - titleColor, descriptionColor, titleTextColor, rippleColor, diff --git a/src/components/Menu/Menu.tsx b/src/components/Menu/Menu.tsx index 956b362562..9ac794021b 100644 --- a/src/components/Menu/Menu.tsx +++ b/src/components/Menu/Menu.tsx @@ -23,7 +23,7 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context'; import MenuItem from './MenuItem'; import { useInternalTheme } from '../../core/theming'; -import type { MD3Elevation, ThemeProp } from '../../types'; +import type { MD3Elevation, MD3Theme, ThemeProp } from '../../types'; import { ElevationLevels } from '../../types'; import { addEventListener } from '../../utils/addEventListener'; import { BackHandler } from '../../utils/BackHandler/BackHandler'; @@ -196,6 +196,7 @@ const Menu = ({ keyboardShouldPersistTaps, }: Props) => { const theme = useInternalTheme(themeOverrides); + const { colors: md3Colors } = theme as MD3Theme; const insets = useSafeAreaInsets(); const [rendered, setRendered] = React.useState(visible); const [left, setLeft] = React.useState(0); @@ -618,7 +619,6 @@ const Menu = ({ }, ], borderRadius: theme.roundness, - ...(!theme.isV3 && { elevation: 8 }), ...(scrollableMenuHeight ? { height: scrollableMenuHeight } : {}), }; @@ -673,13 +673,13 @@ const Menu = ({ style={[ styles.shadowMenuContainer, shadowMenuContainerStyle, - theme.isV3 && { + { backgroundColor: - theme.colors.elevation[ELEVATION_LEVELS_MAP[elevation]], + md3Colors.elevation[ELEVATION_LEVELS_MAP[elevation]], }, contentStyle, ]} - {...(theme.isV3 && { elevation })} + elevation={elevation} testID={`${testID}-surface`} theme={theme} container diff --git a/src/components/Menu/MenuItem.tsx b/src/components/Menu/MenuItem.tsx index 4b8eb3740a..652ffc9a4f 100644 --- a/src/components/Menu/MenuItem.tsx +++ b/src/components/Menu/MenuItem.tsx @@ -18,7 +18,7 @@ import { MIN_WIDTH, } from './utils'; import { useInternalTheme } from '../../core/theming'; -import type { ThemeProp } from '../../types'; +import type { MD3Theme, ThemeProp } from '../../types'; import Icon, { IconSource } from '../Icon'; import TouchableRipple, { Props as TouchableRippleProps, @@ -156,16 +156,13 @@ const MenuItem = ({ disabled, customRippleColor, }); - const { isV3 } = theme; + const containerPadding = 12; - const containerPadding = isV3 ? 12 : 8; + const iconWidth = 24; - const iconWidth = isV3 ? 24 : 40; - - const minWidth = MIN_WIDTH - (isV3 ? 12 : 16); + const minWidth = MIN_WIDTH - 12; const maxWidth = getContentMaxWidth({ - isV3, iconWidth, leadingIcon, trailingIcon, @@ -173,7 +170,7 @@ const MenuItem = ({ const titleTextStyle = { color: titleColor, - ...(isV3 ? theme.fonts.bodyLarge : {}), + ...(theme as MD3Theme).fonts.bodyLarge, }; const newAccessibilityState = { ...accessibilityState, disabled }; @@ -198,22 +195,15 @@ const MenuItem = ({ > {leadingIcon ? ( - + ) : null} {title} - {isV3 && trailingIcon ? ( - + {trailingIcon ? ( + ) : null} @@ -257,12 +244,6 @@ const styles = StyleSheet.create({ row: { flexDirection: 'row', }, - title: { - fontSize: 16, - }, - item: { - marginHorizontal: 8, - }, content: { justifyContent: 'center', }, diff --git a/src/components/Menu/utils.ts b/src/components/Menu/utils.ts index c1b6189ba4..71c503bcc2 100644 --- a/src/components/Menu/utils.ts +++ b/src/components/Menu/utils.ts @@ -2,15 +2,13 @@ import type { ColorValue } from 'react-native'; import color from 'color'; -import { black, white } from '../../styles/themes/v2/colors'; -import type { InternalTheme } from '../../types'; +import type { InternalTheme, MD3Theme } from '../../types'; import type { IconSource } from '../Icon'; export const MIN_WIDTH = 112; export const MAX_WIDTH = 280; type ContentProps = { - isV3: boolean; iconWidth: number; leadingIcon?: IconSource; trailingIcon?: IconSource; @@ -23,38 +21,25 @@ type ColorProps = { }; const getDisabledColor = (theme: InternalTheme) => { - if (theme.isV3) { - return theme.colors.onSurfaceDisabled; - } - - return color(theme.dark ? white : black) - .alpha(0.32) - .rgb() - .string(); + return (theme as MD3Theme).colors.onSurfaceDisabled; }; const getTitleColor = ({ theme, disabled }: ColorProps) => { + const { colors } = theme as MD3Theme; if (disabled) { return getDisabledColor(theme); } - if (theme.isV3) { - return theme.colors.onSurface; - } - - return color(theme.colors.text).alpha(0.87).rgb().string(); + return colors.onSurface; }; const getIconColor = ({ theme, disabled }: ColorProps) => { + const { colors } = theme as MD3Theme; if (disabled) { return getDisabledColor(theme); } - if (theme.isV3) { - return theme.colors.onSurfaceVariant; - } - - return color(theme.colors.text).alpha(0.54).rgb().string(); + return colors.onSurfaceVariant; }; const getRippleColor = ({ @@ -65,11 +50,10 @@ const getRippleColor = ({ return customRippleColor; } - if (theme.isV3) { - return color(theme.colors.onSurfaceVariant).alpha(0.12).rgb().string(); - } - - return undefined; + return color((theme as MD3Theme).colors.onSurfaceVariant) + .alpha(0.12) + .rgb() + .string(); }; export const getMenuItemColor = ({ @@ -85,26 +69,17 @@ export const getMenuItemColor = ({ }; export const getContentMaxWidth = ({ - isV3, iconWidth, leadingIcon, trailingIcon, }: ContentProps) => { - if (isV3) { - if (leadingIcon && trailingIcon) { - return MAX_WIDTH - (2 * iconWidth + 24); - } - - if (leadingIcon || trailingIcon) { - return MAX_WIDTH - (iconWidth + 24); - } - - return MAX_WIDTH - 12; + if (leadingIcon && trailingIcon) { + return MAX_WIDTH - (2 * iconWidth + 24); } - if (leadingIcon) { - return MAX_WIDTH - (iconWidth + 48); + if (leadingIcon || trailingIcon) { + return MAX_WIDTH - (iconWidth + 24); } - return MAX_WIDTH - 16; + return MAX_WIDTH - 12; }; diff --git a/src/components/ProgressBar.tsx b/src/components/ProgressBar.tsx index 790204f4f8..c307df2479 100644 --- a/src/components/ProgressBar.tsx +++ b/src/components/ProgressBar.tsx @@ -10,8 +10,6 @@ import { ViewStyle, } from 'react-native'; -import setColor from 'color'; - import { useInternalTheme } from '../core/theming'; import type { ThemeProp } from '../types'; @@ -191,9 +189,7 @@ const ProgressBar = ({ }; const tintColor = color || theme.colors?.primary; - const trackTintColor = theme.isV3 - ? theme.colors.surfaceVariant - : setColor(tintColor).alpha(0.38).rgb().string(); + const trackTintColor = theme.colors.surfaceVariant; return ( ; } - const textColor = theme.isV3 ? theme.colors.onSurface : theme.colors.text; - const disabledTextColor = theme.isV3 - ? theme.colors.onSurfaceDisabled - : theme.colors.disabled; + const textColor = theme.colors.onSurface; + const disabledTextColor = theme.colors.onSurfaceDisabled; const textAlign = isLeading ? 'right' : 'left'; const computedStyle = { @@ -232,12 +230,7 @@ const RadioButtonItem = ({ {isLeading && radioButton} {label} @@ -270,7 +263,4 @@ const styles = StyleSheet.create({ flexShrink: 1, flexGrow: 1, }, - font: { - fontSize: 16, - }, }); diff --git a/src/components/Searchbar.tsx b/src/components/Searchbar.tsx index 891df22945..6377899280 100644 --- a/src/components/Searchbar.tsx +++ b/src/components/Searchbar.tsx @@ -23,7 +23,7 @@ import IconButton from './IconButton/IconButton'; import MaterialCommunityIcon from './MaterialCommunityIcon'; import Surface from './Surface'; import { useInternalTheme } from '../core/theming'; -import type { ThemeProp } from '../types'; +import type { MD3Theme, ThemeProp } from '../types'; import { forwardRef } from '../utils/forwardRef'; interface Style { @@ -208,6 +208,7 @@ const Searchbar = forwardRef( ref ) => { const theme = useInternalTheme(themeOverrides); + const { colors, fonts } = theme as MD3Theme; const root = React.useRef(null); React.useImperativeHandle(ref, () => ({ @@ -227,34 +228,26 @@ const Searchbar = forwardRef( onClearIconPress?.(e); }; - const { roundness, dark, isV3, fonts } = theme; + const { roundness, dark } = theme; - const placeholderTextColor = isV3 - ? theme.colors.onSurface - : theme.colors?.placeholder; - const textColor = isV3 ? theme.colors.onSurfaceVariant : theme.colors.text; - const md2IconColor = dark - ? textColor - : color(textColor).alpha(0.54).rgb().string(); - const iconColor = - customIconColor || (isV3 ? theme.colors.onSurfaceVariant : md2IconColor); + const placeholderTextColor = colors.onSurface; + const textColor = colors.onSurfaceVariant; + const iconColor = customIconColor || colors.onSurfaceVariant; const rippleColor = customRippleColor || color(textColor).alpha(0.32).rgb().string(); const traileringRippleColor = customTraileringRippleColor || color(textColor).alpha(0.32).rgb().string(); - const font = isV3 - ? { - ...fonts.bodyLarge, - lineHeight: Platform.select({ - ios: 0, - default: fonts.bodyLarge.lineHeight, - }), - } - : theme.fonts.regular; + const font = { + ...fonts.bodyLarge, + lineHeight: Platform.select({ + ios: 0, + default: fonts.bodyLarge.lineHeight, + }), + }; - const isBarMode = isV3 && mode === 'bar'; + const isBarMode = mode === 'bar'; const shouldRenderTraileringIcon = isBarMode && traileringIcon && @@ -265,16 +258,15 @@ const Searchbar = forwardRef( @@ -307,12 +299,12 @@ const Searchbar = forwardRef( ...font, ...Platform.select({ web: { outline: 'none' } }), }, - isV3 && (isBarMode ? styles.barModeInput : styles.viewModeInput), + isBarMode ? styles.barModeInput : styles.viewModeInput, inputStyle, ]} placeholder={placeholder || ''} placeholderTextColor={placeholderTextColor} - selectionColor={theme.colors?.primary} + selectionColor={colors.primary} underlineColorAndroid="transparent" returnKeyType="search" keyboardAppearance={dark ? 'dark' : 'light'} @@ -325,7 +317,7 @@ const Searchbar = forwardRef( {loading ? ( ) : ( // Clear icon should be always rendered within Searchbar – it's transparent, @@ -336,8 +328,8 @@ const Searchbar = forwardRef( pointerEvents={value ? 'auto' : 'none'} testID={`${testID}-icon-wrapper`} style={[ - isV3 && !value && styles.v3ClearIcon, - isV3 && right !== undefined && styles.v3ClearIconHidden, + !value && styles.v3ClearIcon, + right !== undefined && styles.v3ClearIconHidden, ]} > ( clearIcon || (({ size, color }) => ( ( accessibilityRole="button" borderless onPress={onTraileringIconPress} - iconColor={traileringIconColor || theme.colors.onSurfaceVariant} + iconColor={traileringIconColor || colors.onSurfaceVariant} rippleColor={traileringRippleColor} icon={traileringIcon} accessibilityLabel={traileringIconAccessibilityLabel} @@ -377,13 +369,13 @@ const Searchbar = forwardRef( ) : null} {isBarMode && right?.({ color: textColor, style: styles.rightStyle, testID })} - {isV3 && !isBarMode && showDivider && ( + {!isBarMode && showDivider && ( { if (checked) { - if (theme.isV3) { - return theme.colors.secondaryContainer; - } else { - return color(theme.colors.primary).alpha(0.12).rgb().string(); - } + return theme.colors.secondaryContainer; } return 'transparent'; }; -const getSegmentedButtonBorderColor = ({ - theme, - disabled, - checked, -}: BaseProps) => { - if (theme.isV3) { - if (disabled) { - return theme.colors.surfaceDisabled; - } - return theme.colors.outline; - } - if (checked) { - return theme.colors.primary; +const getSegmentedButtonBorderColor = ({ theme, disabled }: BaseProps) => { + if (disabled) { + return theme.colors.surfaceDisabled; } - - return color(theme.dark ? white : black) - .alpha(0.29) - .rgb() - .string(); + return theme.colors.outline; }; const getSegmentedButtonBorderWidth = ({ - theme, + theme: _t, }: Omit) => { - if (theme.isV3) { - return 1; - } - - return StyleSheet.hairlineWidth; + return 1; }; const getSegmentedButtonTextColor = ({ @@ -133,21 +107,13 @@ const getSegmentedButtonTextColor = ({ checkedColor, uncheckedColor, }: SegmentedButtonProps) => { - if (theme.isV3) { - if (disabled) { - return theme.colors.onSurfaceDisabled; - } - if (checked) { - return checkedColor ?? theme.colors.onSecondaryContainer; - } - return uncheckedColor ?? theme.colors.onSurface; - } - if (disabled) { - return theme.colors.disabled; + return theme.colors.onSurfaceDisabled; + } + if (checked) { + return checkedColor ?? theme.colors.onSecondaryContainer; } - // Primary color is used for checked state too. - return theme.colors.primary; + return uncheckedColor ?? theme.colors.onSurface; }; export const getSegmentedButtonColors = ({ diff --git a/src/components/Snackbar.tsx b/src/components/Snackbar.tsx index d11bc91a62..22b55bb02a 100644 --- a/src/components/Snackbar.tsx +++ b/src/components/Snackbar.tsx @@ -20,7 +20,7 @@ import MaterialCommunityIcon from './MaterialCommunityIcon'; import Surface from './Surface'; import Text from './Typography/Text'; import { useInternalTheme } from '../core/theming'; -import type { $Omit, $RemoveChildren, ThemeProp } from '../types'; +import type { $Omit, $RemoveChildren, MD3Theme, ThemeProp } from '../types'; export type Props = $Omit, 'mode'> & { /** @@ -243,7 +243,7 @@ const Snackbar = ({ } }, [visible, handleOnVisible, handleOnHidden]); - const { colors, roundness, isV3 } = theme; + const { colors, roundness } = theme as MD3Theme; if (hidden) { return null; @@ -257,11 +257,11 @@ const Snackbar = ({ ...actionProps } = action || {}; - const buttonTextColor = isV3 ? colors.inversePrimary : colors.accent; - const textColor = isV3 ? colors.inverseOnSurface : colors?.surface; - const backgroundColor = isV3 ? colors.inverseSurface : colors?.onSurface; + const buttonTextColor = colors.inversePrimary; + const textColor = colors.inverseOnSurface; + const backgroundColor = colors.inverseSurface; - const isIconButton = isV3 && onIconPress; + const isIconButton = Boolean(onIconPress); const marginLeft = action ? -12 : -16; @@ -301,7 +301,6 @@ const Snackbar = ({ accessibilityLiveRegion="polite" theme={theme} style={[ - !isV3 && styles.elevation, styles.container, { backgroundColor, @@ -322,7 +321,7 @@ const Snackbar = ({ ]} testID={testID} container - {...(isV3 && { elevation })} + elevation={elevation} {...rest} > {renderChildrenWithWrapper()} @@ -336,7 +335,7 @@ const Snackbar = ({ }} style={[styles.button, actionStyle]} textColor={buttonTextColor} - compact={!isV3} + compact={false} mode="text" theme={theme} rippleColor={actionRippleColor} @@ -350,7 +349,7 @@ const Snackbar = ({ accessibilityRole="button" borderless onPress={onIconPress} - iconColor={theme.colors.inverseOnSurface} + iconColor={colors.inverseOnSurface} rippleColor={rippleColor} theme={theme} icon={ @@ -423,9 +422,6 @@ const styles = StyleSheet.create({ marginRight: 8, marginLeft: 4, }, - elevation: { - elevation: 6, - }, icon: { width: 40, height: 40, diff --git a/src/components/Surface.tsx b/src/components/Surface.tsx index 3b46d099e1..2c8fad2461 100644 --- a/src/components/Surface.tsx +++ b/src/components/Surface.tsx @@ -10,9 +10,9 @@ import { } from 'react-native'; import { useInternalTheme } from '../core/theming'; -import overlay, { isAnimatedValue } from '../styles/overlay'; +import { isAnimatedValue } from '../styles/overlay'; import shadow from '../styles/shadow'; -import type { ThemeProp, MD3Elevation } from '../types'; +import type { MD3Elevation, MD3Theme, ThemeProp } from '../types'; import { forwardRef } from '../utils/forwardRef'; import { splitStyles } from '../utils/splitStyles'; @@ -57,30 +57,6 @@ export type Props = Omit, 'style'> & { container?: boolean; }; -const MD2Surface = forwardRef( - ({ style, theme: overrideTheme, ...rest }: Omit, ref) => { - const { elevation = 4 } = (StyleSheet.flatten(style) || {}) as ViewStyle; - const { dark: isDarkTheme, mode, colors } = useInternalTheme(overrideTheme); - - return ( - - ); - } -); - const outerLayerStyleProperties: (keyof ViewStyle)[] = [ 'position', 'alignSelf', @@ -277,14 +253,7 @@ const Surface = forwardRef( ) => { const theme = useInternalTheme(overridenTheme); - if (!theme.isV3) - return ( - - {children} - - ); - - const { colors } = theme; + const { colors } = theme as MD3Theme; const inputRange = [0, 1, 2, 3, 4, 5]; @@ -313,7 +282,7 @@ const Surface = forwardRef( testID={testID} style={[ { backgroundColor }, - elevation && isElevated ? shadow(elevation, theme.isV3) : null, + elevation && isElevated ? shadow(elevation) : null, style, ]} > diff --git a/src/components/Switch/utils.ts b/src/components/Switch/utils.ts index 2994495af9..34ffc26eb5 100644 --- a/src/components/Switch/utils.ts +++ b/src/components/Switch/utils.ts @@ -29,11 +29,7 @@ const getCheckedColor = ({ return color; } - if (theme.isV3) { - return theme.colors.primary; - } - - return theme.colors.accent; + return theme.colors.primary; }; const getThumbTintColor = ({ @@ -79,10 +75,7 @@ const getOnTintColor = ({ if (disabled) { if (theme.dark) { - if (theme.isV3) { - return setColor(white).alpha(0.06).rgb().string(); - } - return setColor(white).alpha(0.1).rgb().string(); + return setColor(white).alpha(0.06).rgb().string(); } return setColor(black).alpha(0.12).rgb().string(); } diff --git a/src/components/TextInput/Addons/Outline.tsx b/src/components/TextInput/Addons/Outline.tsx index 45b675fd8b..39ffa48b56 100644 --- a/src/components/TextInput/Addons/Outline.tsx +++ b/src/components/TextInput/Addons/Outline.tsx @@ -10,11 +10,9 @@ import { import { TextInputLabelProp } from '../types'; type OutlineProps = { - isV3: boolean; activeColor: string; backgroundColor: ColorValue; hasActiveOutline?: boolean; - focused?: boolean; outlineColor?: string; roundness?: number; label?: TextInputLabelProp; @@ -22,12 +20,10 @@ type OutlineProps = { }; export const Outline = ({ - isV3, label, activeColor, backgroundColor, hasActiveOutline, - focused, outlineColor, roundness, style, @@ -42,7 +38,7 @@ export const Outline = ({ { backgroundColor, borderRadius: roundness, - borderWidth: (isV3 ? hasActiveOutline : focused) ? 2 : 1, + borderWidth: hasActiveOutline ? 2 : 1, borderColor: hasActiveOutline ? activeColor : outlineColor, }, style, diff --git a/src/components/TextInput/Addons/Underline.tsx b/src/components/TextInput/Addons/Underline.tsx index 184cbe63b5..20b49233dc 100644 --- a/src/components/TextInput/Addons/Underline.tsx +++ b/src/components/TextInput/Addons/Underline.tsx @@ -3,8 +3,6 @@ import { Animated, StyleSheet, StyleProp, ViewStyle } from 'react-native'; import type { ThemeProp } from 'src/types'; -import { useInternalTheme } from '../../../core/theming'; - type UnderlineProps = { parentState: { focused: boolean; @@ -28,32 +26,28 @@ export const Underline = ({ underlineColorCustom, hasActiveOutline, style, - theme: themeOverrides, + theme: _themeOverrides, }: UnderlineProps) => { - const { isV3 } = useInternalTheme(themeOverrides); - let backgroundColor = parentState.focused ? activeColor : underlineColorCustom; if (error) backgroundColor = colors?.error; - const activeScale = isV3 ? 2 : 1; + const activeScale = 2; return ( = ({ forceFocus, paddingHorizontal, maxFontSizeMultiplier, - theme, disabled, }) => { if (adornmentConfig.length) { @@ -174,7 +168,6 @@ const TextInputAdornment: React.FunctionComponent = ({ return ( { const theme = useInternalTheme(themeOverrides); - const { AFFIX_OFFSET } = getConstants(theme.isV3); + const { AFFIX_OFFSET } = getConstants(); const { textStyle, diff --git a/src/components/TextInput/Adornment/TextInputIcon.tsx b/src/components/TextInput/Adornment/TextInputIcon.tsx index bd38ca64ab..8f4ce7c4df 100644 --- a/src/components/TextInput/Adornment/TextInputIcon.tsx +++ b/src/components/TextInput/Adornment/TextInputIcon.tsx @@ -69,7 +69,6 @@ const IconAdornment: React.FunctionComponent< icon: React.ReactNode; topPosition: number; side: 'left' | 'right'; - theme?: ThemeProp; disabled?: boolean; } & Omit > = ({ @@ -79,11 +78,9 @@ const IconAdornment: React.FunctionComponent< isTextInputFocused, forceFocus, testID, - theme: themeOverrides, disabled, }) => { - const { isV3 } = useInternalTheme(themeOverrides); - const { ICON_OFFSET } = getConstants(isV3); + const { ICON_OFFSET } = getConstants(); const style = { top: topPosition, diff --git a/src/components/TextInput/Adornment/utils.ts b/src/components/TextInput/Adornment/utils.ts index e7dae2b487..38d9541706 100644 --- a/src/components/TextInput/Adornment/utils.ts +++ b/src/components/TextInput/Adornment/utils.ts @@ -1,5 +1,3 @@ -import color from 'color'; - import type { InternalTheme } from '../../../types'; type BaseProps = { @@ -8,16 +6,11 @@ type BaseProps = { }; export function getTextColor({ theme, disabled }: BaseProps) { - if (theme.isV3) { - if (disabled) { - return theme.colors.onSurfaceDisabled; - } - return theme.colors.onSurfaceVariant; + if (disabled) { + return theme.colors.onSurfaceDisabled; } - return color(theme.colors?.text) - .alpha(theme.dark ? 0.7 : 0.54) - .rgb() - .string(); + + return theme.colors.onSurfaceVariant; } export function getIconColor({ @@ -36,10 +29,6 @@ export function getIconColor({ return customColor; } - if (!theme.isV3) { - return theme.colors.text; - } - if (disabled) { return theme.colors.onSurfaceDisabled; } diff --git a/src/components/TextInput/Label/InputLabel.tsx b/src/components/TextInput/Label/InputLabel.tsx index f0818f98f0..4877bc236e 100644 --- a/src/components/TextInput/Label/InputLabel.tsx +++ b/src/components/TextInput/Label/InputLabel.tsx @@ -48,12 +48,11 @@ const InputLabel = (props: InputLabelProps) => { labelTranslationXOffset, maxFontSizeMultiplier, testID, - isV3, inputContainerLayout, scaledLabel, } = props; - const { INPUT_PADDING_HORIZONTAL } = getConstants(isV3); + const { INPUT_PADDING_HORIZONTAL } = getConstants(); const { width } = useWindowDimensions(); const isWeb = Platform.OS === 'web'; diff --git a/src/components/TextInput/TextInputFlat.tsx b/src/components/TextInput/TextInputFlat.tsx index 378366e176..ee8e438fb4 100644 --- a/src/components/TextInput/TextInputFlat.tsx +++ b/src/components/TextInput/TextInputFlat.tsx @@ -78,12 +78,12 @@ const TextInputFlat = ({ ...rest }: ChildTextInputProps) => { const isAndroid = Platform.OS === 'android'; - const { colors, isV3, roundness } = theme; - const font = isV3 ? theme.fonts.bodyLarge : theme.fonts.regular; + const { colors, roundness } = theme; + const font = theme.fonts.bodyLarge; const hasActiveOutline = parentState.focused || error; const { LABEL_PADDING_TOP, FLAT_INPUT_OFFSET, MIN_HEIGHT, MIN_WIDTH } = - getConstants(isV3); + getConstants(); const { fontSize: fontSizeStyle, @@ -108,7 +108,6 @@ const TextInputFlat = ({ let { paddingLeft, paddingRight } = calculateFlatInputHorizontalPadding({ adornmentConfig, - isV3, }); if (isPaddingHorizontalPassed) { @@ -134,7 +133,6 @@ const TextInputFlat = ({ paddingHorizontal, inputOffset: FLAT_INPUT_OFFSET, mode: InputMode.Flat, - isV3, }); const { @@ -304,7 +302,6 @@ const TextInputFlat = ({ ? 1 : 0 : 1, - isV3, }; const affixTopPosition = { diff --git a/src/components/TextInput/TextInputOutlined.tsx b/src/components/TextInput/TextInputOutlined.tsx index 70b590fabb..0bd85fb8d9 100644 --- a/src/components/TextInput/TextInputOutlined.tsx +++ b/src/components/TextInput/TextInputOutlined.tsx @@ -81,12 +81,12 @@ const TextInputOutlined = ({ }: ChildTextInputProps) => { const adornmentConfig = getAdornmentConfig({ left, right }); - const { colors, isV3, roundness } = theme; - const font = isV3 ? theme.fonts.bodyLarge : theme.fonts.regular; + const { colors, roundness } = theme; + const font = theme.fonts.bodyLarge; const hasActiveOutline = parentState.focused || error; const { INPUT_PADDING_HORIZONTAL, MIN_HEIGHT, ADORNMENT_OFFSET, MIN_WIDTH } = - getConstants(isV3); + getConstants(); const { fontSize: fontSizeStyle, @@ -148,8 +148,8 @@ const TextInputOutlined = ({ if (isAdornmentLeftIcon) { labelTranslationXOffset = - (I18nManager.getConstants().isRTL ? -1 : 1) * - (ADORNMENT_SIZE + ADORNMENT_OFFSET - (isV3 ? 0 : 8)); + (I18nManager.getConstants().isRTL ? -1 : 1) * ADORNMENT_SIZE + + ADORNMENT_OFFSET; } const minInputHeight = @@ -254,7 +254,6 @@ const TextInputOutlined = ({ ? 1 : 0 : 1, - isV3, }; const onLayoutChange = React.useCallback( @@ -303,7 +302,6 @@ const TextInputOutlined = ({ rightAffixWidth, leftAffixWidth, mode: 'outlined', - isV3, }); const affixTopPosition = { [AdornmentSide.Left]: leftAffixTopPosition, @@ -344,12 +342,10 @@ const TextInputOutlined = ({ Otherwise the border will cut off the label on Android */} { const { LABEL_PADDING_HORIZONTAL, ADORNMENT_OFFSET, FLAT_INPUT_OFFSET } = - getConstants(isV3); + getConstants(); let paddingLeft = LABEL_PADDING_HORIZONTAL; let paddingRight = LABEL_PADDING_HORIZONTAL; @@ -320,19 +309,11 @@ const getInputTextColor = ({ return textColor; } - if (theme.isV3) { - if (disabled) { - return theme.colors.onSurfaceDisabled; - } - - return theme.colors.onSurface; - } - if (disabled) { - return color(theme.colors.text).alpha(0.54).rgb().string(); + return theme.colors.onSurfaceDisabled; } - return theme.colors.text; + return theme.colors.onSurface; }; const getActiveColor = ({ @@ -360,30 +341,18 @@ const getActiveColor = ({ } if (disabled) { - if (theme.isV3) { - return theme.colors.onSurfaceDisabled; - } - - return color(theme.colors.text).alpha(0.54).rgb().string(); + return theme.colors.onSurfaceDisabled; } return theme.colors.primary; }; const getPlaceholderColor = ({ theme, disabled }: BaseProps) => { - if (theme.isV3) { - if (disabled) { - return theme.colors.onSurfaceDisabled; - } - - return theme.colors.onSurfaceVariant; - } - if (disabled) { - return theme.colors.disabled; + return theme.colors.onSurfaceDisabled; } - return theme.colors.placeholder; + return theme.colors.onSurfaceVariant; }; const getSelectionColor = ({ @@ -405,21 +374,11 @@ const getSelectionColor = ({ }; const getFlatBackgroundColor = ({ theme, disabled }: BaseProps) => { - if (theme.isV3) { - if (disabled) { - return color(theme.colors.onSurface).alpha(0.04).rgb().string(); - } else { - return theme.colors.surfaceVariant; - } - } - if (disabled) { - return undefined; + return color(theme.colors.onSurface).alpha(0.04).rgb().string(); } - return theme.dark - ? color(theme.colors?.background).lighten(0.24).rgb().string() - : color(theme.colors?.background).darken(0.06).rgb().string(); + return theme.colors.surfaceVariant; }; const getFlatUnderlineColor = ({ @@ -431,19 +390,11 @@ const getFlatUnderlineColor = ({ return underlineColor; } - if (theme.isV3) { - if (disabled) { - return theme.colors.onSurfaceDisabled; - } - - return theme.colors.onSurfaceVariant; - } - if (disabled) { - return 'transparent'; + return theme.colors.onSurfaceDisabled; } - return theme.colors.disabled; + return theme.colors.onSurfaceVariant; }; const getOutlinedOutlineInputColor = ({ @@ -451,30 +402,19 @@ const getOutlinedOutlineInputColor = ({ disabled, customOutlineColor, }: BaseProps & { customOutlineColor?: string }) => { - const isTransparent = color(customOutlineColor).alpha() === 0; - if (!disabled && customOutlineColor) { return customOutlineColor; } - if (theme.isV3) { - if (disabled) { - if (theme.dark) { - return 'transparent'; - } - return theme.colors.surfaceDisabled; + if (disabled) { + if (theme.dark) { + return 'transparent'; } - return theme.colors.outline; + return theme.colors.surfaceDisabled; } - if (disabled) { - if (isTransparent) { - return customOutlineColor; - } - return theme.colors.disabled; - } - return theme.colors.placeholder; + return theme.colors.outline; }; export const getFlatInputColors = ({ @@ -560,53 +500,17 @@ export const getOutlinedInputColors = ({ }; }; -export const getConstants = (isV3?: boolean) => { - // Text input affix - let AFFIX_OFFSET; - // Text input icon - let ICON_OFFSET; - //Text input flat - let LABEL_PADDING_TOP; - let LABEL_PADDING_HORIZONTAL; - let FLAT_INPUT_OFFSET; - let MIN_HEIGHT; - // Text input outlined; - let INPUT_PADDING_HORIZONTAL; - let ADORNMENT_OFFSET; - let OUTLINED_INPUT_OFFSET; - - if (isV3) { - AFFIX_OFFSET = MD3_AFFIX_OFFSET; - ICON_OFFSET = MD3_ICON_OFFSET; - LABEL_PADDING_TOP = MD3_LABEL_PADDING_TOP; - LABEL_PADDING_HORIZONTAL = MD3_LABEL_PADDING_HORIZONTAL; - FLAT_INPUT_OFFSET = MD3_FLAT_INPUT_OFFSET; - MIN_HEIGHT = MD3_MIN_HEIGHT; - INPUT_PADDING_HORIZONTAL = MD3_INPUT_PADDING_HORIZONTAL; - ADORNMENT_OFFSET = MD3_ADORNMENT_OFFSET; - OUTLINED_INPUT_OFFSET = MD3_OUTLINED_INPUT_OFFSET; - } else { - AFFIX_OFFSET = MD2_AFFIX_OFFSET; - ICON_OFFSET = MD2_ICON_OFFSET; - LABEL_PADDING_TOP = MD2_LABEL_PADDING_TOP; - LABEL_PADDING_HORIZONTAL = MD2_LABEL_PADDING_HORIZONTAL; - FLAT_INPUT_OFFSET = MD2_FLAT_INPUT_OFFSET; - MIN_HEIGHT = MD2_MIN_HEIGHT; - INPUT_PADDING_HORIZONTAL = MD2_INPUT_PADDING_HORIZONTAL; - ADORNMENT_OFFSET = MD2_ADORNMENT_OFFSET; - OUTLINED_INPUT_OFFSET = MD2_OUTLINED_INPUT_OFFSET; - } - +export const getConstants = () => { return { - AFFIX_OFFSET, - ICON_OFFSET, - LABEL_PADDING_TOP, - LABEL_PADDING_HORIZONTAL, - FLAT_INPUT_OFFSET, - MIN_HEIGHT, - INPUT_PADDING_HORIZONTAL, - ADORNMENT_OFFSET, - OUTLINED_INPUT_OFFSET, + AFFIX_OFFSET: MD3_AFFIX_OFFSET, + ICON_OFFSET: MD3_ICON_OFFSET, + LABEL_PADDING_TOP: MD3_LABEL_PADDING_TOP, + LABEL_PADDING_HORIZONTAL: MD3_LABEL_PADDING_HORIZONTAL, + FLAT_INPUT_OFFSET: MD3_FLAT_INPUT_OFFSET, + MIN_HEIGHT: MD3_MIN_HEIGHT, + INPUT_PADDING_HORIZONTAL: MD3_INPUT_PADDING_HORIZONTAL, + ADORNMENT_OFFSET: MD3_ADORNMENT_OFFSET, + OUTLINED_INPUT_OFFSET: MD3_OUTLINED_INPUT_OFFSET, MIN_WIDTH, }; }; diff --git a/src/components/TextInput/types.tsx b/src/components/TextInput/types.tsx index 4ec2952366..1f710e4089 100644 --- a/src/components/TextInput/types.tsx +++ b/src/components/TextInput/types.tsx @@ -141,7 +141,6 @@ export type InputLabelProps = { inputContainerLayout: { width: number }; labelBackground?: any; maxFontSizeMultiplier?: number | undefined | null; - isV3?: boolean; scaledLabel?: boolean; } & LabelProps; diff --git a/src/components/ToggleButton/ToggleButton.tsx b/src/components/ToggleButton/ToggleButton.tsx index bfdd3fca5c..e115dec7ec 100644 --- a/src/components/ToggleButton/ToggleButton.tsx +++ b/src/components/ToggleButton/ToggleButton.tsx @@ -9,12 +9,9 @@ import { ColorValue, } from 'react-native'; -import color from 'color'; - import { ToggleButtonGroupContext } from './ToggleButtonGroup'; import { getToggleButtonColor } from './utils'; import { useInternalTheme } from '../../core/theming'; -import { black, white } from '../../styles/themes/v2/colors'; import type { ThemeProp } from '../../types'; import { forwardRef } from '../../utils/forwardRef'; import type { IconSource } from '../Icon'; @@ -128,12 +125,7 @@ const ToggleButton = forwardRef( (context && context.value === value) || status === 'checked'; const backgroundColor = getToggleButtonColor({ theme, checked }); - const borderColor = theme.isV3 - ? theme.colors.outline - : color(theme.dark ? white : black) - .alpha(0.29) - .rgb() - .string(); + const borderColor = theme.colors.outline; return ( { if (checked) { - if (theme.isV3) { - return color(theme.colors.onSecondaryContainer) - .alpha(tokens.md.ref.opacity.level2) - .rgb() - .string(); - } - if (theme.dark) { - return 'rgba(255, 255, 255, .12)'; - } - return 'rgba(0, 0, 0, .08)'; + return color(theme.colors.onSecondaryContainer) + .alpha(tokens.md.ref.opacity.level2) + .rgb() + .string(); } return 'transparent'; }; diff --git a/src/components/Tooltip/Tooltip.tsx b/src/components/Tooltip/Tooltip.tsx index f5a483db5a..fdfef8571f 100644 --- a/src/components/Tooltip/Tooltip.tsx +++ b/src/components/Tooltip/Tooltip.tsx @@ -204,9 +204,7 @@ const Tooltip = ({ style={[ styles.tooltip, { - backgroundColor: theme.isV3 - ? theme.colors.onSurface - : theme.colors.tooltip, + backgroundColor: theme.colors.onSurface, ...getTooltipPosition( measurement as Measurement, children as React.ReactElement diff --git a/src/components/TouchableRipple/utils.ts b/src/components/TouchableRipple/utils.ts index 29c2b18e25..e3a1e9726f 100644 --- a/src/components/TouchableRipple/utils.ts +++ b/src/components/TouchableRipple/utils.ts @@ -5,11 +5,9 @@ import color from 'color'; import type { InternalTheme } from '../../types'; const getUnderlayColor = ({ - theme, calculatedRippleColor, underlayColor, }: { - theme: InternalTheme; calculatedRippleColor: ColorValue; underlayColor?: string; }) => { @@ -17,11 +15,7 @@ const getUnderlayColor = ({ return underlayColor; } - if (theme.isV3) { - return color(calculatedRippleColor).rgb().string(); - } - - return color(calculatedRippleColor).fade(0.5).rgb().string(); + return color(calculatedRippleColor).rgb().string(); }; const getRippleColor = ({ @@ -35,14 +29,7 @@ const getRippleColor = ({ return rippleColor; } - if (theme.isV3) { - return color(theme.colors.onSurface).alpha(0.12).rgb().string(); - } - - if (theme.dark) { - return color(theme.colors.text).alpha(0.32).rgb().string(); - } - return color(theme.colors.text).alpha(0.2).rgb().string(); + return color(theme.colors.onSurface).alpha(0.12).rgb().string(); }; export const getTouchableRippleColors = ({ @@ -58,7 +45,6 @@ export const getTouchableRippleColors = ({ return { calculatedRippleColor, calculatedUnderlayColor: getUnderlayColor({ - theme, calculatedRippleColor, underlayColor, }), diff --git a/src/components/Typography/AnimatedText.tsx b/src/components/Typography/AnimatedText.tsx index 6504ad4b92..19872e2d93 100644 --- a/src/components/Typography/AnimatedText.tsx +++ b/src/components/Typography/AnimatedText.tsx @@ -50,7 +50,7 @@ const AnimatedText = forwardRef>( const theme = useInternalTheme(themeOverrides); const writingDirection = I18nManager.getConstants().isRTL ? 'rtl' : 'ltr'; - if (theme.isV3 && variant) { + if (variant) { const font = theme.fonts[variant]; if (typeof font !== 'object') { throw new Error( @@ -73,10 +73,10 @@ const AnimatedText = forwardRef>( /> ); } else { - const font = !theme.isV3 ? theme.fonts.regular : theme.fonts.bodyMedium; + const font = theme.fonts.bodyMedium; const textStyle = { ...font, - color: theme.isV3 ? theme.colors.onSurface : theme.colors.text, + color: theme.colors.onSurface, }; return ( root.current?.setNativeProps(args), })); - if (theme.isV3 && variant) { + if (variant) { let font = theme.fonts[variant]; let textStyle = [font, style]; @@ -155,10 +155,10 @@ const Text = ( /> ); } else { - const font = theme.isV3 ? theme.fonts.default : theme.fonts?.regular; + const font = theme.fonts.default; const textStyle = { ...font, - color: theme.isV3 ? theme.colors?.onSurface : theme.colors.text, + color: theme.colors?.onSurface, }; return ( & { const StyledText = ({ alpha = 1, - family, + family: _family, style, theme: themeOverrides, ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); - const textColor = color( - theme.isV3 ? theme.colors.onSurface : theme.colors?.text - ) - .alpha(alpha) - .rgb() - .string(); + const textColor = color(theme.colors.onSurface).alpha(alpha).rgb().string(); const writingDirection = I18nManager.getConstants().isRTL ? 'rtl' : 'ltr'; return ( @@ -38,7 +33,6 @@ const StyledText = ({ styles.text, { color: textColor, - ...(!theme.isV3 && theme.fonts?.[family]), writingDirection, }, style, diff --git a/src/components/Typography/v2/Text.tsx b/src/components/Typography/v2/Text.tsx index 8114915189..4e10eecf54 100644 --- a/src/components/Typography/v2/Text.tsx +++ b/src/components/Typography/v2/Text.tsx @@ -6,7 +6,7 @@ import { TextStyle, } from 'react-native'; -import type { MD2Theme } from 'src/types'; +import type { ThemeProp } from 'src/types'; import { useInternalTheme } from '../../../core/theming'; import { forwardRef } from '../../../utils/forwardRef'; @@ -16,7 +16,7 @@ type Props = React.ComponentProps & { /** * @optional */ - theme?: MD2Theme; + theme?: ThemeProp; }; // @component-group Typography @@ -43,8 +43,7 @@ const Text: React.ForwardRefRenderFunction<{}, Props> = ( ref={root} style={[ { - ...(!theme.isV3 && theme.fonts?.regular), - color: theme.isV3 ? theme.colors?.onSurface : theme.colors.text, + color: theme.colors?.onSurface, }, styles.text, style, diff --git a/src/components/__tests__/Appbar/Appbar.test.tsx b/src/components/__tests__/Appbar/Appbar.test.tsx index 6f76dab75b..60a7827b6e 100644 --- a/src/components/__tests__/Appbar/Appbar.test.tsx +++ b/src/components/__tests__/Appbar/Appbar.test.tsx @@ -1,12 +1,10 @@ import React from 'react'; -import { Animated, Platform } from 'react-native'; +import { Animated } from 'react-native'; import { act, render } from '@testing-library/react-native'; import mockSafeAreaContext from 'react-native-safe-area-context/jest/mock'; -import PaperProvider from '../../../core/PaperProvider'; import { getTheme } from '../../../core/theming'; -import overlay from '../../../styles/overlay'; import { tokens } from '../../../styles/themes/v3/tokens'; import Appbar from '../../Appbar'; import { @@ -17,7 +15,6 @@ import { } from '../../Appbar/utils'; import Menu from '../../Menu/Menu'; import Searchbar from '../../Searchbar'; -import Tooltip from '../../Tooltip/Tooltip'; import Text from '../../Typography/Text'; const renderAppbarContent = utilRenderAppbarContent as ( @@ -58,7 +55,6 @@ describe('renderAppbarContent', () => { it('should render all children types if renderOnly is not specified', () => { const result = renderAppbarContent({ - isV3: false, children, isDark: false, }); @@ -68,7 +64,6 @@ describe('renderAppbarContent', () => { it('should render all children types except specified in renderExcept', () => { const result = renderAppbarContent({ - isV3: false, children: [ ...children, { it('should render only children types specifed in renderOnly', () => { const result = renderAppbarContent({ - isV3: false, children, isDark: false, renderOnly: ['Appbar.Action'], @@ -104,7 +98,6 @@ describe('renderAppbarContent', () => { it('should render AppbarContent with correct mode', () => { const result = renderAppbarContent({ - isV3: false, children, isDark: false, renderOnly: ['Appbar.Content'], @@ -115,87 +108,34 @@ describe('renderAppbarContent', () => { }); it('should render centered AppbarContent', () => { - const renderResult = (isV3 = true) => - renderAppbarContent({ - children, - isDark: false, - isV3, - renderOnly: ['Appbar.Content'], - mode: 'center-aligned', - shouldCenterContent: true, - }); - - const centerAlignedContent = { - alignItems: 'center', - }; - - expect(renderResult()[0].props.style).toEqual( - expect.arrayContaining([expect.objectContaining(centerAlignedContent)]) - ); - - expect(renderResult(false)[0].props.style).toEqual( - expect.arrayContaining([expect.objectContaining(centerAlignedContent)]) - ); - }); - - it('should not render centered AppbarContent for Android, if not V3', () => { - Platform.OS = 'android'; - const renderResult = (isV3 = true) => - renderAppbarContent({ - children, - isDark: false, - isV3, - renderOnly: ['Appbar.Content'], - mode: 'center-aligned', - shouldCenterContent: !isV3 && Platform.OS === 'ios', - }); - - const centerAlignedContent = { - alignItems: 'center', - }; - - expect(renderResult(false)[0].props.style).not.toEqual( - expect.arrayContaining([expect.objectContaining(centerAlignedContent)]) - ); - }); - - it('should render centered AppbarContent always for iOS, if not V3', () => { - Platform.OS = 'ios'; - const renderResult = (isV3 = true) => - renderAppbarContent({ - children, - isDark: false, - isV3, - renderOnly: ['Appbar.Content'], - mode: 'center-aligned', - shouldCenterContent: !isV3 && Platform.OS === 'ios', - }); + const result = renderAppbarContent({ + children, + isDark: false, + renderOnly: ['Appbar.Content'], + mode: 'center-aligned', + shouldCenterContent: true, + }); const centerAlignedContent = { alignItems: 'center', }; - expect(renderResult(false)[0].props.style).toEqual( + expect(result[0].props.style).toEqual( expect.arrayContaining([expect.objectContaining(centerAlignedContent)]) ); }); it('should render AppbarContent with correct spacings', () => { - const renderResult = (isV3 = true, withAppbarBackAction = false) => + const renderResult = (withAppbarBackAction = false) => renderAppbarContent({ children, isDark: false, - isV3, renderOnly: [ 'Appbar.Content', withAppbarBackAction && 'Appbar.BackAction', ], }); - const v2Spacing = { - marginLeft: 8, - }; - const v3Spacing = { marginLeft: 12, }; @@ -203,10 +143,6 @@ describe('renderAppbarContent', () => { expect(renderResult()[0].props.style).toEqual( expect.arrayContaining([expect.objectContaining(v3Spacing)]) ); - - expect(renderResult(false, true)[1].props.style).toEqual( - expect.arrayContaining([expect.objectContaining(v2Spacing)]) - ); }); it('Is recognized as a header when no onPress callback has been pressed', () => { @@ -321,40 +257,6 @@ describe('AppbarAction', () => { .children; expect(appbarBackActionIcon.props.color).toBe('purple'); }); - - describe('When V2', () => { - const theme = { isV3: false }; - - it('should be rendered with the right color when no color is passed', () => { - const { getByTestId } = render( - - - - ); - - const appbarActionIcon = getByTestId('cross-fade-icon-current').props - .children; - - expect(appbarActionIcon.props.color).toBe('#ffffff'); - }); - - it('should be rendered with the right color when no color is passed but is wrapped by a Tooltip', () => { - const { getByTestId } = render( - - - - - - - - ); - - const appbarActionIcon = getByTestId('cross-fade-icon-current').props - .children; - - expect(appbarActionIcon.props.color).toBe('#ffffff'); - }); - }); }); describe('AppbarContent', () => { @@ -410,18 +312,6 @@ describe('getAppbarColors', () => { tokens.md.ref.palette.neutral10 ); }); - - it('should return v2 light color if theme version is 2', () => { - expect(getAppbarBackgroundColor(getTheme(false, false), elevation)).toBe( - '#6200ee' - ); - }); - - it('should return v2 dark color if theme version is 2', () => { - expect(getAppbarBackgroundColor(getTheme(true, false), elevation)).toBe( - overlay(elevation, '#121212') - ); - }); }); describe('animated value changes correctly', () => { diff --git a/src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap b/src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap index 4a62c376d8..14afac63f3 100644 --- a/src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap +++ b/src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap @@ -679,7 +679,6 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A "letterSpacing": 0, "lineHeight": 28, }, - false, undefined, ], ], diff --git a/src/components/__tests__/Banner.test.tsx b/src/components/__tests__/Banner.test.tsx index 8e0d8c90d1..048bfa7275 100644 --- a/src/components/__tests__/Banner.test.tsx +++ b/src/components/__tests__/Banner.test.tsx @@ -91,7 +91,7 @@ it('render visible banner, with custom theme', () => { visible theme={{ colors: { - text: '#00f', + onSurface: '#00f', surface: '#ccc', primary: '#043', }, diff --git a/src/components/__tests__/BottomNavigation.test.tsx b/src/components/__tests__/BottomNavigation.test.tsx index 43c1e9383b..f5bdeced00 100644 --- a/src/components/__tests__/BottomNavigation.test.tsx +++ b/src/components/__tests__/BottomNavigation.test.tsx @@ -2,10 +2,8 @@ import * as React from 'react'; import { Animated, Easing, Platform, StyleSheet } from 'react-native'; import { act, fireEvent, render } from '@testing-library/react-native'; -import color from 'color'; import { getTheme } from '../../core/theming'; -import { red300 } from '../../styles/themes/v2/colors'; import { MD3Colors } from '../../styles/themes/v3/tokens'; import BottomNavigation from '../BottomNavigation/BottomNavigation'; import BottomNavigationRouteScreen from '../BottomNavigation/BottomNavigationRouteScreen'; @@ -18,7 +16,7 @@ import Icon from '../Icon'; const styles = StyleSheet.create({ backgroundColor: { - backgroundColor: red300, + backgroundColor: MD3Colors.error60, }, }); @@ -378,7 +376,7 @@ it('renders custom background color passed to barStyle property', () => { ); const wrapper = getByTestId('bottom-navigation-bar-content'); - expect(wrapper).toHaveStyle({ backgroundColor: red300 }); + expect(wrapper).toHaveStyle({ backgroundColor: MD3Colors.error60 }); }); it('renders a single tab', () => { @@ -446,7 +444,7 @@ it('does not apply maxTabBarWidth styling if compact prop is falsy', () => { }); }); -it('displays ripple animation view if shifting is truthy', () => { +it('renders bar content when shifting is enabled', () => { const { getByTestId } = render( { renderScene={({ route }) => route.title} getLazy={({ route }) => route.key === 'key-2'} testID="bottom-navigation" - theme={{ isV3: false }} shifting /> ); - expect(getByTestId('bottom-navigation-bar-content-ripple')).toBeDefined(); + expect(getByTestId('bottom-navigation-bar-content')).toBeDefined(); }); -it('does not display ripple animation view if shifting is falsy', () => { +it('does not render legacy ripple overlay when shifting is disabled', () => { const { queryByTestId } = render( { describe('getActiveTintColor', () => { it.each` - activeColor | defaultColor | useV3 | expected - ${'#FBF7DB'} | ${'#fff'} | ${true} | ${'#FBF7DB'} - ${undefined} | ${'#fff'} | ${true} | ${MD3Colors.secondary10} - ${undefined} | ${'#fff'} | ${false} | ${'#fff'} + activeColor | expected + ${'#FBF7DB'} | ${'#FBF7DB'} + ${undefined} | ${MD3Colors.secondary10} `( - 'returns $expected when activeColor: $activeColor and useV3: $useV3', - ({ activeColor, defaultColor, useV3, expected }) => { - const theme = getTheme(false, useV3); - const color = getActiveTintColor({ activeColor, defaultColor, theme }); - expect(color).toBe(expected); + 'returns $expected when activeColor: $activeColor', + ({ activeColor, expected }) => { + const theme = getTheme(false); + const result = getActiveTintColor({ activeColor, theme }); + expect(result).toBe(expected); } ); }); describe('getInactiveTintColor', () => { it.each` - inactiveColor | defaultColor | useV3 | expected - ${'#853D4B'} | ${'#fff'} | ${true} | ${'#853D4B'} - ${undefined} | ${'#fff'} | ${true} | ${MD3Colors.neutralVariant30} - ${undefined} | ${'#fff'} | ${false} | ${color('#fff').alpha(0.5).rgb().string()} + inactiveColor | expected + ${'#853D4B'} | ${'#853D4B'} + ${undefined} | ${MD3Colors.neutralVariant30} `( - 'returns $expected when inactiveColor: $inactiveColor and useV3: $useV3', - ({ inactiveColor, defaultColor, useV3, expected }) => { - const theme = getTheme(false, useV3); - const color = getInactiveTintColor({ + 'returns $expected when inactiveColor: $inactiveColor', + ({ inactiveColor, expected }) => { + const theme = getTheme(false); + const result = getInactiveTintColor({ inactiveColor, - defaultColor, theme, }); - expect(color).toBe(expected); + expect(result).toBe(expected); } ); }); describe('getLabelColor', () => { it.each` - tintColor | focused | defaultColor | useV3 | expected - ${'#FBF7DB'} | ${true} | ${'#fff'} | ${true} | ${'#FBF7DB'} - ${'#853D4B'} | ${true} | ${'#fff'} | ${true} | ${'#853D4B'} - ${undefined} | ${true} | ${'#fff'} | ${true} | ${MD3Colors.neutral10} - ${undefined} | ${false} | ${'#fff'} | ${true} | ${MD3Colors.neutralVariant30} - ${undefined} | ${false} | ${'#fff'} | ${false} | ${'#fff'} - ${undefined} | ${true} | ${'#fff'} | ${false} | ${'#fff'} + tintColor | focused | expected + ${'#FBF7DB'} | ${true} | ${'#FBF7DB'} + ${'#853D4B'} | ${true} | ${'#853D4B'} + ${undefined} | ${true} | ${MD3Colors.neutral10} + ${undefined} | ${false} | ${MD3Colors.neutralVariant30} `( - 'returns $expected when tintColor: $tintColor, focused: $focused useV3: $useV3', - ({ tintColor, focused, defaultColor, useV3, expected }) => { - const theme = getTheme(false, useV3); - const color = getLabelColor({ - tintColor, + 'returns $expected when tintColor: $tintColor, focused: $focused', + ({ tintColor, focused, expected }) => { + const theme = getTheme(false); + const result = getLabelColor({ + tintColor: tintColor ?? '', hasColor: Boolean(tintColor), focused, - defaultColor, theme, }); - expect(color).toBe(expected); + expect(result).toBe(expected); } ); }); diff --git a/src/components/__tests__/Button.test.tsx b/src/components/__tests__/Button.test.tsx index 8917eaca92..3d16801c15 100644 --- a/src/components/__tests__/Button.test.tsx +++ b/src/components/__tests__/Button.test.tsx @@ -2,10 +2,9 @@ import * as React from 'react'; import { Animated, StyleSheet } from 'react-native'; import { act, fireEvent, render } from '@testing-library/react-native'; -import color from 'color'; import { getTheme } from '../../core/theming'; -import { black, pink500, white } from '../../styles/themes/v2/colors'; +import { pink500, white } from '../../styles/themes/v2/colors'; import Button from '../Button/Button'; import { getButtonColors } from '../Button/utils'; @@ -461,95 +460,6 @@ describe('getButtonColors - background color', () => { }); }) ); - - it('should return correct theme color, for theme version 2, contained mode', () => { - expect( - getButtonColors({ - theme: getTheme(false, false), - mode: 'contained', - }) - ).toMatchObject({ - backgroundColor: getTheme(false, false).colors.primary, - }); - }); - - it('should return correct theme color, for theme version 2, when disabled, contained mode', () => { - expect( - getButtonColors({ - theme: getTheme(false, false), - mode: 'contained', - disabled: true, - }) - ).toMatchObject({ - backgroundColor: color(black).alpha(0.12).rgb().string(), - }); - }); - - it('should return correct theme color, for theme version 2, when disabled, dark theme, contained mode', () => { - expect( - getButtonColors({ - theme: getTheme(true, false), - mode: 'contained', - disabled: true, - }) - ).toMatchObject({ - backgroundColor: color(white).alpha(0.12).rgb().string(), - }); - }); - - (['text', 'outlined'] as const).forEach((mode) => - it(`should return correct theme color, for theme version 2, ${mode} mode`, () => { - expect( - getButtonColors({ - theme: getTheme(false, false), - mode, - }) - ).toMatchObject({ - backgroundColor: 'transparent', - }); - }) - ); - - (['text', 'outlined'] as const).forEach((mode) => - it(`should return correct theme color, for theme version 2, dark theme, ${mode} mode`, () => { - expect( - getButtonColors({ - theme: getTheme(true, false), - mode, - }) - ).toMatchObject({ - backgroundColor: 'transparent', - }); - }) - ); - - (['text', 'outlined'] as const).forEach((mode) => - it(`should return correct theme color, for theme version 2, when disabled, ${mode} mode`, () => { - expect( - getButtonColors({ - theme: getTheme(false, false), - mode, - disabled: true, - }) - ).toMatchObject({ - backgroundColor: 'transparent', - }); - }) - ); - - (['text', 'outlined'] as const).forEach((mode) => - it(`should return correct theme color, for theme version 2, when disabled, dark theme, ${mode} mode`, () => { - expect( - getButtonColors({ - theme: getTheme(true, false), - mode, - disabled: true, - }) - ).toMatchObject({ - backgroundColor: 'transparent', - }); - }) - ); }); describe('getButtonColors - text color', () => { @@ -675,68 +585,6 @@ describe('getButtonColors - text color', () => { textColor: getTheme(true).colors.onSecondaryContainer, }); }); - - it('should return correct theme text color, for theme version 2, when disabled, no matter what the mode is', () => { - expect( - getButtonColors({ - theme: getTheme(false, false), - disabled: true, - mode: 'text', - }) - ).toMatchObject({ - textColor: color(black).alpha(0.32).rgb().string(), - }); - }); - - it('should return correct theme text color, for theme version 2, when disabled, dark theme, no matter what the mode is', () => { - expect( - getButtonColors({ - theme: getTheme(true, false), - disabled: true, - mode: 'text', - }) - ).toMatchObject({ - textColor: color(white).alpha(0.32).rgb().string(), - }); - }); - - it('should return correct theme text color, for theme version 2, contained mode', () => { - expect( - getButtonColors({ - theme: getTheme(false, false), - mode: 'contained', - dark: true, - }) - ).toMatchObject({ - textColor: '#ffffff', - }); - }); - - (['text', 'outlined'] as const).forEach((mode) => - it(`should return correct theme text color, for theme version 2, ${mode} mode`, () => { - expect( - getButtonColors({ - theme: getTheme(false, false), - mode, - }) - ).toMatchObject({ - textColor: getTheme(false, false).colors.primary, - }); - }) - ); - - (['text', 'outlined'] as const).forEach((mode) => - it(`should return correct theme text color, for theme version 2, dark theme, ${mode} mode`, () => { - expect( - getButtonColors({ - theme: getTheme(true, false), - mode, - }) - ).toMatchObject({ - textColor: getTheme(true, false).colors.primary, - }); - }) - ); }); describe('getButtonColors - border color', () => { @@ -813,56 +661,6 @@ describe('getButtonColors - border color', () => { }); }) ); - - it('should return correct border color, for theme version 2, outlined mode', () => { - expect( - getButtonColors({ - theme: getTheme(false, false), - mode: 'outlined', - }) - ).toMatchObject({ - borderColor: color(black).alpha(0.29).rgb().string(), - }); - }); - - it('should return correct border color, for theme version 2, dark theme, outlined mode', () => { - expect( - getButtonColors({ - theme: getTheme(true, false), - mode: 'outlined', - }) - ).toMatchObject({ - borderColor: color(white).alpha(0.29).rgb().string(), - }); - }); - - (['text', 'contained', 'contained-tonal', 'elevated'] as const).forEach( - (mode) => - it(`should return transparent border, for theme version 2, ${mode} mode`, () => { - expect( - getButtonColors({ - theme: getTheme(false, false), - mode, - }) - ).toMatchObject({ - borderColor: 'transparent', - }); - }) - ); - - (['text', 'contained', 'contained-tonal', 'elevated'] as const).forEach( - (mode) => - it(`should return transparent border, for theme version 2, dark theme, ${mode} mode`, () => { - expect( - getButtonColors({ - theme: getTheme(false, false), - mode, - }) - ).toMatchObject({ - borderColor: 'transparent', - }); - }) - ); }); describe('getButtonColors - border width', () => { @@ -877,17 +675,6 @@ describe('getButtonColors - border width', () => { }); }); - it('should return correct border width, for theme version 2, outlined mode', () => { - expect( - getButtonColors({ - theme: getTheme(false, false), - mode: 'outlined', - }) - ).toMatchObject({ - borderWidth: StyleSheet.hairlineWidth, - }); - }); - (['text', 'contained', 'contained-tonal', 'elevated'] as const).forEach( (mode) => it(`should return correct border width, for ${mode} mode`, () => { diff --git a/src/components/__tests__/Card/Card.test.tsx b/src/components/__tests__/Card/Card.test.tsx index 3da4aa2c51..a7dc736c62 100644 --- a/src/components/__tests__/Card/Card.test.tsx +++ b/src/components/__tests__/Card/Card.test.tsx @@ -2,10 +2,8 @@ import React from 'react'; import { Animated, StyleSheet, Text } from 'react-native'; import { act, render } from '@testing-library/react-native'; -import color from 'color'; import { getTheme } from '../../../core/theming'; -import { black, white } from '../../../styles/themes/v2/colors'; import { MD3Colors } from '../../../styles/themes/v3/tokens'; import Button from '../../Button/Button'; import Card from '../../Card/Card'; @@ -193,15 +191,6 @@ describe('getCardColors - background color', () => { }) ).toMatchObject({ backgroundColor: undefined }); }); - - it('should return undefined, for theme version 2', () => { - expect( - getCardColors({ - theme: getTheme(false, false), - mode: undefined as any, - }) - ).toMatchObject({ backgroundColor: undefined }); - }); }); describe('getCardColors - border color', () => { @@ -213,28 +202,6 @@ describe('getCardColors - border color', () => { }) ).toMatchObject({ borderColor: getTheme().colors.outline }); }); - - it('should return correct color, for theme version 2, dark mode', () => { - expect( - getCardColors({ - theme: getTheme(true, false), - mode: undefined as any, - }) - ).toMatchObject({ - borderColor: color(white).alpha(0.12).rgb().string(), - }); - }); - - it('should return correct color, for theme version 2, light mode', () => { - expect( - getCardColors({ - theme: getTheme(false, false), - mode: undefined as any, - }) - ).toMatchObject({ - borderColor: color(black).alpha(0.12).rgb().string(), - }); - }); }); describe('getCardCoverStyle - border radius', () => { @@ -255,44 +222,6 @@ describe('getCardCoverStyle - border radius', () => { }) ).toMatchObject({ borderRadius: 3 * getTheme().roundness }); }); - - it('should return correct border radius based on roundness, for theme version 2, when index is 0 and total is 1', () => { - expect( - getCardCoverStyle({ - theme: getTheme(false, false), - borderRadiusStyles: {}, - index: 0, - total: 1, - }) - ).toMatchObject({ borderRadius: getTheme(false, false).roundness }); - }); - - it('should return correct border radius based on roundness, for theme version 2, when index is 0 and total is other than 1', () => { - expect( - getCardCoverStyle({ - theme: getTheme(false, false), - borderRadiusStyles: {}, - index: 0, - total: 2, - }) - ).toMatchObject({ - borderTopLeftRadius: getTheme(false, false).roundness, - borderTopRightRadius: getTheme(false, false).roundness, - }); - }); - - it('should return correct border radius based on roundness, for theme version 2, when index is equal to total - 1', () => { - expect( - getCardCoverStyle({ - theme: getTheme(false, false), - borderRadiusStyles: {}, - index: 1, - total: 2, - }) - ).toMatchObject({ - borderBottomLeftRadius: getTheme(false, false).roundness, - }); - }); }); it('animated value changes correctly', () => { diff --git a/src/components/__tests__/Checkbox/__snapshots__/CheckboxItem.test.tsx.snap b/src/components/__tests__/Checkbox/__snapshots__/CheckboxItem.test.tsx.snap index b5f1d87e77..dbd992a134 100644 --- a/src/components/__tests__/Checkbox/__snapshots__/CheckboxItem.test.tsx.snap +++ b/src/components/__tests__/Checkbox/__snapshots__/CheckboxItem.test.tsx.snap @@ -163,7 +163,6 @@ exports[`can render leading checkbox control 1`] = ` "flexGrow": 1, "flexShrink": 1, }, - false, { "color": "rgba(28, 27, 31, 1)", "textAlign": "right", @@ -261,7 +260,6 @@ exports[`can render the Android checkbox on different platforms 1`] = ` "flexGrow": 1, "flexShrink": 1, }, - false, { "color": "rgba(28, 27, 31, 1)", "textAlign": "left", @@ -478,7 +476,6 @@ exports[`can render the iOS checkbox on different platforms 1`] = ` "flexGrow": 1, "flexShrink": 1, }, - false, { "color": "rgba(28, 27, 31, 1)", "textAlign": "left", @@ -659,7 +656,6 @@ exports[`renders unchecked 1`] = ` "flexGrow": 1, "flexShrink": 1, }, - false, { "color": "rgba(28, 27, 31, 1)", "textAlign": "left", diff --git a/src/components/__tests__/Checkbox/utils.test.tsx b/src/components/__tests__/Checkbox/utils.test.tsx index 580e3dbedf..3e551140c5 100644 --- a/src/components/__tests__/Checkbox/utils.test.tsx +++ b/src/components/__tests__/Checkbox/utils.test.tsx @@ -22,21 +22,6 @@ describe('getAndroidSelectionControlColor - ripple color', () => { }); }); - it('should return correct disabled color, for theme version 2', () => { - expect( - getAndroidSelectionControlColor({ - theme: getTheme(false, false), - disabled: true, - checked: false, - }) - ).toMatchObject({ - rippleColor: color(getTheme(false, false).colors.text) - .alpha(0.16) - .rgb() - .string(), - }); - }); - it('should return custom color', () => { expect( getAndroidSelectionControlColor({ @@ -59,20 +44,6 @@ describe('getAndroidSelectionControlColor - ripple color', () => { rippleColor: color(getTheme().colors.primary).fade(0.32).rgb().string(), }); }); - - it('should return theme color, for theme version 2', () => { - expect( - getAndroidSelectionControlColor({ - theme: getTheme(false, false), - checked: false, - }) - ).toMatchObject({ - rippleColor: color(getTheme(false, false).colors.accent) - .fade(0.32) - .rgb() - .string(), - }); - }); }); describe('getAndroidSelectionControlColor - checkbox color', () => { @@ -88,18 +59,6 @@ describe('getAndroidSelectionControlColor - checkbox color', () => { }); }); - it('should return correct disabled color, for theme version 2', () => { - expect( - getAndroidSelectionControlColor({ - theme: getTheme(false, false), - disabled: true, - checked: false, - }) - ).toMatchObject({ - selectionControlColor: getTheme(false, false).colors.disabled, - }); - }); - it('should return custom color, checked', () => { expect( getAndroidSelectionControlColor({ @@ -123,17 +82,6 @@ describe('getAndroidSelectionControlColor - checkbox color', () => { }); }); - it('should return theme color, for theme version 2, checked', () => { - expect( - getAndroidSelectionControlColor({ - theme: getTheme(false, false), - checked: true, - }) - ).toMatchObject({ - selectionControlColor: getTheme(false, false).colors.accent, - }); - }); - it('should return custom color, unchecked', () => { expect( getAndroidSelectionControlColor({ @@ -156,34 +104,6 @@ describe('getAndroidSelectionControlColor - checkbox color', () => { selectionControlColor: getTheme().colors.onSurfaceVariant, }); }); - - it('should return theme color, for theme version 2, unchecked, dark mode', () => { - expect( - getAndroidSelectionControlColor({ - theme: getTheme(true, false), - checked: false, - }) - ).toMatchObject({ - selectionControlColor: color(getTheme(true, false).colors.text) - .alpha(0.7) - .rgb() - .string(), - }); - }); - - it('should return theme color, for theme version 2, unchecked, light mode', () => { - expect( - getAndroidSelectionControlColor({ - theme: getTheme(false, false), - checked: false, - }) - ).toMatchObject({ - selectionControlColor: color(getTheme(false, false).colors.text) - .alpha(0.54) - .rgb() - .string(), - }); - }); }); describe('getSelectionControlIOSColor - ripple color', () => { @@ -201,20 +121,6 @@ describe('getSelectionControlIOSColor - ripple color', () => { }); }); - it('should return correct disabled color, for theme version 2', () => { - expect( - getSelectionControlIOSColor({ - theme: getTheme(false, false), - disabled: true, - }) - ).toMatchObject({ - rippleColor: color(getTheme(false, false).colors.text) - .alpha(0.16) - .rgb() - .string(), - }); - }); - it('should return custom color', () => { expect( getSelectionControlIOSColor({ @@ -235,19 +141,6 @@ describe('getSelectionControlIOSColor - ripple color', () => { rippleColor: color(getTheme().colors.primary).fade(0.32).rgb().string(), }); }); - - it('should return theme color, for theme version 2', () => { - expect( - getSelectionControlIOSColor({ - theme: getTheme(false, false), - }) - ).toMatchObject({ - rippleColor: color(getTheme(false, false).colors.accent) - .fade(0.32) - .rgb() - .string(), - }); - }); }); describe('getSelectionControlIOSColor - checked color', () => { @@ -262,17 +155,6 @@ describe('getSelectionControlIOSColor - checked color', () => { }); }); - it('should return correct disabled color, for theme version 2', () => { - expect( - getSelectionControlIOSColor({ - theme: getTheme(false, false), - disabled: true, - }) - ).toMatchObject({ - checkedColor: getTheme(false, false).colors.disabled, - }); - }); - it('should return custom color, checked', () => { expect( getSelectionControlIOSColor({ @@ -293,14 +175,4 @@ describe('getSelectionControlIOSColor - checked color', () => { checkedColor: getTheme().colors.primary, }); }); - - it('should return theme color, for theme version 2, checked', () => { - expect( - getSelectionControlIOSColor({ - theme: getTheme(false, false), - }) - ).toMatchObject({ - checkedColor: getTheme(false, false).colors.accent, - }); - }); }); diff --git a/src/components/__tests__/Chip.test.tsx b/src/components/__tests__/Chip.test.tsx index ca3055e35b..6c0e851f22 100644 --- a/src/components/__tests__/Chip.test.tsx +++ b/src/components/__tests__/Chip.test.tsx @@ -5,7 +5,6 @@ import { act, render } from '@testing-library/react-native'; import color from 'color'; import { getTheme } from '../../core/theming'; -import { black, white } from '../../styles/themes/v2/colors'; import Chip from '../Chip/Chip'; import { getChipColors } from '../Chip/helpers'; @@ -104,18 +103,6 @@ describe('getChipColors - text color', () => { }); }); - it('should return correct disabled color, for theme version 2', () => { - expect( - getChipColors({ - disabled: true, - theme: getTheme(false, false), - isOutlined: false, - }) - ).toMatchObject({ - textColor: getTheme(false, false).colors.disabled, - }); - }); - it('should return correct theme color, for theme version 3, flat mode', () => { expect( getChipColors({ @@ -138,20 +125,6 @@ describe('getChipColors - text color', () => { }); }); - it('should return correct theme color, for theme version 2', () => { - expect( - getChipColors({ - theme: getTheme(false, false), - isOutlined: false, - }) - ).toMatchObject({ - textColor: color(getTheme(false, false).colors.text) - .alpha(0.87) - .rgb() - .string(), - }); - }); - it('should return custom color, for theme version 3', () => { expect( getChipColors({ @@ -163,18 +136,6 @@ describe('getChipColors - text color', () => { textColor: 'purple', }); }); - - it('should return custom color, for theme version 2', () => { - expect( - getChipColors({ - theme: getTheme(false, false), - selectedColor: 'purple', - isOutlined: false, - }) - ).toMatchObject({ - textColor: color('purple').alpha(0.87).rgb().string(), - }); - }); }); describe('getChipColors - icon color', () => { @@ -190,18 +151,6 @@ describe('getChipColors - icon color', () => { }); }); - it('should return correct disabled color, for theme version 2', () => { - expect( - getChipColors({ - disabled: true, - theme: getTheme(false, false), - isOutlined: false, - }) - ).toMatchObject({ - iconColor: getTheme(false, false).colors.disabled, - }); - }); - it('should return correct theme color, for theme version 3, flat mode', () => { expect( getChipColors({ @@ -224,20 +173,6 @@ describe('getChipColors - icon color', () => { }); }); - it('should return correct theme color, for theme version 2', () => { - expect( - getChipColors({ - theme: getTheme(false, false), - isOutlined: false, - }) - ).toMatchObject({ - iconColor: color(getTheme(false, false).colors.text) - .alpha(0.54) - .rgb() - .string(), - }); - }); - it('should return custom color, for theme version 3', () => { expect( getChipColors({ @@ -249,18 +184,6 @@ describe('getChipColors - icon color', () => { iconColor: 'purple', }); }); - - it('should return custom color, for theme version 2', () => { - expect( - getChipColors({ - theme: getTheme(false, false), - selectedColor: 'purple', - isOutlined: false, - }) - ).toMatchObject({ - iconColor: color('purple').alpha(0.54).rgb().string(), - }); - }); }); describe('getChipColors - ripple color', () => { @@ -303,116 +226,6 @@ describe('getChipColors - ripple color', () => { rippleColor: color('purple').alpha(0.12).rgb().string(), }); }); - - it('should return custom color, for theme version 2', () => { - expect( - getChipColors({ - theme: getTheme(false, false), - selectedColor: 'purple', - isOutlined: false, - }) - ).toMatchObject({ - rippleColor: color('purple').fade(0.5).rgb().string(), - }); - }); - - it('should return custom color, for theme version 2, dark mode, outline mode, customBackgroundColor', () => { - expect( - getChipColors({ - theme: getTheme(true, false), - customBackgroundColor: 'purple', - isOutlined: true, - }) - ).toMatchObject({ - rippleColor: color('purple').lighten(0.2).rgb().string(), - }); - }); - - it('should return custom color, for theme version 2, dark mode, flat mode, customBackgroundColor', () => { - expect( - getChipColors({ - theme: getTheme(true, false), - customBackgroundColor: 'purple', - isOutlined: false, - }) - ).toMatchObject({ - rippleColor: color('purple').lighten(0.4).rgb().string(), - }); - }); - - it('should return custom color, for theme version 2, light mode, outline mode, customBackgroundColor', () => { - expect( - getChipColors({ - theme: getTheme(false, false), - customBackgroundColor: 'purple', - isOutlined: true, - }) - ).toMatchObject({ - rippleColor: color('purple').darken(0.08).rgb().string(), - }); - }); - - it('should return custom color, for theme version 2, light mode, flat mode, customBackgroundColor', () => { - expect( - getChipColors({ - theme: getTheme(false, false), - customBackgroundColor: 'purple', - isOutlined: false, - }) - ).toMatchObject({ - rippleColor: color('purple').darken(0.2).rgb().string(), - }); - }); - - it('should return theme color, for theme version 2, light mode, outline mode', () => { - expect( - getChipColors({ - theme: getTheme(false, false), - isOutlined: true, - }) - ).toMatchObject({ - rippleColor: color(getTheme(false, false).colors.surface) - .darken(0.08) - .rgb() - .string(), - }); - }); - - it('should return theme color, for theme version 2, light mode, flat mode', () => { - expect( - getChipColors({ - theme: getTheme(false, false), - isOutlined: false, - }) - ).toMatchObject({ - rippleColor: color('#ebebeb').darken(0.2).rgb().string(), - }); - }); - - it('should return theme color, for theme version 2, dark mode, outline mode', () => { - expect( - getChipColors({ - theme: getTheme(true, false), - isOutlined: true, - }) - ).toMatchObject({ - rippleColor: color(getTheme(true, false).colors.surface) - .lighten(0.2) - .rgb() - .string(), - }); - }); - - it('should return theme color, for theme version 2, dark mode, flat mode', () => { - expect( - getChipColors({ - theme: getTheme(true, false), - isOutlined: false, - }) - ).toMatchObject({ - rippleColor: color('#383838').lighten(0.4).rgb().string(), - }); - }); }); describe('getChipColor - selected background color', () => { @@ -505,90 +318,6 @@ describe('getChipColor - selected background color', () => { .string(), }); }); - - it('should return custom color, for theme version 2, light mode, outlined mode', () => { - expect( - getChipColors({ - theme: getTheme(false, false), - customBackgroundColor: 'purple', - isOutlined: true, - }) - ).toMatchObject({ - selectedBackgroundColor: color('purple').darken(0.08).rgb().string(), - }); - }); - - it('should return custom color, for theme version 2, light mode, flat mode', () => { - expect( - getChipColors({ - theme: getTheme(false, false), - customBackgroundColor: 'purple', - isOutlined: false, - }) - ).toMatchObject({ - selectedBackgroundColor: color('purple').darken(0.2).rgb().string(), - }); - }); - - it('should return custom color, for theme version 2, dark mode, outlined mode', () => { - expect( - getChipColors({ - theme: getTheme(true, false), - customBackgroundColor: 'purple', - isOutlined: true, - }) - ).toMatchObject({ - selectedBackgroundColor: color('purple').lighten(0.2).rgb().string(), - }); - }); - - it('should return custom color, for theme version 2, dark mode, flat mode', () => { - expect( - getChipColors({ - theme: getTheme(true, false), - customBackgroundColor: 'purple', - isOutlined: false, - }) - ).toMatchObject({ - selectedBackgroundColor: color('purple').lighten(0.4).rgb().string(), - }); - }); - - it('should return theme color, for theme version 2, outlined mode', () => { - expect( - getChipColors({ - theme: getTheme(false, false), - isOutlined: true, - }) - ).toMatchObject({ - selectedBackgroundColor: color(getTheme(false, false).colors.surface) - .darken(0.08) - .rgb() - .string(), - }); - }); - - it('should return theme color, for theme version 2, light mode, flat mode', () => { - expect( - getChipColors({ - theme: getTheme(false, false), - isOutlined: false, - }) - ).toMatchObject({ - selectedBackgroundColor: color('#ebebeb').darken(0.2).rgb().string(), - }); - }); - - it('should return theme color, for theme version 2, dark mode, flat mode', () => { - expect( - getChipColors({ - theme: getTheme(true, false), - isOutlined: false, - }) - ).toMatchObject({ - selectedBackgroundColor: color('#383838').lighten(0.4).rgb().string(), - }); - }); }); describe('getChipColor - background color', () => { @@ -625,39 +354,6 @@ describe('getChipColor - background color', () => { backgroundColor: getTheme().colors.secondaryContainer, }); }); - - it('should return theme color, for theme version 2, outlined mode', () => { - expect( - getChipColors({ - theme: getTheme(false, false), - isOutlined: true, - }) - ).toMatchObject({ - backgroundColor: getTheme(false, false).colors.surface, - }); - }); - - it('should return theme color, for theme version 2, light mode, flat mode', () => { - expect( - getChipColors({ - theme: getTheme(false, false), - isOutlined: false, - }) - ).toMatchObject({ - backgroundColor: '#ebebeb', - }); - }); - - it('should return theme color, for theme version 2, dark mode, flat mode', () => { - expect( - getChipColors({ - theme: getTheme(true, false), - isOutlined: false, - }) - ).toMatchObject({ - backgroundColor: '#383838', - }); - }); }); describe('getChipColor - border color', () => { @@ -695,74 +391,6 @@ describe('getChipColor - border color', () => { borderColor: 'transparent', }); }); - - it('should return custom color, for theme version 2, outlined mode', () => { - expect( - getChipColors({ - theme: getTheme(false, false), - selectedColor: 'purple', - isOutlined: true, - }) - ).toMatchObject({ - borderColor: color('purple').alpha(0.29).rgb().string(), - }); - }); - - it('should return custom color, for theme version 2, flat mode', () => { - expect( - getChipColors({ - theme: getTheme(true, false), - customBackgroundColor: 'purple', - isOutlined: false, - }) - ).toMatchObject({ - borderColor: 'purple', - }); - }); - - it('should return theme color, for theme version 2, light mode, outlined mode', () => { - expect( - getChipColors({ - theme: getTheme(false, false), - isOutlined: true, - }) - ).toMatchObject({ - borderColor: color(black).alpha(0.29).rgb().string(), - }); - }); - - it('should return theme color, for theme version 2, dark mode, outlined mode', () => { - expect( - getChipColors({ - theme: getTheme(true, false), - isOutlined: true, - }) - ).toMatchObject({ - borderColor: color(white).alpha(0.29).rgb().string(), - }); - }); - - it('should return theme background color, for theme version 2, light mode, flat mode', () => { - expect( - getChipColors({ - theme: getTheme(false, false), - isOutlined: false, - }) - ).toMatchObject({ - borderColor: '#ebebeb', - }); - }); - - it('should return theme background color, for theme version 2, dark mode, flat mode', () => { - expect( - getChipColors({ - theme: getTheme(true, false), - isOutlined: false, - }) - ).toMatchObject({ - borderColor: '#383838', - }); - }); }); it('animated value changes correctly', () => { diff --git a/src/components/__tests__/FAB.test.tsx b/src/components/__tests__/FAB.test.tsx index d59639efc1..74f636cf5c 100644 --- a/src/components/__tests__/FAB.test.tsx +++ b/src/components/__tests__/FAB.test.tsx @@ -2,12 +2,9 @@ import * as React from 'react'; import { Animated, StyleSheet } from 'react-native'; import { fireEvent, render } from '@testing-library/react-native'; -import color from 'color'; import { act } from 'react-test-renderer'; import { getTheme } from '../../core/theming'; -import { black, white } from '../../styles/themes/v2/colors'; -import getContrastingColor from '../../utils/getContrastingColor'; import FAB from '../FAB'; import { getFABColors } from '../FAB/utils'; @@ -211,30 +208,6 @@ describe('getFABColors - background color', () => { }); }); - it('should return correct disabled color, for theme version 2, light mode', () => { - expect( - getFABColors({ - theme: getTheme(false, false), - disabled: true, - variant: 'primary', - }) - ).toMatchObject({ - backgroundColor: color(black).alpha(0.12).rgb().string(), - }); - }); - - it('should return correct disabled color, for theme version 2, dark mode', () => { - expect( - getFABColors({ - theme: getTheme(true, false), - disabled: true, - variant: 'primary', - }) - ).toMatchObject({ - backgroundColor: color(white).alpha(0.12).rgb().string(), - }); - }); - it('should return correct theme color, for theme version 3, primary variant', () => { expect( getFABColors({ @@ -278,17 +251,6 @@ describe('getFABColors - background color', () => { backgroundColor: getTheme().colors.elevation.level3, }); }); - - it('should return correct theme color, for theme version 2', () => { - expect( - getFABColors({ - theme: getTheme(false, false), - variant: 'primary', - }) - ).toMatchObject({ - backgroundColor: getTheme(false, false).colors.accent, - }); - }); }); describe('getFABColors - foreground color', () => { @@ -316,30 +278,6 @@ describe('getFABColors - foreground color', () => { }); }); - it('should return correct disabled color, for theme version 2, light mode', () => { - expect( - getFABColors({ - theme: getTheme(false, false), - disabled: true, - variant: 'primary', - }) - ).toMatchObject({ - foregroundColor: color(black).alpha(0.32).rgb().string(), - }); - }); - - it('should return correct disabled color, for theme version 2, dark mode', () => { - expect( - getFABColors({ - theme: getTheme(true, false), - disabled: true, - variant: 'primary', - }) - ).toMatchObject({ - foregroundColor: color(white).alpha(0.32).rgb().string(), - }); - }); - it('should return correct theme color, for theme version 3, primary variant', () => { expect( getFABColors({ @@ -383,21 +321,6 @@ describe('getFABColors - foreground color', () => { foregroundColor: getTheme().colors.primary, }); }); - - it('should return correct theme color, for theme version 2', () => { - expect( - getFABColors({ - theme: getTheme(false, false), - variant: 'primary', - }) - ).toMatchObject({ - foregroundColor: getContrastingColor( - getTheme(false, false).colors.accent, - white, - 'rgba(0, 0, 0, .54)' - ), - }); - }); }); it('animated value changes correctly', () => { diff --git a/src/components/__tests__/FABGroup.test.tsx b/src/components/__tests__/FABGroup.test.tsx index 50cc0a7173..3eb51c78d6 100644 --- a/src/components/__tests__/FABGroup.test.tsx +++ b/src/components/__tests__/FABGroup.test.tsx @@ -32,16 +32,6 @@ describe('getFABGroupColors - backdrop color', () => { .string(), }); }); - - it('should return correct backdrop color, for theme version 2', () => { - expect( - getFABGroupColors({ - theme: getTheme(false, false), - }) - ).toMatchObject({ - backdropColor: getTheme(false, false).colors.backdrop, - }); - }); }); describe('getFABGroupColors - label color', () => { @@ -54,29 +44,6 @@ describe('getFABGroupColors - label color', () => { labelColor: getTheme().colors.onSurface, }); }); - - it('should return correct theme color, dark mode, for theme version 2', () => { - expect( - getFABGroupColors({ - theme: getTheme(true, false), - }) - ).toMatchObject({ - labelColor: getTheme(true, false).colors.text, - }); - }); - - it('should return correct theme color, light mode, for theme version 2', () => { - expect( - getFABGroupColors({ - theme: getTheme(false, false), - }) - ).toMatchObject({ - labelColor: color(getTheme(false, false).colors.text) - .fade(0.54) - .rgb() - .string(), - }); - }); }); describe('getFABGroupColors - stacked FAB background color', () => { @@ -89,16 +56,6 @@ describe('getFABGroupColors - stacked FAB background color', () => { stackedFABBackgroundColor: getTheme().colors.elevation.level3, }); }); - - it('should return correct theme color, dark mode, for theme version 2', () => { - expect( - getFABGroupColors({ - theme: getTheme(false, false), - }) - ).toMatchObject({ - stackedFABBackgroundColor: getTheme(false, false).colors.surface, - }); - }); }); describe('FABActions - labelStyle - containerStyle', () => { diff --git a/src/components/__tests__/IconButton.test.tsx b/src/components/__tests__/IconButton.test.tsx index 381ea5ae24..11f47cb49c 100644 --- a/src/components/__tests__/IconButton.test.tsx +++ b/src/components/__tests__/IconButton.test.tsx @@ -190,16 +190,6 @@ describe('getIconButtonColor - icon color', () => { iconColor: getTheme().colors.primary, }); }); - - it('should return theme icon color, for theme version 2', () => { - expect( - getIconButtonColor({ - theme: getTheme(false, false), - }) - ).toMatchObject({ - iconColor: getTheme(false, false).colors.text, - }); - }); }); describe('getIconButtonColor - background color', () => { @@ -316,16 +306,6 @@ describe('getIconButtonColor - border color', () => { borderColor: getTheme().colors.outline, }); }); - - it('should return undefined, for theme version 2', () => { - expect( - getIconButtonColor({ - theme: getTheme(false, false), - }) - ).toMatchObject({ - borderColor: undefined, - }); - }); }); describe('getIconButtonColor - ripple color', () => { @@ -341,19 +321,6 @@ describe('getIconButtonColor - ripple color', () => { .string(), }); }); - - it('should return theme color, for theme version 2', () => { - expect( - getIconButtonColor({ - theme: getTheme(false, false), - }) - ).toMatchObject({ - rippleColor: color(getTheme(false, false).colors.text) - .alpha(0.32) - .rgb() - .string(), - }); - }); }); it('action animated value changes correctly', () => { diff --git a/src/components/__tests__/ListAccordion.test.tsx b/src/components/__tests__/ListAccordion.test.tsx index 0c24538348..9695b3c186 100644 --- a/src/components/__tests__/ListAccordion.test.tsx +++ b/src/components/__tests__/ListAccordion.test.tsx @@ -115,31 +115,6 @@ describe('ListAccordion', () => { }); }); -describe('getAccordionColors - title color', () => { - it('should return theme color, for theme version 3', () => { - expect( - getAccordionColors({ - theme: getTheme(), - }) - ).toMatchObject({ - titleColor: getTheme().colors.onSurface, - }); - }); - - it('should return theme color, for theme version 2', () => { - expect( - getAccordionColors({ - theme: getTheme(false, false), - }) - ).toMatchObject({ - titleColor: color(getTheme(false, false).colors.text) - .alpha(0.87) - .rgb() - .string(), - }); - }); -}); - describe('getAccordionColors - description color', () => { it('should return theme color, for theme version 3', () => { expect( @@ -150,19 +125,6 @@ describe('getAccordionColors - description color', () => { descriptionColor: getTheme().colors.onSurfaceVariant, }); }); - - it('should return theme color, for theme version 2', () => { - expect( - getAccordionColors({ - theme: getTheme(false, false), - }) - ).toMatchObject({ - descriptionColor: color(getTheme(false, false).colors.text) - .alpha(0.54) - .rgb() - .string(), - }); - }); }); describe('getAccordionColors - title text color', () => { @@ -176,19 +138,6 @@ describe('getAccordionColors - title text color', () => { }); }); - it('should return theme color, for theme version 2', () => { - expect( - getAccordionColors({ - theme: getTheme(false, false), - }) - ).toMatchObject({ - titleTextColor: color(getTheme(false, false).colors.text) - .alpha(0.87) - .rgb() - .string(), - }); - }); - it('should return primary color if it is expanded', () => { expect( getAccordionColors({ @@ -215,21 +164,6 @@ describe('getAccordionColors - ripple color', () => { }); }); - it('should return theme color, for theme version 2', () => { - const v2TextColor = color(getTheme(false, false).colors.text) - .alpha(0.87) - .rgb() - .string(); - - expect( - getAccordionColors({ - theme: getTheme(false, false), - }) - ).toMatchObject({ - rippleColor: color(v2TextColor).alpha(0.12).rgb().string(), - }); - }); - it('should return primary color if it is expanded', () => { expect( getAccordionColors({ diff --git a/src/components/__tests__/ListUtils.test.tsx b/src/components/__tests__/ListUtils.test.tsx index 4aeefb6ca9..a9889834d8 100644 --- a/src/components/__tests__/ListUtils.test.tsx +++ b/src/components/__tests__/ListUtils.test.tsx @@ -5,18 +5,11 @@ import { getLeftStyles, getRightStyles } from '../List/utils'; import Text from '../Typography/Text'; const styles = StyleSheet.create({ - leftItem: { - marginLeft: 0, - marginRight: 16, - }, leftItemV3: { marginLeft: 16, marginRight: 0, alignSelf: 'center', }, - rightItem: { - marginRight: 0, - }, rightItemV3: { marginLeft: 16, marginRight: 0, @@ -30,23 +23,13 @@ const description = Test; * ********************** getLeftStyles ********************** * */ -it('returns styles for left item without description for V2', () => { - const style = getLeftStyles(false, null, false); - expect(style).toStrictEqual({ ...styles.leftItem, marginVertical: 0 }); -}); - -it('returns styles for left item w/ desctiption for V2', () => { - const style = getLeftStyles(false, description, false); - expect(style).toStrictEqual(styles.leftItem); -}); - -it('returns styles for left item without description for V3', () => { - const style = getLeftStyles(false, null, true); +it('returns styles for left item without description', () => { + const style = getLeftStyles(false, null); expect(style).toStrictEqual({ ...styles.leftItemV3, marginVertical: 0 }); }); -it('returns styles for left item w/ desctiption for V3', () => { - const style = getLeftStyles(true, description, true); +it('returns styles for left item w/ desctiption', () => { + const style = getLeftStyles(true, description); expect(style).toStrictEqual({ ...styles.leftItemV3, alignSelf: 'flex-start', @@ -57,23 +40,13 @@ it('returns styles for left item w/ desctiption for V3', () => { * ********************** getRightStyles ********************** * */ -it('returns styles for right item without description for V2', () => { - const style = getRightStyles(false, null, false); - expect(style).toStrictEqual({ ...styles.rightItem, marginVertical: 0 }); -}); - -it('returns styles for right item w/ desctiption for V2', () => { - const style = getRightStyles(false, description, false); - expect(style).toStrictEqual(styles.rightItem); -}); - -it('returns styles for right item without description for V3', () => { - const style = getRightStyles(false, null, true); +it('returns styles for right item without description', () => { + const style = getRightStyles(false, null); expect(style).toStrictEqual({ ...styles.rightItemV3, marginVertical: 0 }); }); -it('returns styles for right item w/ desctiption for V3', () => { - const style = getRightStyles(true, description, true); +it('returns styles for right item w/ desctiption', () => { + const style = getRightStyles(true, description); expect(style).toStrictEqual({ ...styles.rightItemV3, alignSelf: 'flex-start', diff --git a/src/components/__tests__/Menu.test.tsx b/src/components/__tests__/Menu.test.tsx index 29397d1262..21ed4d0802 100644 --- a/src/components/__tests__/Menu.test.tsx +++ b/src/components/__tests__/Menu.test.tsx @@ -70,7 +70,7 @@ it('renders menu with content styles', () => { ([0, 1, 2, 3, 4, 5] as MD3Elevation[]).forEach((elevation) => it(`renders menu with background color based on elevation value = ${elevation}`, () => { - const theme = getTheme(false, true); + const theme = getTheme(); const { getByTestId } = render( diff --git a/src/components/__tests__/MenuItem.test.tsx b/src/components/__tests__/MenuItem.test.tsx index 7413f43622..d482800582 100644 --- a/src/components/__tests__/MenuItem.test.tsx +++ b/src/components/__tests__/MenuItem.test.tsx @@ -4,7 +4,6 @@ import { render } from '@testing-library/react-native'; import color from 'color'; import { getTheme } from '../../core/theming'; -import { black, white } from '../../styles/themes/v2/colors'; import Menu from '../Menu/Menu'; import { getMenuItemColor } from '../Menu/utils'; @@ -75,28 +74,6 @@ describe('getMenuItemColor - title color', () => { ).toMatchObject({ titleColor: getTheme().colors.onSurfaceDisabled }); }); - it('should return disabled color if disabled, for theme version 2, light theme', () => { - expect( - getMenuItemColor({ - theme: getTheme(false, false), - disabled: true, - }) - ).toMatchObject({ - titleColor: color(black).alpha(0.32).rgb().string(), - }); - }); - - it('should return disabled color if disabled, for theme version 2, dark theme', () => { - expect( - getMenuItemColor({ - theme: getTheme(true, false), - disabled: true, - }) - ).toMatchObject({ - titleColor: color(white).alpha(0.32).rgb().string(), - }); - }); - it('should return correct theme color, for theme version 3', () => { expect( getMenuItemColor({ @@ -106,19 +83,6 @@ describe('getMenuItemColor - title color', () => { titleColor: getTheme().colors.onSurface, }); }); - - it('should return correct theme color, for theme version 2', () => { - expect( - getMenuItemColor({ - theme: getTheme(false, false), - }) - ).toMatchObject({ - titleColor: color(getTheme(false, false).colors.text) - .alpha(0.87) - .rgb() - .string(), - }); - }); }); describe('getMenuItemColor - icon color', () => { @@ -131,28 +95,6 @@ describe('getMenuItemColor - icon color', () => { ).toMatchObject({ iconColor: getTheme().colors.onSurfaceDisabled }); }); - it('should return disabled color if disabled, for theme version 2, light theme', () => { - expect( - getMenuItemColor({ - theme: getTheme(false, false), - disabled: true, - }) - ).toMatchObject({ - iconColor: color(black).alpha(0.32).rgb().string(), - }); - }); - - it('should return disabled color if disabled, for theme version 2, dark theme', () => { - expect( - getMenuItemColor({ - theme: getTheme(true, false), - disabled: true, - }) - ).toMatchObject({ - iconColor: color(white).alpha(0.32).rgb().string(), - }); - }); - it('should return correct theme color, for theme version 3', () => { expect( getMenuItemColor({ @@ -162,19 +104,6 @@ describe('getMenuItemColor - icon color', () => { iconColor: getTheme().colors.onSurfaceVariant, }); }); - - it('should return correct theme color, for theme version 2', () => { - expect( - getMenuItemColor({ - theme: getTheme(false, false), - }) - ).toMatchObject({ - iconColor: color(getTheme(false, false).colors.text) - .alpha(0.54) - .rgb() - .string(), - }); - }); }); describe('getMenuItemColor - ripple color', () => { @@ -190,14 +119,4 @@ describe('getMenuItemColor - ripple color', () => { .string(), }); }); - - it('should return undefined, for theme version 2', () => { - expect( - getMenuItemColor({ - theme: getTheme(false, false), - }) - ).toMatchObject({ - rippleColor: undefined, - }); - }); }); diff --git a/src/components/__tests__/RadioButton/__snapshots__/RadioButtonItem.test.tsx.snap b/src/components/__tests__/RadioButton/__snapshots__/RadioButtonItem.test.tsx.snap index dfbe5fa131..e74650efd2 100644 --- a/src/components/__tests__/RadioButton/__snapshots__/RadioButtonItem.test.tsx.snap +++ b/src/components/__tests__/RadioButton/__snapshots__/RadioButtonItem.test.tsx.snap @@ -161,7 +161,6 @@ exports[`can render leading radio button control 1`] = ` "flexGrow": 1, "flexShrink": 1, }, - false, { "color": "rgba(28, 27, 31, 1)", "textAlign": "right", @@ -256,7 +255,6 @@ exports[`can render the Android radio button on different platforms 1`] = ` "flexGrow": 1, "flexShrink": 1, }, - false, { "color": "rgba(28, 27, 31, 1)", "textAlign": "left", @@ -408,7 +406,6 @@ exports[`can render the iOS radio button on different platforms 1`] = ` "flexGrow": 1, "flexShrink": 1, }, - false, { "color": "rgba(28, 27, 31, 1)", "textAlign": "left", @@ -586,7 +583,6 @@ exports[`renders unchecked 1`] = ` "flexGrow": 1, "flexShrink": 1, }, - false, { "color": "rgba(28, 27, 31, 1)", "textAlign": "left", diff --git a/src/components/__tests__/SegmentedButton.test.tsx b/src/components/__tests__/SegmentedButton.test.tsx index d36babb5bb..e65f9015f7 100644 --- a/src/components/__tests__/SegmentedButton.test.tsx +++ b/src/components/__tests__/SegmentedButton.test.tsx @@ -1,10 +1,8 @@ import * as React from 'react'; import { render } from '@testing-library/react-native'; -import color from 'color'; import { getTheme } from '../../core/theming'; -import { black } from '../../styles/themes/v2/colors'; import SegmentedButtons from '../SegmentedButtons/SegmentedButtons'; import { getDisabledSegmentedButtonStyle, @@ -56,22 +54,16 @@ it('renders checked segmented button with selected check', async () => { describe('getSegmentedButtonColors', () => { it.each` - theme | disabled | checked | checkedColor | uncheckedColor | expected - ${getTheme()} | ${false} | ${true} | ${undefined} | ${undefined} | ${getTheme().colors.onSecondaryContainer} - ${getTheme()} | ${false} | ${false} | ${undefined} | ${undefined} | ${getTheme().colors.onSurface} - ${getTheme()} | ${true} | ${true} | ${undefined} | ${undefined} | ${getTheme().colors.onSurfaceDisabled} - ${getTheme()} | ${true} | ${false} | ${undefined} | ${undefined} | ${getTheme().colors.onSurfaceDisabled} - ${getTheme()} | ${false} | ${true} | ${'a125f5'} | ${undefined} | ${'a125f5'} - ${getTheme()} | ${false} | ${false} | ${undefined} | ${'000'} | ${'000'} - ${getTheme()} | ${false} | ${false} | ${'a125f5'} | ${'000'} | ${'000'} - ${getTheme()} | ${false} | ${false} | ${'a125f5'} | ${undefined} | ${getTheme().colors.onSurface} - ${getTheme()} | ${false} | ${true} | ${undefined} | ${'000'} | ${getTheme().colors.onSecondaryContainer} - ${getTheme(false, false)} | ${false} | ${false} | ${undefined} | ${undefined} | ${getTheme(false, false).colors.primary} - ${getTheme(false, false)} | ${false} | ${true} | ${undefined} | ${undefined} | ${getTheme(false, false).colors.primary} - ${getTheme(false, false)} | ${true} | ${false} | ${undefined} | ${undefined} | ${getTheme(false, false).colors.disabled} - ${getTheme(false, false)} | ${true} | ${true} | ${undefined} | ${undefined} | ${getTheme(false, false).colors.disabled} - ${getTheme(false, false)} | ${false} | ${false} | ${'a125f5'} | ${undefined} | ${getTheme(false, false).colors.primary} - ${getTheme(false, false)} | ${false} | ${true} | ${undefined} | ${'000'} | ${getTheme(false, false).colors.primary} + theme | disabled | checked | checkedColor | uncheckedColor | expected + ${getTheme()} | ${false} | ${true} | ${undefined} | ${undefined} | ${getTheme().colors.onSecondaryContainer} + ${getTheme()} | ${false} | ${false} | ${undefined} | ${undefined} | ${getTheme().colors.onSurface} + ${getTheme()} | ${true} | ${true} | ${undefined} | ${undefined} | ${getTheme().colors.onSurfaceDisabled} + ${getTheme()} | ${true} | ${false} | ${undefined} | ${undefined} | ${getTheme().colors.onSurfaceDisabled} + ${getTheme()} | ${false} | ${true} | ${'a125f5'} | ${undefined} | ${'a125f5'} + ${getTheme()} | ${false} | ${false} | ${undefined} | ${'000'} | ${'000'} + ${getTheme()} | ${false} | ${false} | ${'a125f5'} | ${'000'} | ${'000'} + ${getTheme()} | ${false} | ${false} | ${'a125f5'} | ${undefined} | ${getTheme().colors.onSurface} + ${getTheme()} | ${false} | ${true} | ${undefined} | ${'000'} | ${getTheme().colors.onSecondaryContainer} `( 'returns $expected when disabled: $disabled, checked: $checked, checkedColor is $checkedColor and uncheckedColor is $uncheckedColor and isV3: $theme.isV3', ({ theme, disabled, checked, checkedColor, uncheckedColor, expected }) => { @@ -97,25 +89,10 @@ describe('getSegmentedButtonColors', () => { ).toMatchObject({ backgroundColor: getTheme().colors.secondaryContainer }); }); - it('should return correct background color when checked and theme version 2', () => { - expect( - getSegmentedButtonColors({ - theme: getTheme(false, false), - disabled: false, - checked: true, - }) - ).toMatchObject({ - backgroundColor: color(getTheme(false, false).colors.primary) - .alpha(0.12) - .rgb() - .string(), - }); - }); - it('should return correct background color when uncheked (V3 & V2)', () => { expect( getSegmentedButtonColors({ - theme: getTheme(false, false), + theme: getTheme(), disabled: false, checked: false, }) @@ -136,18 +113,6 @@ describe('getSegmentedButtonColors', () => { }); }); - it('should return correct border color with theme version 2', () => { - expect( - getSegmentedButtonColors({ - theme: getTheme(false, false), - disabled: false, - checked: false, - }) - ).toMatchObject({ - borderColor: color(black).alpha(0.29).rgb().string(), - }); - }); - it('should return correct border color when disabled and theme version 3', () => { expect( getSegmentedButtonColors({ @@ -172,18 +137,6 @@ describe('getSegmentedButtonColors', () => { }); }); - it('should return correct textColor with theme version 2', () => { - expect( - getSegmentedButtonColors({ - theme: getTheme(false, false), - disabled: false, - checked: false, - }) - ).toMatchObject({ - textColor: getTheme(false, false).colors.primary, - }); - }); - it('should return correct textColor when disabled and theme version 3', () => { expect( getSegmentedButtonColors({ @@ -195,18 +148,6 @@ describe('getSegmentedButtonColors', () => { textColor: getTheme().colors.onSurfaceDisabled, }); }); - - it('should return correct textColor when disabled and theme version 2', () => { - expect( - getSegmentedButtonColors({ - theme: getTheme(false, false), - disabled: true, - checked: false, - }) - ).toMatchObject({ - textColor: getTheme(false, false).colors.disabled, - }); - }); }); describe('getDisabledSegmentedButtonBorderWidth', () => { diff --git a/src/components/__tests__/Switch.test.tsx b/src/components/__tests__/Switch.test.tsx index e475b9a166..dfaa028b43 100644 --- a/src/components/__tests__/Switch.test.tsx +++ b/src/components/__tests__/Switch.test.tsx @@ -62,16 +62,6 @@ describe('getSwitchColor - checked color', () => { checkedColor: getTheme().colors.primary, }); }); - - it('should return theme color, for theme version 2', () => { - expect( - getSwitchColor({ - theme: getTheme(false, false), - }) - ).toMatchObject({ - checkedColor: getTheme(false, false).colors.accent, - }); - }); }); describe('getSwitchColor - thumb tint color', () => { @@ -163,24 +153,12 @@ describe('getSwitchColor - on tint color', () => { }); }); - it('should return checked color for iOS platform, for theme version 2', () => { - Platform.OS = 'ios'; - - expect( - getSwitchColor({ - theme: getTheme(false, false), - }) - ).toMatchObject({ - onTintColor: getTheme(false, false).colors.accent, - }); - }); - it('should return custom color for iOS platform', () => { Platform.OS = 'ios'; expect( getSwitchColor({ - theme: getTheme(false, false), + theme: getTheme(), color: 'purple', }) ).toMatchObject({ @@ -201,17 +179,6 @@ describe('getSwitchColor - on tint color', () => { }); }); - it('should return correct disabled color, for theme version 2, dark mode', () => { - expect( - getSwitchColor({ - theme: getTheme(true, false), - disabled: true, - }) - ).toMatchObject({ - onTintColor: color(white).alpha(0.1).rgb().string(), - }); - }); - it('should return correct disabled color, light mode', () => { expect( getSwitchColor({ diff --git a/src/components/__tests__/TextInput.test.tsx b/src/components/__tests__/TextInput.test.tsx index e190a537d6..c92ed138c4 100644 --- a/src/components/__tests__/TextInput.test.tsx +++ b/src/components/__tests__/TextInput.test.tsx @@ -551,17 +551,6 @@ describe('getFlatInputColor - underline color', () => { }); }); - it('should return correct disabled color, for theme version 2', () => { - expect( - getFlatInputColors({ - disabled: true, - theme: getTheme(false, false), - }) - ).toMatchObject({ - underlineColorCustom: 'transparent', - }); - }); - it('should return correct theme color, for theme version 3', () => { expect( getFlatInputColors({ @@ -572,16 +561,6 @@ describe('getFlatInputColor - underline color', () => { }); }); - it('should return correct theme color, for theme version 2', () => { - expect( - getFlatInputColors({ - theme: getTheme(false, false), - }) - ).toMatchObject({ - underlineColorCustom: getTheme(false, false).colors.disabled, - }); - }); - it('should return custom color, no matter what the theme is', () => { expect( getFlatInputColors({ @@ -595,7 +574,7 @@ describe('getFlatInputColor - underline color', () => { expect( getFlatInputColors({ underlineColor: 'beige', - theme: getTheme(false, false), + theme: getTheme(), }) ).toMatchObject({ underlineColorCustom: 'beige', @@ -617,7 +596,7 @@ describe('getFlatInputColor - input text color', () => { expect( getOutlinedInputColors({ textColor: 'beige', - theme: getTheme(false, false), + theme: getTheme(), }) ).toMatchObject({ inputTextColor: 'beige', @@ -635,20 +614,6 @@ describe('getFlatInputColor - input text color', () => { }); }); - it('should return correct disabled color, for theme version 2', () => { - expect( - getFlatInputColors({ - disabled: true, - theme: getTheme(false, false), - }) - ).toMatchObject({ - inputTextColor: color(getTheme(false, false).colors?.text) - .alpha(0.54) - .rgb() - .string(), - }); - }); - it('should return correct theme color, for theme version 3', () => { expect( getFlatInputColors({ @@ -658,16 +623,6 @@ describe('getFlatInputColor - input text color', () => { inputTextColor: getTheme().colors.onSurface, }); }); - - it('should return correct theme color, for theme version 2', () => { - expect( - getFlatInputColors({ - theme: getTheme(false, false), - }) - ).toMatchObject({ - inputTextColor: getTheme(false, false).colors.text, - }); - }); }); describe('getFlatInputColor - placeholder color', () => { @@ -682,17 +637,6 @@ describe('getFlatInputColor - placeholder color', () => { }); }); - it('should return correct disabled color, for theme version 2', () => { - expect( - getFlatInputColors({ - disabled: true, - theme: getTheme(false, false), - }) - ).toMatchObject({ - placeholderColor: getTheme(false, false).colors.disabled, - }); - }); - it('should return correct theme color, for theme version 3', () => { expect( getFlatInputColors({ @@ -702,16 +646,6 @@ describe('getFlatInputColor - placeholder color', () => { placeholderColor: getTheme().colors.onSurfaceVariant, }); }); - - it('should return correct theme color, for theme version 2', () => { - expect( - getFlatInputColors({ - theme: getTheme(false, false), - }) - ).toMatchObject({ - placeholderColor: getTheme(false, false).colors.placeholder, - }); - }); }); describe('getFlatInputColor - background color', () => { @@ -740,17 +674,6 @@ describe('getFlatInputColor - background color', () => { }); }); - it('should return undefined when disabled, for theme version 2', () => { - expect( - getFlatInputColors({ - disabled: true, - theme: getTheme(false, false), - }) - ).toMatchObject({ - backgroundColor: undefined, - }); - }); - it('should return correct theme color, for theme version 3', () => { expect( getFlatInputColors({ @@ -760,32 +683,6 @@ describe('getFlatInputColor - background color', () => { backgroundColor: getTheme().colors.surfaceVariant, }); }); - - it('should return correct theme color, for theme version 2, light mode', () => { - expect( - getFlatInputColors({ - theme: getTheme(false, false), - }) - ).toMatchObject({ - backgroundColor: color(getTheme(false, false).colors?.background) - .darken(0.06) - .rgb() - .string(), - }); - }); - - it('should return correct theme color, for theme version 2, dark mode', () => { - expect( - getFlatInputColors({ - theme: getTheme(true, false), - }) - ).toMatchObject({ - backgroundColor: color(getTheme(true, false).colors?.background) - .lighten(0.24) - .rgb() - .string(), - }); - }); }); describe('getFlatInputColor - error color', () => { @@ -802,10 +699,10 @@ describe('getFlatInputColor - error color', () => { expect( getFlatInputColors({ error: true, - theme: getTheme(false, true), + theme: getTheme(), }) ).toMatchObject({ - errorColor: getTheme(false, true).colors.error, + errorColor: getTheme().colors.error, }); }); }); @@ -822,20 +719,6 @@ describe('getFlatInputColor - active color', () => { }); }); - it('should return disabled color, for theme version 2', () => { - expect( - getFlatInputColors({ - disabled: true, - theme: getTheme(false, false), - }) - ).toMatchObject({ - activeColor: color(getTheme(false, false).colors?.text) - .alpha(0.54) - .rgb() - .string(), - }); - }); - it('should return correct active color, if error, no matter what the theme is', () => { expect( getFlatInputColors({ @@ -849,10 +732,10 @@ describe('getFlatInputColor - active color', () => { expect( getFlatInputColors({ error: true, - theme: getTheme(false, true), + theme: getTheme(), }) ).toMatchObject({ - activeColor: getTheme(false, true).colors.error, + activeColor: getTheme().colors.error, }); }); @@ -869,7 +752,7 @@ describe('getFlatInputColor - active color', () => { expect( getFlatInputColors({ activeUnderlineColor: 'beige', - theme: getTheme(false, false), + theme: getTheme(), }) ).toMatchObject({ activeColor: 'beige', @@ -885,16 +768,6 @@ describe('getFlatInputColor - active color', () => { activeColor: getTheme().colors.primary, }); }); - - it('should return theme active color, for theme version 2', () => { - expect( - getFlatInputColors({ - theme: getTheme(false, true), - }) - ).toMatchObject({ - activeColor: getTheme(false, true).colors.primary, - }); - }); }); describe('getOutlinedInputColors - outline color', () => { @@ -920,29 +793,6 @@ describe('getOutlinedInputColors - outline color', () => { }); }); - it('should return correct disabled color, for theme version 2', () => { - expect( - getOutlinedInputColors({ - disabled: true, - theme: getTheme(false, false), - }) - ).toMatchObject({ - outlineColor: getTheme(false, false).colors.disabled, - }); - }); - - it('should return custom color as disabled, when it is transparent, for theme version 2', () => { - expect( - getOutlinedInputColors({ - disabled: true, - customOutlineColor: 'transparent', - theme: getTheme(false, false), - }) - ).toMatchObject({ - outlineColor: 'transparent', - }); - }); - it('should return custom color, if not disabled, no matter what the theme is', () => { expect( getOutlinedInputColors({ @@ -956,7 +806,7 @@ describe('getOutlinedInputColors - outline color', () => { expect( getOutlinedInputColors({ customOutlineColor: 'beige', - theme: getTheme(false, false), + theme: getTheme(), }) ).toMatchObject({ outlineColor: 'beige', @@ -972,16 +822,6 @@ describe('getOutlinedInputColors - outline color', () => { outlineColor: getTheme().colors.outline, }); }); - - it('should return theme color, for theme version 2', () => { - expect( - getOutlinedInputColors({ - theme: getTheme(false, false), - }) - ).toMatchObject({ - outlineColor: getTheme(false, false).colors.placeholder, - }); - }); }); describe('getOutlinedInputColors - input text color', () => { @@ -996,20 +836,6 @@ describe('getOutlinedInputColors - input text color', () => { }); }); - it('should return correct disabled color, for theme version 2', () => { - expect( - getOutlinedInputColors({ - disabled: true, - theme: getTheme(false, false), - }) - ).toMatchObject({ - inputTextColor: color(getTheme(false, false).colors?.text) - .alpha(0.54) - .rgb() - .string(), - }); - }); - it('should return correct theme color, for theme version 3', () => { expect( getOutlinedInputColors({ @@ -1019,16 +845,6 @@ describe('getOutlinedInputColors - input text color', () => { inputTextColor: getTheme().colors.onSurface, }); }); - - it('should return correct theme color, for theme version 2', () => { - expect( - getOutlinedInputColors({ - theme: getTheme(false, false), - }) - ).toMatchObject({ - inputTextColor: getTheme(false, false).colors.text, - }); - }); }); describe('getOutlinedInputColors - placeholder color', () => { @@ -1043,17 +859,6 @@ describe('getOutlinedInputColors - placeholder color', () => { }); }); - it('should return correct disabled color, for theme version 2', () => { - expect( - getOutlinedInputColors({ - disabled: true, - theme: getTheme(false, false), - }) - ).toMatchObject({ - placeholderColor: getTheme(false, false).colors.disabled, - }); - }); - it('should return correct theme color, for theme version 3', () => { expect( getOutlinedInputColors({ @@ -1063,16 +868,6 @@ describe('getOutlinedInputColors - placeholder color', () => { placeholderColor: getTheme().colors.onSurfaceVariant, }); }); - - it('should return correct theme color, for theme version 2', () => { - expect( - getOutlinedInputColors({ - theme: getTheme(false, false), - }) - ).toMatchObject({ - placeholderColor: getTheme(false, false).colors.placeholder, - }); - }); }); describe('getOutlinedInputColors - error color', () => { @@ -1089,10 +884,10 @@ describe('getOutlinedInputColors - error color', () => { expect( getOutlinedInputColors({ error: true, - theme: getTheme(false, true), + theme: getTheme(), }) ).toMatchObject({ - errorColor: getTheme(false, true).colors.error, + errorColor: getTheme().colors.error, }); }); }); @@ -1109,20 +904,6 @@ describe('getOutlinedInputColors - active color', () => { }); }); - it('should return disabled color, for theme version 2', () => { - expect( - getOutlinedInputColors({ - disabled: true, - theme: getTheme(false, false), - }) - ).toMatchObject({ - activeColor: color(getTheme(false, false).colors?.text) - .alpha(0.54) - .rgb() - .string(), - }); - }); - it('should return correct active color, if error, no matter what the theme is', () => { expect( getOutlinedInputColors({ @@ -1136,10 +917,10 @@ describe('getOutlinedInputColors - active color', () => { expect( getOutlinedInputColors({ error: true, - theme: getTheme(false, true), + theme: getTheme(), }) ).toMatchObject({ - activeColor: getTheme(false, true).colors.error, + activeColor: getTheme().colors.error, }); }); @@ -1156,7 +937,7 @@ describe('getOutlinedInputColors - active color', () => { expect( getOutlinedInputColors({ activeOutlineColor: 'beige', - theme: getTheme(false, false), + theme: getTheme(), }) ).toMatchObject({ activeColor: 'beige', @@ -1172,16 +953,6 @@ describe('getOutlinedInputColors - active color', () => { activeColor: getTheme().colors.primary, }); }); - - it('should return theme active color, for theme version 2', () => { - expect( - getOutlinedInputColors({ - theme: getTheme(false, true), - }) - ).toMatchObject({ - activeColor: getTheme(false, true).colors.primary, - }); - }); }); describe('outlineStyle - underlineStyle', () => { diff --git a/src/components/__tests__/ToggleButton.test.tsx b/src/components/__tests__/ToggleButton.test.tsx index 3ab234d0f3..a0e2bbafcb 100644 --- a/src/components/__tests__/ToggleButton.test.tsx +++ b/src/components/__tests__/ToggleButton.test.tsx @@ -68,18 +68,6 @@ describe('getToggleButtonColor', () => { ); }); - it('should return correct color when checked and theme version 2', () => { - expect( - getToggleButtonColor({ theme: getTheme(false, false), checked: true }) - ).toBe('rgba(0, 0, 0, .08)'); - }); - - it('should return correct color when checked and theme version 2, dark theme', () => { - expect( - getToggleButtonColor({ theme: getTheme(true, false), checked: true }) - ).toBe('rgba(255, 255, 255, .12)'); - }); - it('should return transparent color when not checked', () => { expect(getToggleButtonColor({ theme: getTheme(), checked: false })).toBe( 'transparent' diff --git a/src/components/__tests__/__snapshots__/Banner.test.tsx.snap b/src/components/__tests__/__snapshots__/Banner.test.tsx.snap index b1aaff7ab0..175383e4ad 100644 --- a/src/components/__tests__/__snapshots__/Banner.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Banner.test.tsx.snap @@ -82,21 +82,25 @@ exports[`render visible banner, with custom theme 1`] = ` }, { "color": "rgba(28, 27, 31, 1)", - "fontFamily": "System", - "fontWeight": "400", - "letterSpacing": 0, - }, - { "writingDirection": "ltr", }, [ { - "flex": 1, - "margin": 8, - }, - { - "color": "rgba(28, 27, 31, 1)", + "fontFamily": "System", + "fontSize": 14, + "fontWeight": "400", + "letterSpacing": 0.25, + "lineHeight": 20, }, + [ + { + "flex": 1, + "margin": 8, + }, + { + "color": "#00f", + }, + ], ], ] } @@ -234,7 +238,6 @@ exports[`render visible banner, with custom theme 1`] = ` "marginVertical": 9, "textAlign": "center", }, - false, { "marginHorizontal": 12, }, @@ -364,21 +367,25 @@ exports[`renders hidden banner, without action buttons and without image 1`] = ` }, { "color": "rgba(28, 27, 31, 1)", - "fontFamily": "System", - "fontWeight": "400", - "letterSpacing": 0, - }, - { "writingDirection": "ltr", }, [ { - "flex": 1, - "margin": 8, - }, - { - "color": "rgba(28, 27, 31, 1)", + "fontFamily": "System", + "fontSize": 14, + "fontWeight": "400", + "letterSpacing": 0.25, + "lineHeight": 20, }, + [ + { + "flex": 1, + "margin": 8, + }, + { + "color": "rgba(28, 27, 31, 1)", + }, + ], ], ] } @@ -505,21 +512,25 @@ exports[`renders visible banner, with action buttons and with image 1`] = ` }, { "color": "rgba(28, 27, 31, 1)", - "fontFamily": "System", - "fontWeight": "400", - "letterSpacing": 0, - }, - { "writingDirection": "ltr", }, [ { - "flex": 1, - "margin": 8, - }, - { - "color": "rgba(28, 27, 31, 1)", + "fontFamily": "System", + "fontSize": 14, + "fontWeight": "400", + "letterSpacing": 0.25, + "lineHeight": 20, }, + [ + { + "flex": 1, + "margin": 8, + }, + { + "color": "rgba(28, 27, 31, 1)", + }, + ], ], ] } @@ -657,7 +668,6 @@ exports[`renders visible banner, with action buttons and with image 1`] = ` "marginVertical": 9, "textAlign": "center", }, - false, { "marginHorizontal": 12, }, @@ -775,21 +785,25 @@ exports[`renders visible banner, with action buttons and without image 1`] = ` }, { "color": "rgba(28, 27, 31, 1)", - "fontFamily": "System", - "fontWeight": "400", - "letterSpacing": 0, - }, - { "writingDirection": "ltr", }, [ { - "flex": 1, - "margin": 8, - }, - { - "color": "rgba(28, 27, 31, 1)", + "fontFamily": "System", + "fontSize": 14, + "fontWeight": "400", + "letterSpacing": 0.25, + "lineHeight": 20, }, + [ + { + "flex": 1, + "margin": 8, + }, + { + "color": "rgba(28, 27, 31, 1)", + }, + ], ], ] } @@ -927,7 +941,6 @@ exports[`renders visible banner, with action buttons and without image 1`] = ` "marginVertical": 9, "textAlign": "center", }, - false, { "marginHorizontal": 12, }, @@ -1077,7 +1090,6 @@ exports[`renders visible banner, with action buttons and without image 1`] = ` "marginVertical": 9, "textAlign": "center", }, - false, { "marginHorizontal": 12, }, @@ -1217,21 +1229,25 @@ exports[`renders visible banner, without action buttons and with image 1`] = ` }, { "color": "rgba(28, 27, 31, 1)", - "fontFamily": "System", - "fontWeight": "400", - "letterSpacing": 0, - }, - { "writingDirection": "ltr", }, [ { - "flex": 1, - "margin": 8, - }, - { - "color": "rgba(28, 27, 31, 1)", + "fontFamily": "System", + "fontSize": 14, + "fontWeight": "400", + "letterSpacing": 0.25, + "lineHeight": 20, }, + [ + { + "flex": 1, + "margin": 8, + }, + { + "color": "rgba(28, 27, 31, 1)", + }, + ], ], ] } @@ -1336,21 +1352,25 @@ exports[`renders visible banner, without action buttons and without image 1`] = }, { "color": "rgba(28, 27, 31, 1)", - "fontFamily": "System", - "fontWeight": "400", - "letterSpacing": 0, - }, - { "writingDirection": "ltr", }, [ { - "flex": 1, - "margin": 8, - }, - { - "color": "rgba(28, 27, 31, 1)", + "fontFamily": "System", + "fontSize": 14, + "fontWeight": "400", + "letterSpacing": 0.25, + "lineHeight": 20, }, + [ + { + "flex": 1, + "margin": 8, + }, + { + "color": "rgba(28, 27, 31, 1)", + }, + ], ], ] } diff --git a/src/components/__tests__/__snapshots__/Button.test.tsx.snap b/src/components/__tests__/__snapshots__/Button.test.tsx.snap index db8e187690..d5f335c3f1 100644 --- a/src/components/__tests__/__snapshots__/Button.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Button.test.tsx.snap @@ -122,7 +122,6 @@ exports[`renders button with an accessibility hint 1`] = ` "marginVertical": 9, "textAlign": "center", }, - false, { "marginHorizontal": 12, }, @@ -273,7 +272,6 @@ exports[`renders button with an accessibility label 1`] = ` "marginVertical": 9, "textAlign": "center", }, - false, { "marginHorizontal": 12, }, @@ -423,7 +421,6 @@ exports[`renders button with button color 1`] = ` "marginVertical": 9, "textAlign": "center", }, - false, { "marginHorizontal": 12, }, @@ -573,7 +570,6 @@ exports[`renders button with color 1`] = ` "marginVertical": 9, "textAlign": "center", }, - false, { "marginHorizontal": 12, }, @@ -723,7 +719,6 @@ exports[`renders button with custom testID 1`] = ` "marginVertical": 9, "textAlign": "center", }, - false, { "marginHorizontal": 12, }, @@ -922,7 +917,6 @@ exports[`renders button with icon 1`] = ` "marginVertical": 9, "textAlign": "center", }, - false, { "marginHorizontal": 16, }, @@ -1123,7 +1117,6 @@ exports[`renders button with icon in reverse order 1`] = ` "marginVertical": 9, "textAlign": "center", }, - false, { "marginHorizontal": 16, }, @@ -1273,7 +1266,6 @@ exports[`renders contained contained with mode 1`] = ` "marginVertical": 9, "textAlign": "center", }, - false, { "marginHorizontal": 24, "marginVertical": 10, @@ -1424,7 +1416,6 @@ exports[`renders disabled button 1`] = ` "marginVertical": 9, "textAlign": "center", }, - false, { "marginHorizontal": 12, }, @@ -1782,7 +1773,6 @@ exports[`renders loading button 1`] = ` "marginVertical": 9, "textAlign": "center", }, - false, { "marginHorizontal": 16, }, @@ -1932,7 +1922,6 @@ exports[`renders outlined button with mode 1`] = ` "marginVertical": 9, "textAlign": "center", }, - false, { "marginHorizontal": 24, "marginVertical": 10, @@ -2083,7 +2072,6 @@ exports[`renders text button by default 1`] = ` "marginVertical": 9, "textAlign": "center", }, - false, { "marginHorizontal": 12, }, @@ -2233,7 +2221,6 @@ exports[`renders text button with mode 1`] = ` "marginVertical": 9, "textAlign": "center", }, - false, { "marginHorizontal": 12, }, diff --git a/src/components/__tests__/__snapshots__/DataTable.test.tsx.snap b/src/components/__tests__/__snapshots__/DataTable.test.tsx.snap index a6ffbfcb06..59e80d0aef 100644 --- a/src/components/__tests__/__snapshots__/DataTable.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/DataTable.test.tsx.snap @@ -1801,7 +1801,6 @@ exports[`DataTable.Pagination renders data table pagination with options select "marginVertical": 9, "textAlign": "center", }, - false, { "marginHorizontal": 24, "marginVertical": 10, diff --git a/src/components/__tests__/__snapshots__/DrawerItem.test.tsx.snap b/src/components/__tests__/__snapshots__/DrawerItem.test.tsx.snap index 78e3ed8612..e3d5e8ca8b 100644 --- a/src/components/__tests__/__snapshots__/DrawerItem.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/DrawerItem.test.tsx.snap @@ -43,10 +43,6 @@ exports[`renders DrawerItem with icon 1`] = ` "marginHorizontal": 10, "marginVertical": 4, }, - { - "backgroundColor": undefined, - "borderRadius": 28, - }, { "height": 56, "justifyContent": "center", @@ -54,6 +50,10 @@ exports[`renders DrawerItem with icon 1`] = ` "marginRight": 12, "marginVertical": 0, }, + { + "backgroundColor": undefined, + "borderRadius": 28, + }, undefined, ], ] @@ -202,10 +202,6 @@ exports[`renders active DrawerItem 1`] = ` "marginHorizontal": 10, "marginVertical": 4, }, - { - "backgroundColor": "rgba(232, 222, 248, 1)", - "borderRadius": 28, - }, { "height": 56, "justifyContent": "center", @@ -213,6 +209,10 @@ exports[`renders active DrawerItem 1`] = ` "marginRight": 12, "marginVertical": 0, }, + { + "backgroundColor": "rgba(232, 222, 248, 1)", + "borderRadius": 28, + }, undefined, ], ] @@ -361,10 +361,6 @@ exports[`renders basic DrawerItem 1`] = ` "marginHorizontal": 10, "marginVertical": 4, }, - { - "backgroundColor": undefined, - "borderRadius": 28, - }, { "height": 56, "justifyContent": "center", @@ -372,6 +368,10 @@ exports[`renders basic DrawerItem 1`] = ` "marginRight": 12, "marginVertical": 0, }, + { + "backgroundColor": undefined, + "borderRadius": 28, + }, undefined, ], ] diff --git a/src/components/__tests__/__snapshots__/Menu.test.tsx.snap b/src/components/__tests__/__snapshots__/Menu.test.tsx.snap index fc3ac61473..f2a20c8047 100644 --- a/src/components/__tests__/__snapshots__/Menu.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Menu.test.tsx.snap @@ -134,7 +134,6 @@ exports[`renders menu with content styles 1`] = ` "marginVertical": 9, "textAlign": "center", }, - false, { "marginHorizontal": 24, "marginVertical": 10, @@ -371,7 +370,6 @@ exports[`renders menu with content styles 1`] = ` pointerEvents="none" style={ [ - false, { "justifyContent": "center", }, @@ -408,7 +406,6 @@ exports[`renders menu with content styles 1`] = ` "lineHeight": 24, }, [ - false, { "color": "rgba(28, 27, 31, 1)", "fontFamily": "System", @@ -494,7 +491,6 @@ exports[`renders menu with content styles 1`] = ` pointerEvents="none" style={ [ - false, { "justifyContent": "center", }, @@ -531,7 +527,6 @@ exports[`renders menu with content styles 1`] = ` "lineHeight": 24, }, [ - false, { "color": "rgba(28, 27, 31, 1)", "fontFamily": "System", @@ -693,7 +688,6 @@ exports[`renders not visible menu 1`] = ` "marginVertical": 9, "textAlign": "center", }, - false, { "marginHorizontal": 24, "marginVertical": 10, @@ -859,7 +853,6 @@ exports[`renders visible menu 1`] = ` "marginVertical": 9, "textAlign": "center", }, - false, { "marginHorizontal": 24, "marginVertical": 10, @@ -1092,7 +1085,6 @@ exports[`renders visible menu 1`] = ` pointerEvents="none" style={ [ - false, { "justifyContent": "center", }, @@ -1129,7 +1121,6 @@ exports[`renders visible menu 1`] = ` "lineHeight": 24, }, [ - false, { "color": "rgba(28, 27, 31, 1)", "fontFamily": "System", @@ -1215,7 +1206,6 @@ exports[`renders visible menu 1`] = ` pointerEvents="none" style={ [ - false, { "justifyContent": "center", }, @@ -1252,7 +1242,6 @@ exports[`renders visible menu 1`] = ` "lineHeight": 24, }, [ - false, { "color": "rgba(28, 27, 31, 1)", "fontFamily": "System", diff --git a/src/components/__tests__/__snapshots__/MenuItem.test.tsx.snap b/src/components/__tests__/__snapshots__/MenuItem.test.tsx.snap index e16c6134f4..a34067f576 100644 --- a/src/components/__tests__/__snapshots__/MenuItem.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/MenuItem.test.tsx.snap @@ -67,7 +67,6 @@ exports[`Menu Item renders menu item 1`] = ` pointerEvents="box-none" style={ [ - false, { "width": 24, }, @@ -108,7 +107,6 @@ exports[`Menu Item renders menu item 1`] = ` pointerEvents="none" style={ [ - false, { "justifyContent": "center", }, @@ -145,7 +143,6 @@ exports[`Menu Item renders menu item 1`] = ` "lineHeight": 24, }, [ - false, { "color": "rgba(28, 27, 31, 1)", "fontFamily": "System", @@ -231,7 +228,6 @@ exports[`Menu Item renders menu item 1`] = ` pointerEvents="box-none" style={ [ - false, { "width": 24, }, @@ -272,7 +268,6 @@ exports[`Menu Item renders menu item 1`] = ` pointerEvents="none" style={ [ - false, { "justifyContent": "center", }, @@ -309,7 +304,6 @@ exports[`Menu Item renders menu item 1`] = ` "lineHeight": 24, }, [ - false, { "color": "rgba(28, 27, 31, 1)", "fontFamily": "System", @@ -395,7 +389,6 @@ exports[`Menu Item renders menu item 1`] = ` pointerEvents="box-none" style={ [ - false, { "width": 24, }, @@ -436,7 +429,6 @@ exports[`Menu Item renders menu item 1`] = ` pointerEvents="none" style={ [ - false, { "justifyContent": "center", }, @@ -473,7 +465,6 @@ exports[`Menu Item renders menu item 1`] = ` "lineHeight": 24, }, [ - false, { "color": "rgba(28, 27, 31, 0.38)", "fontFamily": "System", @@ -559,7 +550,6 @@ exports[`Menu Item renders menu item 1`] = ` pointerEvents="box-none" style={ [ - false, { "width": 24, }, @@ -600,7 +590,6 @@ exports[`Menu Item renders menu item 1`] = ` pointerEvents="none" style={ [ - false, { "justifyContent": "center", }, @@ -637,7 +626,6 @@ exports[`Menu Item renders menu item 1`] = ` "lineHeight": 24, }, [ - false, { "color": "rgba(28, 27, 31, 0.38)", "fontFamily": "System", @@ -723,7 +711,6 @@ exports[`Menu Item renders menu item 1`] = ` pointerEvents="none" style={ [ - false, { "justifyContent": "center", }, @@ -760,7 +747,6 @@ exports[`Menu Item renders menu item 1`] = ` "lineHeight": 24, }, [ - false, { "color": "rgba(28, 27, 31, 1)", "fontFamily": "System", diff --git a/src/components/__tests__/__snapshots__/Snackbar.test.tsx.snap b/src/components/__tests__/__snapshots__/Snackbar.test.tsx.snap index 9fdd75d4dc..b859166348 100644 --- a/src/components/__tests__/__snapshots__/Snackbar.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Snackbar.test.tsx.snap @@ -440,7 +440,6 @@ exports[`renders snackbar with action button 1`] = ` "marginVertical": 9, "textAlign": "center", }, - false, { "marginHorizontal": 12, }, diff --git a/src/core/PaperProvider.tsx b/src/core/PaperProvider.tsx index 44fd426ab5..04bc547d34 100644 --- a/src/core/PaperProvider.tsx +++ b/src/core/PaperProvider.tsx @@ -8,7 +8,7 @@ import { import SafeAreaProviderCompat from './SafeAreaProviderCompat'; import { Provider as SettingsProvider, Settings } from './settings'; -import { defaultThemesByVersion, ThemeProvider } from './theming'; +import { defaultThemes, ThemeProvider } from './theming'; import MaterialCommunityIcon from '../components/MaterialCommunityIcon'; import PortalHost from '../components/Portal/PortalHost'; import type { ThemeProp } from '../types'; @@ -21,12 +21,8 @@ export type Props = { }; const PaperProvider = (props: Props) => { - const isOnlyVersionInTheme = - props.theme && Object.keys(props.theme).length === 1 && props.theme.version; - const colorSchemeName = - ((!props.theme || isOnlyVersionInTheme) && Appearance?.getColorScheme()) || - 'light'; + (!props.theme && Appearance?.getColorScheme()) || 'light'; const [reduceMotionEnabled, setReduceMotionEnabled] = React.useState(false); @@ -59,13 +55,13 @@ const PaperProvider = (props: Props) => { React.useEffect(() => { let appearanceSubscription: NativeEventSubscription | undefined; - if (!props.theme || isOnlyVersionInTheme) { + if (!props.theme) { appearanceSubscription = Appearance?.addChangeListener( handleAppearanceChange ) as NativeEventSubscription | undefined; } return () => { - if (!props.theme || isOnlyVersionInTheme) { + if (!props.theme) { if (appearanceSubscription) { appearanceSubscription.remove(); } else { @@ -74,17 +70,16 @@ const PaperProvider = (props: Props) => { } } }; - }, [props.theme, isOnlyVersionInTheme]); + }, [props.theme]); const theme = React.useMemo(() => { - const themeVersion = props.theme?.version || 3; const scheme = colorScheme === 'dark' ? 'dark' : 'light'; - const defaultThemeBase = defaultThemesByVersion[themeVersion][scheme]; + const defaultThemeBase = defaultThemes[scheme]; const extendedThemeBase = { ...defaultThemeBase, ...props.theme, - version: themeVersion, + version: 3 as const, animation: { ...props.theme?.animation, scale: reduceMotionEnabled ? 0 : 1, @@ -93,7 +88,7 @@ const PaperProvider = (props: Props) => { return { ...extendedThemeBase, - isV3: extendedThemeBase.version === 3, + isV3: true as const, }; }, [colorScheme, props.theme, reduceMotionEnabled]); diff --git a/src/core/__tests__/PaperProvider.test.tsx b/src/core/__tests__/PaperProvider.test.tsx index 11c4beff49..28843d4ba7 100644 --- a/src/core/__tests__/PaperProvider.test.tsx +++ b/src/core/__tests__/PaperProvider.test.tsx @@ -8,12 +8,7 @@ import { import { render, act } from '@testing-library/react-native'; -import { - MD2LightTheme, - MD2DarkTheme, - MD3LightTheme, - MD3DarkTheme, -} from '../../styles/themes'; +import { MD3LightTheme, MD3DarkTheme } from '../../styles/themes'; import type { ThemeProp } from '../../types'; import PaperProvider from '../PaperProvider'; import { useTheme } from '../theming'; @@ -229,7 +224,6 @@ describe('PaperProvider', () => { colors: { ...ExtendedLightTheme.colors, primary: 'tomato', - accent: 'yellow', }, } as ThemeProp; const { getByTestId } = render(createProvider(customTheme)); @@ -237,23 +231,4 @@ describe('PaperProvider', () => { customTheme ); }); - - it.each` - version | colorScheme | expectedTheme - ${2} | ${'light'} | ${MD2LightTheme} - ${2} | ${'dark'} | ${MD2DarkTheme} - ${3} | ${'light'} | ${MD3LightTheme} - ${3} | ${'dark'} | ${MD3DarkTheme} - `( - 'uses correct theme, $colorScheme mode, version $version', - async ({ version, colorScheme, expectedTheme }) => { - mockAppearance(); - (Appearance.getColorScheme as jest.Mock).mockReturnValue(colorScheme); - const { getByTestId } = render(createProvider({ version })); - - expect(getByTestId('provider-child-view').props.theme).toStrictEqual( - expectedTheme - ); - } - ); }); diff --git a/src/core/theming.tsx b/src/core/theming.tsx index 44223f032a..042a83d960 100644 --- a/src/core/theming.tsx +++ b/src/core/theming.tsx @@ -3,12 +3,7 @@ import type { ComponentType } from 'react'; import { $DeepPartial, createTheming } from '@callstack/react-theme-provider'; import color from 'color'; -import { - MD2DarkTheme, - MD2LightTheme, - MD3DarkTheme, - MD3LightTheme, -} from '../styles/themes'; +import { MD3DarkTheme, MD3LightTheme } from '../styles/themes'; import type { InternalTheme, MD3Theme, @@ -36,30 +31,17 @@ export const withInternalTheme = ( WrappedComponent: ComponentType & C ) => withTheme(WrappedComponent); -export const defaultThemesByVersion = { - 2: { - light: MD2LightTheme, - dark: MD2DarkTheme, - }, - 3: { - light: MD3LightTheme, - dark: MD3DarkTheme, - }, +export const defaultThemes = { + light: MD3LightTheme, + dark: MD3DarkTheme, }; -export const getTheme = < - Scheme extends boolean = false, - IsVersion3 extends boolean = true ->( - isDark: Scheme = false as Scheme, - isV3: IsVersion3 = true as IsVersion3 -): (typeof defaultThemesByVersion)[IsVersion3 extends true - ? 3 - : 2][Scheme extends true ? 'dark' : 'light'] => { - const themeVersion = isV3 ? 3 : 2; +export const getTheme = ( + isDark: Scheme = false as Scheme +): (typeof defaultThemes)[Scheme extends true ? 'dark' : 'light'] => { const scheme = isDark ? 'dark' : 'light'; - return defaultThemesByVersion[themeVersion][scheme]; + return defaultThemes[scheme]; }; // eslint-disable-next-line no-redeclare diff --git a/src/index.tsx b/src/index.tsx index 1b20528787..7e609b709e 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -19,9 +19,7 @@ export { default as configureFonts } from './styles/fonts'; import * as Avatar from './components/Avatar/Avatar'; import * as Drawer from './components/Drawer/Drawer'; import * as List from './components/List/List'; -import * as MD2Colors from './styles/themes/v2/colors'; -export { MD2Colors }; export { Avatar, List, Drawer }; export * from './components/FAB/AnimatedFAB'; @@ -161,7 +159,6 @@ export type { } from './react-navigation'; export type { - MD2Theme, MD3Theme, ThemeBase, MD3Elevation, diff --git a/src/styles/__tests__/fonts.test.js b/src/styles/__tests__/fonts.test.js index fb8dce5ba5..6deed087a4 100644 --- a/src/styles/__tests__/fonts.test.js +++ b/src/styles/__tests__/fonts.test.js @@ -1,10 +1,3 @@ -const customFont = { - custom: { - fontFamily: 'sans-serif', - fontWeight: 'bold', - }, -}; - const customFontV3 = { displayLarge: { fontFamily: 'NotoSans', @@ -131,18 +124,16 @@ const mockPlatform = (OS) => { const loadFonts = () => { let configureFonts; - let fontConfig; let typescale; jest.isolateModules(() => { const fonts = require('../fonts'); configureFonts = fonts.default; - fontConfig = fonts.fontConfig; typescale = require('../themes/v3/tokens').typescale; }); - return { configureFonts, fontConfig, typescale }; + return { configureFonts, typescale }; }; describe('configureFonts', () => { @@ -150,66 +141,6 @@ describe('configureFonts', () => { jest.dontMock('react-native'); }); - it('adds custom fonts to the iOS config', () => { - mockPlatform('ios'); - const { configureFonts, fontConfig } = loadFonts(); - - expect( - configureFonts({ - config: { - ios: { - ...fontConfig.ios, - customFont, - }, - }, - isV3: false, - }) - ).toEqual({ - ...fontConfig.ios, - customFont, - }); - }); - - it('adds custom fonts to the Android config', () => { - mockPlatform('android'); - const { configureFonts, fontConfig } = loadFonts(); - - expect( - configureFonts({ - config: { - android: { - ...fontConfig.android, - customFont, - }, - }, - isV3: false, - }) - ).toEqual({ - ...fontConfig.android, - customFont, - }); - }); - - it('adds custom fonts to the Web config', () => { - mockPlatform('web'); - const { configureFonts, fontConfig } = loadFonts(); - - expect( - configureFonts({ - config: { - web: { - ...fontConfig.web, - customFont, - }, - }, - isV3: false, - }) - ).toEqual({ - ...fontConfig.web, - customFont, - }); - }); - it('overrides properties passed in config for all variants', () => { mockPlatform('ios'); const { configureFonts } = loadFonts(); diff --git a/src/styles/fonts.tsx b/src/styles/fonts.tsx index e3b5017fc4..07a0ab2a2e 100644 --- a/src/styles/fonts.tsx +++ b/src/styles/fonts.tsx @@ -1,69 +1,6 @@ -import { Platform, PlatformOSType } from 'react-native'; - -import type { Fonts, MD3Type, MD3Typescale, MD3TypescaleKey } from '../types'; +import type { MD3Type, MD3Typescale, MD3TypescaleKey } from '../types'; import { typescale } from './themes/v3/tokens'; -export const fontConfig = { - web: { - regular: { - fontFamily: 'Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif', - fontWeight: '400' as '400', - }, - medium: { - fontFamily: 'Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif', - fontWeight: '500' as '500', - }, - light: { - fontFamily: 'Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif', - fontWeight: '300' as '300', - }, - thin: { - fontFamily: 'Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif', - fontWeight: '100' as '100', - }, - }, - ios: { - regular: { - fontFamily: 'System', - fontWeight: '400' as '400', - }, - medium: { - fontFamily: 'System', - fontWeight: '500' as '500', - }, - light: { - fontFamily: 'System', - fontWeight: '300' as '300', - }, - thin: { - fontFamily: 'System', - fontWeight: '100' as '100', - }, - }, - default: { - regular: { - fontFamily: 'sans-serif', - fontWeight: 'normal' as 'normal', - }, - medium: { - fontFamily: 'sans-serif-medium', - fontWeight: 'normal' as 'normal', - }, - light: { - fontFamily: 'sans-serif-light', - fontWeight: 'normal' as 'normal', - }, - thin: { - fontFamily: 'sans-serif-thin', - fontWeight: 'normal' as 'normal', - }, - }, -}; - -type MD2FontsConfig = { - [platform in PlatformOSType | 'default']?: Fonts; -}; - type MD3FontsConfig = | { [key in MD3TypescaleKey]: Partial; @@ -73,11 +10,6 @@ type MD3FontsConfig = } | Partial; -function configureV2Fonts(config: MD2FontsConfig): Fonts { - const fonts = Platform.select({ ...fontConfig, ...config }) as Fonts; - return fonts; -} - function configureV3Fonts( config: MD3FontsConfig ): MD3Typescale | (MD3Typescale & { [key: string]: MD3Type }) { @@ -110,13 +42,6 @@ function configureV3Fonts( ); } -// eslint-disable-next-line no-redeclare -export default function configureFonts(params: { isV3: false }): Fonts; -// eslint-disable-next-line no-redeclare -export default function configureFonts(params: { - config?: MD2FontsConfig; - isV3: false; -}): Fonts; // eslint-disable-next-line no-redeclare export default function configureFonts(params?: { config?: Partial; @@ -134,10 +59,6 @@ export default function configureFonts(params: { }): MD3Typescale & { [key: string]: MD3Type }; // eslint-disable-next-line no-redeclare export default function configureFonts(params?: any) { - const { isV3 = true, config } = params || {}; - - if (isV3) { - return configureV3Fonts(config); - } - return configureV2Fonts(config); + const { config } = params || {}; + return configureV3Fonts(config); } diff --git a/src/styles/overlay.tsx b/src/styles/overlay.tsx index f9e6f8f9a5..050e0c06d1 100644 --- a/src/styles/overlay.tsx +++ b/src/styles/overlay.tsx @@ -2,7 +2,7 @@ import { Animated } from 'react-native'; import color from 'color'; -import { MD2DarkTheme } from './themes/v2/DarkTheme'; +import { MD3DarkTheme } from './themes'; export const isAnimatedValue = ( it: number | string | Animated.AnimatedInterpolation @@ -10,7 +10,7 @@ export const isAnimatedValue = ( export default function overlay( elevation: T, - surfaceColor: string = MD2DarkTheme.colors?.surface + surfaceColor: string = MD3DarkTheme.colors.surface ): T extends number ? string : Animated.AnimatedInterpolation { if (isAnimatedValue(elevation)) { const inputRange = [0, 1, 2, 3, 8, 24]; diff --git a/src/styles/shadow.tsx b/src/styles/shadow.tsx index dcc11e8b65..57cc3612de 100644 --- a/src/styles/shadow.tsx +++ b/src/styles/shadow.tsx @@ -1,73 +1,12 @@ import { Animated } from 'react-native'; -import * as MD2Colors from './themes/v2/colors'; import { MD3Colors } from './themes/v3/tokens'; -const SHADOW_COLOR = MD2Colors.black; -const SHADOW_OPACITY = 0.24; const MD3_SHADOW_OPACITY = 0.3; const MD3_SHADOW_COLOR = MD3Colors.primary0; -export default function shadow( - elevation: number | Animated.Value = 0, - isV3 = false -) { - return isV3 ? v3Shadow(elevation) : v2Shadow(elevation); -} - -function v2Shadow(elevation: number | Animated.Value = 0) { - if (elevation instanceof Animated.Value) { - const inputRange = [0, 1, 2, 3, 8, 24]; - - return { - shadowColor: SHADOW_COLOR, - shadowOffset: { - width: new Animated.Value(0), - height: elevation.interpolate({ - inputRange, - outputRange: [0, 0.5, 0.75, 2, 7, 23], - }), - }, - shadowOpacity: elevation.interpolate({ - inputRange: [0, 1], - outputRange: [0, SHADOW_OPACITY], - extrapolate: 'clamp', - }), - shadowRadius: elevation.interpolate({ - inputRange, - outputRange: [0, 0.75, 1.5, 3, 8, 24], - }), - }; - } else { - if (elevation === 0) { - return {}; - } - - let height, radius; - switch (elevation) { - case 1: - height = 0.5; - radius = 0.75; - break; - case 2: - height = 0.75; - radius = 1.5; - break; - default: - height = elevation - 1; - radius = elevation; - } - - return { - shadowColor: SHADOW_COLOR, - shadowOffset: { - width: 0, - height, - }, - shadowOpacity: SHADOW_OPACITY, - shadowRadius: radius, - }; - } +export default function shadow(elevation: number | Animated.Value = 0) { + return v3Shadow(elevation); } function v3Shadow(elevation: number | Animated.Value = 0) { diff --git a/src/styles/themes/index.ts b/src/styles/themes/index.ts index 3db1a460ad..39bcb6648c 100644 --- a/src/styles/themes/index.ts +++ b/src/styles/themes/index.ts @@ -1,4 +1,2 @@ export { MD3LightTheme } from './v3/LightTheme'; export { MD3DarkTheme } from './v3/DarkTheme'; -export { MD2LightTheme } from './v2/LightTheme'; -export { MD2DarkTheme } from './v2/DarkTheme'; diff --git a/src/styles/themes/v2/DarkTheme.tsx b/src/styles/themes/v2/DarkTheme.tsx deleted file mode 100644 index 9eaa576dcb..0000000000 --- a/src/styles/themes/v2/DarkTheme.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import color from 'color'; - -import { black, pinkA100, white } from './colors'; -import { MD2LightTheme } from './LightTheme'; -import type { Fonts, MD2Theme } from '../../../types'; -import configureFonts from '../../fonts'; - -export const MD2DarkTheme: MD2Theme = { - ...MD2LightTheme, - dark: true, - mode: 'adaptive', - version: 2, - isV3: false, - colors: { - ...MD2LightTheme.colors, - primary: '#BB86FC', - accent: '#03dac6', - background: '#121212', - surface: '#121212', - error: '#CF6679', - onSurface: '#FFFFFF', - text: white, - disabled: color(white).alpha(0.38).rgb().string(), - placeholder: color(white).alpha(0.54).rgb().string(), - backdrop: color(black).alpha(0.5).rgb().string(), - notification: pinkA100, - tooltip: 'rgba(230, 225, 229, 1)', - }, - fonts: configureFonts({ isV3: false }) as Fonts, -}; diff --git a/src/styles/themes/v2/LightTheme.tsx b/src/styles/themes/v2/LightTheme.tsx deleted file mode 100644 index 8566bdcc40..0000000000 --- a/src/styles/themes/v2/LightTheme.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import color from 'color'; - -import { black, pinkA400, white } from './colors'; -import type { Fonts, MD2Theme } from '../../../types'; -import configureFonts from '../../fonts'; - -export const MD2LightTheme: MD2Theme = { - dark: false, - roundness: 4, - version: 2, - isV3: false, - colors: { - primary: '#6200ee', - accent: '#03dac4', - background: '#f6f6f6', - surface: white, - error: '#B00020', - text: black, - onSurface: '#000000', - disabled: color(black).alpha(0.26).rgb().string(), - placeholder: color(black).alpha(0.54).rgb().string(), - backdrop: color(black).alpha(0.5).rgb().string(), - notification: pinkA400, - tooltip: 'rgba(28, 27, 31, 1)', - }, - fonts: configureFonts({ isV3: false }) as Fonts, - animation: { - scale: 1.0, - }, -}; diff --git a/src/types.tsx b/src/types.tsx index 175131cab3..4208fa0d64 100644 --- a/src/types.tsx +++ b/src/types.tsx @@ -28,21 +28,6 @@ export type Fonts = { type Mode = 'adaptive' | 'exact'; -export type MD2Colors = { - primary: string; - background: string; - surface: string; - accent: string; - error: string; - text: string; - onSurface: string; - disabled: string; - placeholder: string; - backdrop: string; - notification: string; - tooltip: string; -}; - export type MD3Colors = { primary: string; primaryContainer: string; @@ -132,14 +117,7 @@ export type MD3Theme = ThemeBase & { fonts: MD3Typescale; }; -export type MD2Theme = ThemeBase & { - version: 2; - isV3: false; - colors: MD2Colors; - fonts: Fonts; -}; - -export type InternalTheme = MD2Theme | MD3Theme; +export type InternalTheme = MD3Theme; // MD3 types export enum MD3TypescaleKey { From e5fcbdca3a0c5e426450dcfc1af7b93216e9b700 Mon Sep 17 00:00:00 2001 From: Diogo Mota Date: Mon, 13 Apr 2026 12:10:05 +0100 Subject: [PATCH 02/13] docs: remove md2 references from docs --- docs/docs/guides/01-getting-started.md | 4 - docs/docs/guides/02-theming.mdx | 110 +----------------- docs/docs/guides/04-fonts.md | 95 +-------------- .../08-theming-with-react-navigation.md | 57 +-------- docs/docs/guides/10-migration-guide-to-5.0.md | 37 +----- docs/static/llms.txt | 4 +- 6 files changed, 16 insertions(+), 291 deletions(-) diff --git a/docs/docs/guides/01-getting-started.md b/docs/docs/guides/01-getting-started.md index 68071c4d25..19fc3c2dea 100644 --- a/docs/docs/guides/01-getting-started.md +++ b/docs/docs/guides/01-getting-started.md @@ -165,7 +165,3 @@ export default function Main() { ); } ``` - -:::note -For MD2 check the following [Material Design 2 default theme](https://github.com/callstack/react-native-paper/blob/main/src/styles/themes/v2/LightTheme.tsx). -::: diff --git a/docs/docs/guides/02-theming.mdx b/docs/docs/guides/02-theming.mdx index 76869182ae..beeb8bfaff 100644 --- a/docs/docs/guides/02-theming.mdx +++ b/docs/docs/guides/02-theming.mdx @@ -65,9 +65,7 @@ You can change the theme prop dynamically and all the components will automatica A theme usually contains the following properties: - `dark` (`boolean`): whether this is a dark theme or light theme. -- `version`: specify which design system components should follow in the app - - 3 - new Material You (MD3) - - 2 - previous Material Design (MD2) +- `version`: Material You (MD3); kept for compatibility and normalized to `3` by `PaperProvider` - `mode` (`'adaptive' | 'exact'`): color mode for dark theme (See [Dark Theme](#dark-theme)). - `roundness` (`number`): roundness of common elements, such as buttons. - `colors` (`object`): various colors used throughout different elements. @@ -471,111 +469,13 @@ export default function HomeScreen() { } ``` -## Material Design 2 +## Material Design 3 -Using Material Design 2 is fully supported in React Native Paper v5.x. +React Native Paper ships with Material Design 3 (Material You) only. Customize the default experience by extending `MD3LightTheme` or `MD3DarkTheme` (see [Extending the theme](#extending-the-theme) and [Advanced theme overrides](#advanced-theme-overrides)). -### Simple setup +### Migrating from Material Design 2 -In order to use the Material Design 2 theme you can just pass `{ version: 2 }` to the PaperProvider theme prop: - -```js -import * as React from 'react'; -import { PaperProvider } from 'react-native-paper'; -import App from './src/App'; - -export default function Main() { - return ( - - - - ); -} -``` - -Specifying `{ version: 2 }` tells React Native Paper to use the built in Material Design 2 theme, so you don't have to fully extend it on your own. - -### Advanced setup - -As with any theme, you can also specify your custom properties within the Material Design 2 theme: - -```js -import * as React from 'react'; -import { MD2LightTheme, PaperProvider } from 'react-native-paper'; -import App from './src/App'; - -export default function Main() { - const theme = { - ...MD2LightTheme, - - // Specify a custom property - custom: 'property', - - // Specify a custom nested property - colors: { - ...MD2LightTheme.colors, - primary: '#fefefe', - }, - }; - - return ( - - - - ); -} -``` - -### Typescript - -Due to the amount of changes in the theme's schema shape it falls into the [Advanced theme overrides](#advanced-theme-overrides) category. The steps are identical as with any advanced theme, just make sure to extend the built-in `MD2LightTheme` or `MD2DarkTheme` instead of `MD3LightTheme` or `MD3DarkTheme`. - -The final example for Material Design 2 would look like this: - -```ts -import * as React from 'react'; -import { MD2LightTheme, PaperProvider, useTheme } from 'react-native-paper'; -import App from './src/App'; - -const theme = { - // Extend Material Design 2 theme - - ...MD2LightTheme, // or MD2DarkTheme - - // Specify a custom property - myOwnProperty: true, - - // Specify a custom nested property - colors: { - ...MD2LightTheme.colors, - myOwnColor: '#BADA55', - }, -}; - -export type AppTheme = typeof theme; - -export const useAppTheme = () => useTheme(); - -export default function Main() { - return ( - - - - ); -} - -// App.tsx - -export default function App() { - const { theme } = useAppTheme(); - - return ; -} -``` - -### Migrating to Material You - -If you are migrating from Material Design 2 (4.x and lower) to Material You (5.x), please refer to our [Migration Guide](https://callstack.github.io/react-native-paper/docs/guides/migration-guide-to-5.0) +If you are upgrading from Material Design 2 (4.x and lower), follow the [Migration Guide](https://callstack.github.io/react-native-paper/docs/guides/migration-guide-to-5.0). ## Applying a theme to a paper component diff --git a/docs/docs/guides/04-fonts.md b/docs/docs/guides/04-fonts.md index 60d3c6e457..5e8e435c0a 100644 --- a/docs/docs/guides/04-fonts.md +++ b/docs/docs/guides/04-fonts.md @@ -47,99 +47,8 @@ Now, you are able to use `fontFamily` from font files. ## Configuring fonts in ThemeProvider -### Material Design 2 - -#### Using `configureFonts` helper - -To create a custom font, prepare a `fontConfig` object where fonts are divided by platforms. After that, you have to: - -* pass the `fontConfig` into `configureFonts` params object property called `config` -* set the params object property `isV3` to `false`. - -The `fontConfig` object accepts `ios`, `android`, `macos`, `windows`, `web`, and `native`. Use these to override fonts on particular platforms. - -:::info -At a minimum, you need to explicitly pass fonts for `android`, `ios`, and `web`. -::: - -```js -import * as React from 'react'; -import { configureFonts, MD2LightTheme, PaperProvider } from 'react-native-paper'; -import App from './src/App'; - -const fontConfig = { - web: { - regular: { - fontFamily: 'sans-serif', - fontWeight: 'normal', - }, - medium: { - fontFamily: 'sans-serif-medium', - fontWeight: 'normal', - }, - light: { - fontFamily: 'sans-serif-light', - fontWeight: 'normal', - }, - thin: { - fontFamily: 'sans-serif-thin', - fontWeight: 'normal', - }, - }, - ios: { - regular: { - fontFamily: 'sans-serif', - fontWeight: 'normal', - }, - medium: { - fontFamily: 'sans-serif-medium', - fontWeight: 'normal', - }, - light: { - fontFamily: 'sans-serif-light', - fontWeight: 'normal', - }, - thin: { - fontFamily: 'sans-serif-thin', - fontWeight: 'normal', - }, - }, - android: { - regular: { - fontFamily: 'sans-serif', - fontWeight: 'normal', - }, - medium: { - fontFamily: 'sans-serif-medium', - fontWeight: 'normal', - }, - light: { - fontFamily: 'sans-serif-light', - fontWeight: 'normal', - }, - thin: { - fontFamily: 'sans-serif-thin', - fontWeight: 'normal', - }, - } -}; - -const theme = { - ...MD2LightTheme, - fonts: configureFonts({config: fontConfig, isV3: false}), -}; - -export default function Main() { - return ( - - - - ); -} -``` - -:::tip -If you're using TypeScript use `as const` when defining `fontConfig`. +:::note +Older Material Design 2 platform-split font configuration (`configureFonts` with per-platform `ios` / `android` / `web` keys) is no longer supported. Use the Material Design 3 typescale and `configureFonts` as documented below. ::: ### Material Design 3 diff --git a/docs/docs/guides/08-theming-with-react-navigation.md b/docs/docs/guides/08-theming-with-react-navigation.md index 6003953c02..15dbfbbec6 100644 --- a/docs/docs/guides/08-theming-with-react-navigation.md +++ b/docs/docs/guides/08-theming-with-react-navigation.md @@ -11,25 +11,9 @@ But how to make them work together? ## Themes adaptation -### Material Design 2 - -Fortunately, in Material Design 2, both React Navigation and React Native Paper offer very similar API when it comes to theming and theme color structure. It's possible to import them in light and dark variants from both. - -```js -import { - DarkTheme as NavigationDarkTheme, - DefaultTheme as NavigationDefaultTheme, -} from '@react-navigation/native'; - -import { - MD2LightTheme, - MD2DarkTheme, -} from 'react-native-paper'; -``` - ### Material Design 3 -From v5, React Native Paper theme colors structure follows the Material Design 3 (known as Material You) colors system, which differs significantly from both the previous Paper's theme and React Navigation theme. +React Native Paper follows the Material Design 3 (Material You) color system, which differs from React Navigation’s default theme shape. However, to simplify adapting React Navigation theme colors, to use the ones from React Native Paper, it's worth using a utility called `adaptNavigationTheme` – it accepts navigation-compliant themes in both modes and returns their equivalents adjusted to Material Design 3. @@ -127,24 +111,6 @@ To make things easier we can use [deepmerge](https://www.npmjs.com/package/deepm npm install deepmerge ``` -### Material Design 2 - -```js -import { - NavigationContainer, - DarkTheme as NavigationDarkTheme, - DefaultTheme as NavigationDefaultTheme, -} from '@react-navigation/native'; -import { - MD2DarkTheme, - MD2LightTheme, -} from 'react-native-paper'; -import merge from 'deepmerge'; - -const CombinedDefaultTheme = merge(MD2LightTheme, NavigationDefaultTheme); -const CombinedDarkTheme = merge(MD2DarkTheme, NavigationDarkTheme); -``` - ### Material Design 3 ```js @@ -171,27 +137,6 @@ const CombinedDarkTheme = merge(MD3DarkTheme, DarkTheme); Alternatively, we could merge those themes using vanilla JavaScript: -### Material Design 2 - -```js -const CombinedDefaultTheme = { - ...MD2LightTheme, - ...NavigationDefaultTheme, - colors: { - ...MD2LightTheme.colors, - ...NavigationDefaultTheme.colors, - }, -}; -const CombinedDarkTheme = { - ...MD2DarkTheme, - ...NavigationDarkTheme, - colors: { - ...MD2DarkTheme.colors, - ...NavigationDarkTheme.colors, - }, -}; -``` - ### Material Design 3 ```js diff --git a/docs/docs/guides/10-migration-guide-to-5.0.md b/docs/docs/guides/10-migration-guide-to-5.0.md index 6c358d387f..7631b8cf94 100644 --- a/docs/docs/guides/10-migration-guide-to-5.0.md +++ b/docs/docs/guides/10-migration-guide-to-5.0.md @@ -4,7 +4,7 @@ title: Introducing v5 with Material You React Native Paper v5 is all about adopting the new Material Design 3 aka Material You. It was released in October 2021 after intense work and effort to make Material You follow a more expressive approach to design. -Paper now supports both Material Design 2 and 3 through the configuration described in [Versioning](#versioning) and is compatible with a handful of API changes. +Current releases use Material Design 3 only; the historical `version: 2` / MD2 theme APIs described below were removed after v5. Use this guide when upgrading older apps to MD3. # Migration guide to Material You 5.0 @@ -36,15 +36,12 @@ npx pod-install ### Versioning -Introducing Material You (MD3) into `react-native-paper` doesn't mean dropping previous Material Design (MD2)! On the contrary, both of them will be supported, however, not simultaneously. To specify which design system components should follow in the app, there is a newly created property in [the theme](https://callstack.github.io/react-native-paper/docs/guides/theming#theme-properties) named `version` that accepts one of two values: - -* 3(default) new Material You (MD3), -* 2 - previous Material Design (MD2). +In v5, Material You (MD3) became the default theme. Earlier releases also exposed `version: 2` for Material Design 2; that option and MD2 theme exports have since been removed—use MD3 themes (`MD3LightTheme` / `MD3DarkTheme`) only. ```js theme: { /* ... */ - version: 3 | 2 + version: 3 } ``` @@ -166,35 +163,13 @@ Take a look at the suggested replacement diff: ### Configure fonts -The existing utility called `configureFonts` was adjusted to help users configure their theme fonts in both version, that's why that function, as of today, is going to accept the object with the follwing properties as an argument: +The `configureFonts` helper configures the Material Design 3 typescale. Pass overrides via the `config` object (see [Fonts](https://callstack.github.io/react-native-paper/docs/guides/fonts.html)). ```ts -configureFonts(params) -``` - -Parameters: - -| NAME | TYPE | REQUIRED | -| ----------- | ----------- | ----------- | -| params | object | No | - -Valid `params` keys are: - - * `config` ([MD2FontsConfig](https://github.com/callstack/react-native-paper/blob/main/src/styles/fonts.tsx#L63) | [MD3FontsConfig](https://github.com/callstack/react-native-paper/blob/main/src/styles/fonts.tsx#L67)) - fonts config object appropriate to the MD version - * `isV3` (boolean) - whether adjusting theme fonts for v3. Default it true. - -To use your current font config from v2 and migrate to v3 there are two requirements: -* the font config previously passed directly into function has to be passed into the params object property called `config` -* the params object property `isV3` has to be set to `false` - -```diff -- configureFonts(fontConfig) -+ configureFonts({config: fontConfig, isV3: false}) +configureFonts({ config: { bodyLarge: { fontFamily: 'System' } } }) ``` -:::tip -If you want to check how to use `configureFonts` on MD3, check the [Fonts](https://callstack.github.io/react-native-paper/docs/guides/fonts.html) guide. -::: +Older direct calls like `configureFonts(fontConfig)` and MD2 platform-split configs should be replaced with MD3 variant keys (`displayLarge`, `bodyMedium`, and so on). ## Components diff --git a/docs/static/llms.txt b/docs/static/llms.txt index 46da789d41..4029ace3ea 100644 --- a/docs/static/llms.txt +++ b/docs/static/llms.txt @@ -7,7 +7,7 @@ - Install: npm install react-native-paper react-native-safe-area-context - Wrap your app with PaperProvider -- Default theme is Material You (MD3); set theme.version: 2 for MD2 +- Default theme is Material You (MD3) - Requires React Native 0.72+ and React 18+ ## Guides @@ -63,7 +63,7 @@ - Theme object accepts colors, dark, roundness, fonts, animation, and version properties - Use useTheme() hook or ThemeProvider for nested theme overrides -- MD3 (Material You) is the default; set version: 2 for MD2 compatibility +- MD3 (Material You) is the only supported design system; extend MD3LightTheme / MD3DarkTheme - See theming guide: https://callstack.github.io/react-native-paper/docs/guides/theming ## Provider Pattern From c7656d536c7118c03d9ba20e6208f01f0f0e4cd2 Mon Sep 17 00:00:00 2001 From: Diogo Mota Date: Mon, 13 Apr 2026 13:55:02 +0100 Subject: [PATCH 03/13] chore: update example to use md3 only, removing md2 references --- example/src/DrawerItems.tsx | 23 +- .../src/Examples/ActivityIndicatorExample.tsx | 12 +- .../AnimatedFABExample/AnimatedFABExample.tsx | 40 ++-- example/src/Examples/AppbarExample.tsx | 141 +++++------- example/src/Examples/AvatarExample.tsx | 12 +- example/src/Examples/BadgeExample.tsx | 11 +- example/src/Examples/BannerExample.tsx | 33 ++- .../src/Examples/BottomNavigationExample.tsx | 18 +- example/src/Examples/ButtonExample.tsx | 214 +++++++++--------- example/src/Examples/CheckboxExample.tsx | 27 +-- example/src/Examples/ChipExample.tsx | 159 ++++++------- .../Dialogs/DialogWithCustomColors.tsx | 26 +-- .../DialogWithDismissableBackButton.tsx | 4 +- .../Dialogs/DialogWithLoadingIndicator.tsx | 6 +- .../Examples/Dialogs/UndismissableDialog.tsx | 4 +- example/src/Examples/IconButtonExample.tsx | 31 +-- example/src/Examples/MenuExample.tsx | 27 +-- example/src/Examples/ProgressBarExample.tsx | 8 +- example/src/Examples/RadioButtonExample.tsx | 17 +- example/src/Examples/SwitchExample.tsx | 37 +-- example/src/Examples/TextInputExample.tsx | 27 +-- example/src/PreferencesContext.tsx | 5 +- example/src/hooks/useExampleTheme.ts | 4 +- example/src/index.native.tsx | 21 +- example/src/index.tsx | 26 +-- 25 files changed, 342 insertions(+), 591 deletions(-) diff --git a/example/src/DrawerItems.tsx b/example/src/DrawerItems.tsx index 2d3ca6c202..2a31565f67 100644 --- a/example/src/DrawerItems.tsx +++ b/example/src/DrawerItems.tsx @@ -9,7 +9,6 @@ import { Button, Dialog, Drawer, - MD2Colors, MD3Colors, Switch, Text, @@ -107,7 +106,6 @@ function DrawerItems() { toggleShouldUseDeviceColors, toggleTheme, toggleRtl: toggleRTL, - toggleThemeVersion, toggleCollapsed, toggleCustomFont, toggleRippleEffect, @@ -137,14 +135,10 @@ function DrawerItems() { }; const coloredLabelTheme = { - colors: isV3 - ? { - secondaryContainer: MD3Colors.tertiary80, - onSecondaryContainer: MD3Colors.tertiary20, - } - : { - primary: MD2Colors.tealA200, - }, + colors: { + secondaryContainer: MD3Colors.tertiary80, + onSecondaryContainer: MD3Colors.tertiary20, + }, }; return ( @@ -217,15 +211,6 @@ function DrawerItems() { )} - - - MD 2 - - - - - - {isV3 && ( diff --git a/example/src/Examples/ActivityIndicatorExample.tsx b/example/src/Examples/ActivityIndicatorExample.tsx index 8013142921..15686054fa 100644 --- a/example/src/Examples/ActivityIndicatorExample.tsx +++ b/example/src/Examples/ActivityIndicatorExample.tsx @@ -1,20 +1,12 @@ import * as React from 'react'; import { StyleSheet, View } from 'react-native'; -import { - ActivityIndicator, - FAB, - List, - MD2Colors, - MD3Colors, -} from 'react-native-paper'; +import { ActivityIndicator, FAB, List, MD3Colors } from 'react-native-paper'; -import { useExampleTheme } from '../hooks/useExampleTheme'; import ScreenWrapper from '../ScreenWrapper'; const ActivityIndicatorExample = () => { const [animating, setAnimating] = React.useState(true); - const { isV3 } = useExampleTheme(); return ( @@ -49,7 +41,7 @@ const ActivityIndicatorExample = () => { diff --git a/example/src/Examples/AnimatedFABExample/AnimatedFABExample.tsx b/example/src/Examples/AnimatedFABExample/AnimatedFABExample.tsx index 4bffa05322..f9b2303fad 100644 --- a/example/src/Examples/AnimatedFABExample/AnimatedFABExample.tsx +++ b/example/src/Examples/AnimatedFABExample/AnimatedFABExample.tsx @@ -3,13 +3,7 @@ import type { NativeScrollEvent, NativeSyntheticEvent } from 'react-native'; import { Animated, FlatList, Platform, StyleSheet, View } from 'react-native'; import Icon from '@expo/vector-icons/MaterialCommunityIcons'; -import { - Avatar, - MD2Colors, - MD3Colors, - Paragraph, - Text, -} from 'react-native-paper'; +import { Avatar, MD3Colors, Text } from 'react-native-paper'; import CustomFAB from './CustomFAB'; import CustomFABControls, { @@ -32,7 +26,7 @@ type Item = { }; const AnimatedFABExample = () => { - const { colors, isV3 } = useExampleTheme(); + const { colors } = useExampleTheme(); const isIOS = Platform.OS === 'ios'; @@ -47,63 +41,55 @@ const AnimatedFABExample = () => { const renderItem = React.useCallback( ({ item }: { item: Item }) => { - const TextComponent = isV3 ? Text : Paragraph; - return ( - {item.sender} - - + {item.date} - + - {item.header} - - + {item.message} - + setVisible(!visible)} @@ -114,7 +100,7 @@ const AnimatedFABExample = () => { ); }, - [visible, isV3] + [visible] ); const onScroll = ({ diff --git a/example/src/Examples/AppbarExample.tsx b/example/src/Examples/AppbarExample.tsx index 1ebe74bad5..a5b1042ea5 100644 --- a/example/src/Examples/AppbarExample.tsx +++ b/example/src/Examples/AppbarExample.tsx @@ -6,7 +6,7 @@ import { Appbar, FAB, List, - Paragraph, + MD3Colors, RadioButton, Snackbar, Switch, @@ -14,7 +14,6 @@ import { } from 'react-native-paper'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; -import { yellowA200 } from '../../../src/styles/themes/v2/colors'; import { useExampleTheme } from '../hooks/useExampleTheme'; import ScreenWrapper from '../ScreenWrapper'; @@ -41,7 +40,7 @@ const AppbarExample = ({ navigation }: Props) => { const theme = useExampleTheme(); const { bottom, left, right } = useSafeAreaInsets(); - const height = theme.isV3 ? 80 : 56; + const height = 80; const isCenterAlignedMode = appbarMode === 'center-aligned'; @@ -92,21 +91,14 @@ const AppbarExample = ({ navigation }: Props) => { showElevated, ]); - const TextComponent = theme.isV3 ? Text : Paragraph; - const renderFAB = () => { return ( {}} - style={[ - styles.fab, - theme.isV3 - ? { top: (height - MEDIUM_FAB_HEIGHT) / 2 } - : { bottom: height / 2 + bottom }, - ]} + style={[styles.fab, { top: (height - MEDIUM_FAB_HEIGHT) / 2 }]} /> ); }; @@ -114,49 +106,41 @@ const AppbarExample = ({ navigation }: Props) => { const renderDefaultOptions = () => ( <> - Left icon + Left icon - {!theme.isV3 && ( - - Subtitle - - - )} - Search icon + Subtitle + + + + Search icon - More icon + More icon - {theme.isV3 && ( - - Calendar icon - - - )} - Custom Color + Calendar icon + + + + Custom Color - {!theme.isV3 && ( - - Exact Dark Theme - - - )} - {theme.isV3 && ( - - Elevated - - - )} + + Exact Dark Theme + + + + Elevated + + ); @@ -166,40 +150,34 @@ const AppbarExample = ({ navigation }: Props) => { style={{ marginBottom: height + bottom }} contentContainerStyle={styles.contentContainer} > - {theme.isV3 ? ( - - {renderDefaultOptions()} - - ) : ( - renderDefaultOptions() - )} - {theme.isV3 && ( - - - setAppbarMode(value as AppbarModes) - } - > - - Small (default) - - - - Medium - - - - Large - - - - Center-aligned - - - - - )} + + {renderDefaultOptions()} + + + + setAppbarMode(value as AppbarModes) + } + > + + Small (default) + + + + Medium + + + + Large + + + + Center-aligned + + + + { { height: height + bottom, }, - theme.isV3 && { + { backgroundColor: theme.colors.elevation.level2, }, ]} @@ -218,9 +196,8 @@ const AppbarExample = ({ navigation }: Props) => { {}} /> {}} /> {}} /> - {theme.isV3 && renderFAB()} + {renderFAB()} - {!theme.isV3 && renderFAB()} setShowSnackbar(false)} @@ -258,6 +235,6 @@ const styles = StyleSheet.create({ right: 16, }, customColor: { - backgroundColor: yellowA200, + backgroundColor: MD3Colors.secondary80, }, }); diff --git a/example/src/Examples/AvatarExample.tsx b/example/src/Examples/AvatarExample.tsx index b77da80b09..229c2f4a0b 100644 --- a/example/src/Examples/AvatarExample.tsx +++ b/example/src/Examples/AvatarExample.tsx @@ -1,13 +1,11 @@ import * as React from 'react'; import { StyleSheet, View } from 'react-native'; -import { Avatar, List, MD2Colors, MD3Colors } from 'react-native-paper'; +import { Avatar, List, MD3Colors } from 'react-native-paper'; -import { useExampleTheme } from '../hooks/useExampleTheme'; import ScreenWrapper from '../ScreenWrapper'; const AvatarExample = () => { - const { isV3 } = useExampleTheme(); return ( @@ -16,11 +14,11 @@ const AvatarExample = () => { style={[ styles.avatar, { - backgroundColor: isV3 ? MD3Colors.error70 : MD2Colors.yellow500, + backgroundColor: MD3Colors.error70, }, ]} label="XD" - color={isV3 ? MD3Colors.primary0 : MD2Colors.black} + color={MD3Colors.primary0} /> @@ -32,11 +30,11 @@ const AvatarExample = () => { style={[ styles.avatar, { - backgroundColor: isV3 ? MD3Colors.error70 : MD2Colors.yellow500, + backgroundColor: MD3Colors.error70, }, ]} icon="folder" - color={isV3 ? MD3Colors.primary0 : MD2Colors.black} + color={MD3Colors.primary0} /> diff --git a/example/src/Examples/BadgeExample.tsx b/example/src/Examples/BadgeExample.tsx index 17f0e1b160..3269dc70a8 100644 --- a/example/src/Examples/BadgeExample.tsx +++ b/example/src/Examples/BadgeExample.tsx @@ -5,18 +5,15 @@ import { Badge, IconButton, List, - MD2Colors, MD3Colors, Text, Switch, } from 'react-native-paper'; -import { useExampleTheme } from '../hooks/useExampleTheme'; import ScreenWrapper from '../ScreenWrapper'; const BadgeExample = () => { const [visible, setVisible] = React.useState(true); - const { isV3 } = useExampleTheme(); return ( @@ -44,9 +41,7 @@ const BadgeExample = () => { style={[ styles.badge, { - backgroundColor: isV3 - ? MD3Colors.primary80 - : MD2Colors.blue500, + backgroundColor: MD3Colors.primary80, }, ]} > @@ -59,11 +54,11 @@ const BadgeExample = () => { - + - + diff --git a/example/src/Examples/BannerExample.tsx b/example/src/Examples/BannerExample.tsx index 0e856e9699..7ec874a283 100644 --- a/example/src/Examples/BannerExample.tsx +++ b/example/src/Examples/BannerExample.tsx @@ -8,7 +8,7 @@ import { View, } from 'react-native'; -import { Banner, FAB, MD2Colors, MD3Colors } from 'react-native-paper'; +import { Banner, FAB, MD3Colors } from 'react-native-paper'; import { useExampleTheme } from '../hooks/useExampleTheme'; import ScreenWrapper from '../ScreenWrapper'; @@ -29,25 +29,18 @@ const BannerExample = () => { setHeight(layoutHeight); }; - const customTheme = !defaultTheme.isV3 - ? { - ...defaultTheme, - colors: { - text: MD2Colors.white, - surface: MD2Colors.blue200, - primary: MD2Colors.purple900, - }, - } - : { - ...defaultTheme, - colors: { - onSurface: MD3Colors.tertiary100, - elevation: { - level1: MD3Colors.tertiary50, - }, - primary: MD3Colors.tertiary10, - }, - }; + const customTheme = { + ...defaultTheme, + colors: { + ...defaultTheme.colors, + onSurface: MD3Colors.tertiary100, + elevation: { + ...defaultTheme.colors.elevation, + level1: MD3Colors.tertiary50, + }, + primary: MD3Colors.tertiary10, + }, + }; return ( <> diff --git a/example/src/Examples/BottomNavigationExample.tsx b/example/src/Examples/BottomNavigationExample.tsx index 6ed5d7add5..419aca0f9d 100644 --- a/example/src/Examples/BottomNavigationExample.tsx +++ b/example/src/Examples/BottomNavigationExample.tsx @@ -17,7 +17,6 @@ import { } from 'react-native-paper'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; -import { useExampleTheme } from '../hooks/useExampleTheme'; import ScreenWrapper from '../ScreenWrapper'; type Route = { route: { key: string } }; @@ -49,7 +48,6 @@ const PhotoGallery = ({ route }: Route) => { }; const BottomNavigationExample = ({ navigation }: Props) => { - const { isV3 } = useExampleTheme(); const insets = useSafeAreaInsets(); const [index, setIndex] = React.useState(0); const [menuVisible, setMenuVisible] = React.useState(false); @@ -63,34 +61,25 @@ const BottomNavigationExample = ({ navigation }: Props) => { key: 'album', title: 'Album', focusedIcon: 'image-album', - ...(!isV3 && { color: '#6200ee' }), }, { key: 'library', title: 'Library', focusedIcon: 'inbox', + unfocusedIcon: 'inbox-outline', badge: true, - ...(isV3 - ? { unfocusedIcon: 'inbox-outline' } - : { - color: '#2962ff', - }), }, { key: 'favorites', title: 'Favorites', focusedIcon: 'heart', - ...(isV3 - ? { unfocusedIcon: 'heart-outline' } - : { - color: '#00796b', - }), + unfocusedIcon: 'heart-outline', }, { key: 'purchased', title: 'Purchased', focusedIcon: 'shopping', - ...(isV3 ? { unfocusedIcon: 'shopping-outline' } : { color: '#c51162' }), + unfocusedIcon: 'shopping-outline', }, ]); @@ -112,7 +101,6 @@ const BottomNavigationExample = ({ navigation }: Props) => { setMenuVisible(true)} - {...(!isV3 && { color: 'white' })} /> } > diff --git a/example/src/Examples/ButtonExample.tsx b/example/src/Examples/ButtonExample.tsx index 7ec58f90f4..c6ecc56d09 100644 --- a/example/src/Examples/ButtonExample.tsx +++ b/example/src/Examples/ButtonExample.tsx @@ -9,11 +9,11 @@ import ScreenWrapper from '../ScreenWrapper'; const ButtonExample = () => { const theme = useExampleTheme(); - const color = theme.isV3 ? theme.colors.inversePrimary : theme.colors.accent; + const color = theme.colors.inversePrimary; return ( - + - {theme.isV3 && ( - - - - - - - - - - - )} - + + + + + + + + + + + - + - {theme.isV3 && ( - - - - - - - - - - - )} + + + + + + + + + + diff --git a/example/src/Examples/CheckboxExample.tsx b/example/src/Examples/CheckboxExample.tsx index c8ce8c23a7..06088a646a 100644 --- a/example/src/Examples/CheckboxExample.tsx +++ b/example/src/Examples/CheckboxExample.tsx @@ -1,16 +1,8 @@ import * as React from 'react'; import { StyleSheet, View } from 'react-native'; -import { - Checkbox, - MD2Colors, - MD3Colors, - Paragraph, - Text, - TouchableRipple, -} from 'react-native-paper'; +import { Checkbox, MD3Colors, Text, TouchableRipple } from 'react-native-paper'; -import { useExampleTheme } from '../hooks/useExampleTheme'; import ScreenWrapper from '../ScreenWrapper'; const CheckboxExample = () => { @@ -18,14 +10,11 @@ const CheckboxExample = () => { const [checkedCustom, setCheckedCustom] = React.useState(true); const [indeterminate, setIndeterminate] = React.useState(true); - const { isV3 } = useExampleTheme(); - const TextComponent = isV3 ? Text : Paragraph; - return ( setCheckedNormal(!checkedNormal)}> - Normal + Normal @@ -34,10 +23,10 @@ const CheckboxExample = () => { setCheckedCustom(!checkedCustom)}> - Custom + Custom @@ -46,7 +35,7 @@ const CheckboxExample = () => { setIndeterminate(!indeterminate)}> - Indeterminate + Indeterminate @@ -54,15 +43,15 @@ const CheckboxExample = () => { - Checked (Disabled) + Checked (Disabled) - Unchecked (Disabled) + Unchecked (Disabled) - Indeterminate (Disabled) + Indeterminate (Disabled) diff --git a/example/src/Examples/ChipExample.tsx b/example/src/Examples/ChipExample.tsx index 20f0393153..211ebfde49 100644 --- a/example/src/Examples/ChipExample.tsx +++ b/example/src/Examples/ChipExample.tsx @@ -2,16 +2,8 @@ import * as React from 'react'; import { Image, StyleSheet, View } from 'react-native'; import color from 'color'; -import { - Chip, - List, - MD2Colors, - MD3Colors, - Snackbar, - Text, -} from 'react-native-paper'; +import { Chip, List, MD3Colors, Snackbar, Text } from 'react-native-paper'; -import { useExampleTheme } from '../hooks/useExampleTheme'; import ScreenWrapper from '../ScreenWrapper'; const ChipExample = () => { @@ -19,8 +11,7 @@ const ChipExample = () => { visible: false, text: '', }); - const { isV3 } = useExampleTheme(); - const customColor = isV3 ? MD3Colors.error50 : MD2Colors.purple900; + const customColor = MD3Colors.error50; return ( <> @@ -30,24 +21,20 @@ const ChipExample = () => { {}} style={styles.chip}> Simple - {isV3 && ( - <> - {}} - style={styles.chip} - > - With selected overlay - - {}} style={styles.chip}> - Elevated - - {}}> - Compact chip - - - )} + {}} + style={styles.chip} + > + With selected overlay + + {}} style={styles.chip}> + Elevated + + {}}> + Compact chip + {}} onClose={() => @@ -137,35 +124,31 @@ const ChipExample = () => { {}} style={styles.chip}> Simple - {isV3 && ( - <> - {}} - style={styles.chip} - > - With selected overlay - - {}} - style={styles.chip} - > - Elevated - - {}} - style={styles.chip} - > - Compact chip - - - )} + {}} + style={styles.chip} + > + With selected overlay + + {}} + style={styles.chip} + > + Elevated + + {}} + style={styles.chip} + > + Compact chip + {}} @@ -251,38 +234,34 @@ const ChipExample = () => { - {isV3 && ( - <> - {}} - compact - avatar={ - - } - style={[styles.chip, styles.customBorderRadius]} - > - Compact with custom border radius - - {}} - compact - avatar={ - - } - style={[styles.chip, styles.customBorderRadius]} - > - Compact with custom border radius - - - )} + {}} + compact + avatar={ + + } + style={[styles.chip, styles.customBorderRadius]} + > + Compact with custom border radius + + {}} + compact + avatar={ + + } + style={[styles.chip, styles.customBorderRadius]} + > + Compact with custom border radius + {}} diff --git a/example/src/Examples/Dialogs/DialogWithCustomColors.tsx b/example/src/Examples/Dialogs/DialogWithCustomColors.tsx index 251b7b6fdb..e3bffafd60 100644 --- a/example/src/Examples/Dialogs/DialogWithCustomColors.tsx +++ b/example/src/Examples/Dialogs/DialogWithCustomColors.tsx @@ -1,15 +1,8 @@ import * as React from 'react'; -import { - Button, - Portal, - Dialog, - MD2Colors, - MD3Colors, -} from 'react-native-paper'; +import { Button, Portal, Dialog, MD3Colors } from 'react-native-paper'; import { TextComponent } from './DialogTextComponent'; -import { useExampleTheme } from '../../hooks/useExampleTheme'; const DialogWithCustomColors = ({ visible, @@ -18,34 +11,25 @@ const DialogWithCustomColors = ({ visible: boolean; close: () => void; }) => { - const { isV3 } = useExampleTheme(); - return ( - + Alert - + This is a dialog with custom colors - diff --git a/example/src/Examples/Dialogs/DialogWithDismissableBackButton.tsx b/example/src/Examples/Dialogs/DialogWithDismissableBackButton.tsx index 32512dc91d..261b7ff9e6 100644 --- a/example/src/Examples/Dialogs/DialogWithDismissableBackButton.tsx +++ b/example/src/Examples/Dialogs/DialogWithDismissableBackButton.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; -import { Button, Portal, Dialog, MD2Colors } from 'react-native-paper'; +import { Button, Portal, Dialog, MD3Colors } from 'react-native-paper'; import { TextComponent } from './DialogTextComponent'; @@ -26,7 +26,7 @@ const DialogWithDismissableBackButton = ({ - diff --git a/example/src/Examples/Dialogs/DialogWithLoadingIndicator.tsx b/example/src/Examples/Dialogs/DialogWithLoadingIndicator.tsx index 5ef9e7e7f2..5860737e3e 100644 --- a/example/src/Examples/Dialogs/DialogWithLoadingIndicator.tsx +++ b/example/src/Examples/Dialogs/DialogWithLoadingIndicator.tsx @@ -1,10 +1,9 @@ import * as React from 'react'; import { ActivityIndicator, Platform, StyleSheet, View } from 'react-native'; -import { Dialog, MD2Colors, MD3Colors, Portal } from 'react-native-paper'; +import { Dialog, MD3Colors, Portal } from 'react-native-paper'; import { TextComponent } from './DialogTextComponent'; -import { useExampleTheme } from '../../hooks/useExampleTheme'; const isIOS = Platform.OS === 'ios'; @@ -15,7 +14,6 @@ const DialogWithLoadingIndicator = ({ visible: boolean; close: () => void; }) => { - const { isV3 } = useExampleTheme(); return ( @@ -23,7 +21,7 @@ const DialogWithLoadingIndicator = ({ diff --git a/example/src/Examples/Dialogs/UndismissableDialog.tsx b/example/src/Examples/Dialogs/UndismissableDialog.tsx index 2af40f4e97..ded4896fe2 100644 --- a/example/src/Examples/Dialogs/UndismissableDialog.tsx +++ b/example/src/Examples/Dialogs/UndismissableDialog.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; -import { Button, Portal, Dialog, MD2Colors } from 'react-native-paper'; +import { Button, Portal, Dialog, MD3Colors } from 'react-native-paper'; import { TextComponent } from './DialogTextComponent'; @@ -18,7 +18,7 @@ const UndismissableDialog = ({ This is an undismissable dialog!! - diff --git a/example/src/Examples/IconButtonExample.tsx b/example/src/Examples/IconButtonExample.tsx index 6342b1e144..a2ac7e72db 100644 --- a/example/src/Examples/IconButtonExample.tsx +++ b/example/src/Examples/IconButtonExample.tsx @@ -1,36 +1,11 @@ import * as React from 'react'; import { StyleSheet, View } from 'react-native'; -import { IconButton, List, MD2Colors, MD3Colors } from 'react-native-paper'; +import { IconButton, List, MD3Colors } from 'react-native-paper'; -import { useExampleTheme } from '../hooks/useExampleTheme'; import ScreenWrapper from '../ScreenWrapper'; const ButtonExample = () => { - const { isV3 } = useExampleTheme(); - if (!isV3) { - return ( - - {}} /> - {}} - /> - {}} loading /> - {}} /> - {}} - style={{ backgroundColor: MD2Colors.lightGreen200 }} - /> - {}} /> - - ); - } - return ( @@ -200,10 +175,6 @@ const ButtonExample = () => { ButtonExample.title = 'Icon Button'; const styles = StyleSheet.create({ - v2Container: { - flexDirection: 'row', - padding: 8, - }, v3Container: { flexDirection: 'column', }, diff --git a/example/src/Examples/MenuExample.tsx b/example/src/Examples/MenuExample.tsx index c1164d35b6..b43fb04778 100644 --- a/example/src/Examples/MenuExample.tsx +++ b/example/src/Examples/MenuExample.tsx @@ -16,7 +16,6 @@ import { TouchableRipple, } from 'react-native-paper'; -import { useExampleTheme } from '../hooks/useExampleTheme'; import ScreenWrapper from '../ScreenWrapper'; type ContextualMenuCoord = { x: number; y: number }; @@ -35,8 +34,6 @@ const MenuExample = ({ navigation }: Props) => { const [visible, setVisible] = React.useState({}); const [contextualMenuCoord, setContextualMenuCoor] = React.useState({ x: 0, y: 0 }); - const { isV3 } = useExampleTheme(); - const _toggleMenu = (name: string) => () => setVisible({ ...visible, [name]: !visible[name] }); @@ -66,16 +63,12 @@ const MenuExample = ({ navigation }: Props) => { visible={_getVisible('menu1')} onDismiss={_toggleMenu('menu1')} anchor={ - + } > {}} title="Undo" /> {}} title="Redo" /> - + {}} title="Cut" disabled /> {}} title="Copy" disabled /> {}} title="Paste" /> @@ -99,7 +92,7 @@ const MenuExample = ({ navigation }: Props) => { {}} title="Undo" /> {}} title="Redo" /> - + { onPress={() => {}} title="Paste" /> - {isV3 && ( - {}} - title="Share" - /> - )} + {}} + title="Share" + /> { > {}} title="Item 1" /> {}} title="Item 2" /> - + {}} title="Item 3" disabled /> diff --git a/example/src/Examples/ProgressBarExample.tsx b/example/src/Examples/ProgressBarExample.tsx index 565147f4c6..5ab797bb1d 100644 --- a/example/src/Examples/ProgressBarExample.tsx +++ b/example/src/Examples/ProgressBarExample.tsx @@ -4,7 +4,6 @@ import { View, StyleSheet, Animated } from 'react-native'; import { Button, ProgressBar, - MD2Colors, MD3Colors, ProgressBarProps, Text, @@ -29,7 +28,6 @@ const ProgressBarExample = () => { const [visible, setVisible] = React.useState(true); const [progress, setProgress] = React.useState(0.3); const theme = useExampleTheme(); - const { isV3 } = theme; const { current: progressBarValue } = React.useRef(new Animated.Value(0)); const runCustomAnimation = () => { @@ -64,7 +62,7 @@ const ProgressBarExample = () => { @@ -75,9 +73,9 @@ const ProgressBarExample = () => { diff --git a/example/src/Examples/RadioButtonExample.tsx b/example/src/Examples/RadioButtonExample.tsx index 88bf9ebfb7..7e3b3cf754 100644 --- a/example/src/Examples/RadioButtonExample.tsx +++ b/example/src/Examples/RadioButtonExample.tsx @@ -2,29 +2,24 @@ import * as React from 'react'; import { StyleSheet, View } from 'react-native'; import { - MD2Colors, MD3Colors, - Paragraph, RadioButton, Text, TouchableRipple, } from 'react-native-paper'; -import { useExampleTheme } from '../hooks/useExampleTheme'; import ScreenWrapper from '../ScreenWrapper'; type State = 'normal' | 'normal-ios' | 'normal-item' | 'custom'; const RadioButtonExample = () => { const [checked, setChecked] = React.useState('normal'); - const { isV3 } = useExampleTheme(); - const TextComponent = isV3 ? Text : Paragraph; return ( setChecked('normal')}> - Normal - Material Design + Normal - Material Design { setChecked('normal-ios')}> - Normal 2 - IOS + Normal 2 - IOS { setChecked('custom')}> - Custom + Custom @@ -63,11 +58,11 @@ const RadioButtonExample = () => { onPress={() => setChecked('normal-item')} /> - Checked (Disabled) + Checked (Disabled) - Unchecked (Disabled) + Unchecked (Disabled) { const [valueNormal, setNormalValue] = React.useState(true); const [valueCustom, setCustomValue] = React.useState(true); - const { isV3 } = useExampleTheme(); - const switchValueNormalLabel = `switch ${ valueNormal === true ? 'on' : 'off' }`; @@ -26,13 +16,11 @@ const SwitchExample = () => { valueCustom === true ? 'on' : 'off' }`; - const TextComponent = isV3 ? Text : Paragraph; - return Platform.OS === 'android' ? ( setNormalValue(!valueNormal)}> - Normal {switchValueNormalLabel} + Normal {switchValueNormalLabel} @@ -40,47 +28,44 @@ const SwitchExample = () => { setCustomValue(!valueCustom)}> - Custom {switchValueCustomlLabel} + Custom {switchValueCustomlLabel} - + - Switch on (disabled) + Switch on (disabled) - Switch off (disabled) + Switch off (disabled) ) : ( - Normal {switchValueNormalLabel} + Normal {switchValueNormalLabel} setNormalValue(!valueNormal)} /> - Custom {switchValueCustomlLabel} + Custom {switchValueCustomlLabel} setCustomValue(!valueCustom)} - color={isV3 ? MD3Colors.tertiary50 : MD2Colors.blue500} + color={MD3Colors.tertiary50} /> - Switch on (disabled) + Switch on (disabled) - Switch off (disabled) + Switch off (disabled) diff --git a/example/src/Examples/TextInputExample.tsx b/example/src/Examples/TextInputExample.tsx index 7102abd0b6..37c039ba13 100644 --- a/example/src/Examples/TextInputExample.tsx +++ b/example/src/Examples/TextInputExample.tsx @@ -13,7 +13,6 @@ import { configureFonts, HelperText, List, - MD2Colors, MD3Colors, TextInput, } from 'react-native-paper'; @@ -138,11 +137,7 @@ const TextInputExample = () => { const newColors = { ...state.iconsColor, - [name]: !color - ? theme.isV3 - ? theme.colors.primary - : theme.colors?.accent - : undefined, + [name]: !color ? theme.colors.primary : undefined, }; dispatch({ @@ -572,9 +567,7 @@ const TextInputExample = () => { * @@ -604,12 +597,8 @@ const TextInputExample = () => { onChangeText={(flatUnderlineColors) => inputActionHandler('flatUnderlineColors', flatUnderlineColors) } - underlineColor={ - theme.isV3 ? MD3Colors.primary70 : MD2Colors.pink400 - } - activeUnderlineColor={ - theme.isV3 ? MD3Colors.tertiary50 : MD2Colors.amber900 - } + underlineColor={MD3Colors.primary70} + activeUnderlineColor={MD3Colors.tertiary50} /> { onChangeText={(outlinedColors) => inputActionHandler('outlinedColors', outlinedColors) } - outlineColor={ - theme.isV3 ? MD3Colors.primary70 : MD2Colors.pink400 - } - activeOutlineColor={ - theme.isV3 ? MD3Colors.tertiary50 : MD2Colors.amber900 - } + outlineColor={MD3Colors.primary70} + activeOutlineColor={MD3Colors.tertiary50} /> void; toggleRtl: () => void; - toggleThemeVersion: () => void; toggleCollapsed: () => void; toggleCustomFont: () => void; toggleRippleEffect: () => void; toggleShouldUseDeviceColors?: () => void; - theme: MD2Theme | MD3Theme; + theme: MD3Theme; rtl: boolean; collapsed: boolean; customFontLoaded: boolean; diff --git a/example/src/hooks/useExampleTheme.ts b/example/src/hooks/useExampleTheme.ts index 9196f044b0..059ab4d05c 100644 --- a/example/src/hooks/useExampleTheme.ts +++ b/example/src/hooks/useExampleTheme.ts @@ -1,3 +1,3 @@ -import { MD2Theme, MD3Theme, useTheme } from 'react-native-paper'; +import { useTheme, type MD3Theme } from 'react-native-paper'; -export const useExampleTheme = () => useTheme(); +export const useExampleTheme = () => useTheme(); diff --git a/example/src/index.native.tsx b/example/src/index.native.tsx index 0878a1f13b..70d712816b 100644 --- a/example/src/index.native.tsx +++ b/example/src/index.native.tsx @@ -9,13 +9,7 @@ import { useFonts } from 'expo-font'; import { useKeepAwake } from 'expo-keep-awake'; import { StatusBar } from 'expo-status-bar'; import * as Updates from 'expo-updates'; -import { - PaperProvider, - MD2DarkTheme, - MD2LightTheme, - MD3DarkTheme, - MD3LightTheme, -} from 'react-native-paper'; +import { PaperProvider, MD3DarkTheme, MD3LightTheme } from 'react-native-paper'; import { SafeAreaInsetsContext } from 'react-native-safe-area-context'; import DrawerItems from './DrawerItems'; @@ -49,7 +43,6 @@ export default function PaperExample() { const [shouldUseDeviceColors, setShouldUseDeviceColors] = React.useState(true); const [isDarkMode, setIsDarkMode] = React.useState(false); - const [themeVersion, setThemeVersion] = React.useState<2 | 3>(3); const [rtl, setRtl] = React.useState( I18nManager.getConstants().isRTL ); @@ -59,10 +52,6 @@ export default function PaperExample() { const { theme: mdTheme } = useMaterial3Theme(); const theme = React.useMemo(() => { - if (themeVersion === 2) { - return isDarkMode ? MD2DarkTheme : MD2LightTheme; - } - if (!deviceColorsSupported || !shouldUseDeviceColors) { return isDarkMode ? MD3DarkTheme : MD3LightTheme; } @@ -70,7 +59,7 @@ export default function PaperExample() { return isDarkMode ? { ...MD3DarkTheme, colors: mdTheme.dark } : { ...MD3LightTheme, colors: mdTheme.light }; - }, [isDarkMode, mdTheme, shouldUseDeviceColors, themeVersion]); + }, [isDarkMode, mdTheme, shouldUseDeviceColors]); React.useEffect(() => { const restoreState = async () => { @@ -144,12 +133,6 @@ export default function PaperExample() { toggleCollapsed: () => setCollapsed(!collapsed), toggleCustomFont: () => setCustomFont(!customFontLoaded), toggleRippleEffect: () => setRippleEffectEnabled(!rippleEffectEnabled), - toggleThemeVersion: () => { - setCustomFont(false); - setCollapsed(false); - setThemeVersion((oldThemeVersion) => (oldThemeVersion === 2 ? 3 : 2)); - setRippleEffectEnabled(true); - }, customFontLoaded, rippleEffectEnabled, collapsed, diff --git a/example/src/index.tsx b/example/src/index.tsx index 76607763f1..4395d2d55e 100644 --- a/example/src/index.tsx +++ b/example/src/index.tsx @@ -5,13 +5,7 @@ import { createDrawerNavigator } from '@react-navigation/drawer'; import { InitialState, NavigationContainer } from '@react-navigation/native'; import { useFonts } from 'expo-font'; import { useKeepAwake } from 'expo-keep-awake'; -import { - PaperProvider, - MD3DarkTheme, - MD3LightTheme, - MD2DarkTheme, - MD2LightTheme, -} from 'react-native-paper'; +import { PaperProvider, MD3DarkTheme, MD3LightTheme } from 'react-native-paper'; import { SafeAreaInsetsContext } from 'react-native-safe-area-context'; import DrawerItems from './DrawerItems'; @@ -43,18 +37,14 @@ export default function PaperExample() { >(); const [isDarkMode, setIsDarkMode] = React.useState(false); - const [themeVersion, setThemeVersion] = React.useState<2 | 3>(3); const [collapsed, setCollapsed] = React.useState(false); const [customFontLoaded, setCustomFont] = React.useState(false); const [rippleEffectEnabled, setRippleEffectEnabled] = React.useState(true); - const theme = React.useMemo(() => { - if (themeVersion === 2) { - return isDarkMode ? MD2DarkTheme : MD2LightTheme; - } - - return isDarkMode ? MD3DarkTheme : MD3LightTheme; - }, [isDarkMode, themeVersion]); + const theme = React.useMemo( + () => (isDarkMode ? MD3DarkTheme : MD3LightTheme), + [isDarkMode] + ); React.useEffect(() => { const restoreState = async () => { @@ -112,12 +102,6 @@ export default function PaperExample() { const preferences = React.useMemo( () => ({ toggleTheme: () => setIsDarkMode((oldValue) => !oldValue), - toggleThemeVersion: () => { - setCustomFont(false); - setCollapsed(false); - setThemeVersion((oldThemeVersion) => (oldThemeVersion === 2 ? 3 : 2)); - setRippleEffectEnabled(true); - }, toggleCollapsed: () => setCollapsed(!collapsed), toggleCustomFont: () => setCustomFont(!customFontLoaded), toggleRippleEffect: () => setRippleEffectEnabled(!rippleEffectEnabled), From 2133b89c15f41a63d6b3d4b8d515cb26e1a1dbf7 Mon Sep 17 00:00:00 2001 From: Adrian Cotfas Date: Mon, 13 Apr 2026 11:29:39 +0300 Subject: [PATCH 04/13] fix: pre-commit hook lint issues --- example/src/Examples/IconButtonExample.tsx | 5 ++++- example/src/index.native.tsx | 2 +- src/components/BottomNavigation/BottomNavigation.tsx | 2 -- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/example/src/Examples/IconButtonExample.tsx b/example/src/Examples/IconButtonExample.tsx index a2ac7e72db..2b90a4ebd4 100644 --- a/example/src/Examples/IconButtonExample.tsx +++ b/example/src/Examples/IconButtonExample.tsx @@ -137,7 +137,7 @@ const ButtonExample = () => { mode="contained" style={styles.slightlyRounded} size={24} - contentStyle={{ padding: 8 }} + contentStyle={styles.contentPadding} iconColor={MD3Colors.tertiary50} onPress={() => {}} /> @@ -190,6 +190,9 @@ const styles = StyleSheet.create({ width: 48, height: 48, }, + contentPadding: { + padding: 8, + }, differentBorderRadius: { borderTopLeftRadius: 2, borderTopRightRadius: 4, diff --git a/example/src/index.native.tsx b/example/src/index.native.tsx index 70d712816b..fae347d85d 100644 --- a/example/src/index.native.tsx +++ b/example/src/index.native.tsx @@ -13,9 +13,9 @@ import { PaperProvider, MD3DarkTheme, MD3LightTheme } from 'react-native-paper'; import { SafeAreaInsetsContext } from 'react-native-safe-area-context'; import DrawerItems from './DrawerItems'; +import { PreferencesContext } from './PreferencesContext'; import App from './RootNavigator'; import { deviceColorsSupported } from '../utils'; -import { PreferencesContext } from './PreferencesContext'; import { CombinedDefaultTheme, CombinedDarkTheme, diff --git a/src/components/BottomNavigation/BottomNavigation.tsx b/src/components/BottomNavigation/BottomNavigation.tsx index 54df09d236..da764929ee 100644 --- a/src/components/BottomNavigation/BottomNavigation.tsx +++ b/src/components/BottomNavigation/BottomNavigation.tsx @@ -423,13 +423,11 @@ const BottomNavigation = ({ }); }, [ - shifting, navigationState.routes, offsetsAnims, scale, tabsPositionAnims, sceneAnimationEasing, - theme, ] ); From 5a6ec84bfb24a612352fd0c809c67fde07c135c7 Mon Sep 17 00:00:00 2001 From: Adrian Cotfas Date: Tue, 14 Apr 2026 16:32:50 +0300 Subject: [PATCH 05/13] fix: ripple not showing on majority of components --- .../TouchableRipple/TouchableRipple.native.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/components/TouchableRipple/TouchableRipple.native.tsx b/src/components/TouchableRipple/TouchableRipple.native.tsx index 1cb17b4068..3f8c791c33 100644 --- a/src/components/TouchableRipple/TouchableRipple.native.tsx +++ b/src/components/TouchableRipple/TouchableRipple.native.tsx @@ -73,12 +73,13 @@ const TouchableRipple = ( underlayColor, }); - // A workaround for ripple on Android P is to use useForeground + overflow: 'hidden' + // Use foreground ripple on Android P+ to ensure visibility. + // Background ripple requires the view to have a background drawable, + // which isn't always present. Foreground ripple needs overflow: 'hidden' + // to stay within bounds. // https://github.com/facebook/react-native/issues/6480 const useForeground = - Platform.OS === 'android' && - Platform.Version >= ANDROID_VERSION_PIE && - borderless; + Platform.OS === 'android' && Platform.Version >= ANDROID_VERSION_PIE; if (TouchableRipple.supported) { const androidRipple = rippleEffectEnabled @@ -94,7 +95,7 @@ const TouchableRipple = ( {...rest} ref={ref} disabled={disabled} - style={[borderless && styles.overflowHidden, style]} + style={[useForeground && styles.overflowHidden, style]} android_ripple={androidRipple} > {React.Children.only(children)} From ac4e178def27078a1b8640b3f8b3477a63977548 Mon Sep 17 00:00:00 2001 From: Adrian Cotfas Date: Mon, 13 Apr 2026 11:29:39 +0300 Subject: [PATCH 06/13] feat: remove customRippleColor from components * fixes #4894 --- src/components/Appbar/AppbarAction.tsx | 14 +------ src/components/Button/Button.tsx | 12 ------ src/components/Checkbox/CheckboxItem.tsx | 7 ---- src/components/Chip/Chip.tsx | 9 ---- src/components/Chip/helpers.tsx | 39 ----------------- .../DataTable/DataTablePagination.tsx | 26 ------------ src/components/Drawer/DrawerItem.tsx | 10 ----- src/components/FAB/AnimatedFAB.tsx | 12 ------ src/components/FAB/FAB.tsx | 10 +---- src/components/FAB/FABGroup.tsx | 10 ----- src/components/FAB/utils.ts | 4 -- src/components/IconButton/IconButton.tsx | 26 ++++-------- src/components/IconButton/utils.ts | 20 --------- src/components/List/ListAccordion.tsx | 10 +---- src/components/List/utils.ts | 9 +--- src/components/Menu/MenuItem.tsx | 10 +---- src/components/Menu/utils.ts | 26 +----------- .../RadioButton/RadioButtonItem.tsx | 7 ---- src/components/Searchbar.tsx | 31 ++------------ .../SegmentedButtons/SegmentedButtonItem.tsx | 11 ----- src/components/Snackbar.tsx | 13 +----- .../TextInput/Adornment/TextInputIcon.tsx | 7 ---- src/components/ToggleButton/ToggleButton.tsx | 7 ---- src/components/TouchableRipple/utils.ts | 2 +- src/components/__tests__/Chip.test.tsx | 42 ------------------- src/components/__tests__/FABGroup.test.tsx | 31 -------------- src/components/__tests__/IconButton.test.tsx | 16 ------- .../__tests__/ListAccordion.test.tsx | 27 ------------ src/components/__tests__/MenuItem.test.tsx | 16 ------- src/components/__tests__/Searchbar.test.tsx | 36 ---------------- src/components/__tests__/Snackbar.test.tsx | 17 -------- .../__tests__/ToggleButton.test.tsx | 16 ------- 32 files changed, 20 insertions(+), 513 deletions(-) diff --git a/src/components/Appbar/AppbarAction.tsx b/src/components/Appbar/AppbarAction.tsx index 14982cbecb..212fcca952 100644 --- a/src/components/Appbar/AppbarAction.tsx +++ b/src/components/Appbar/AppbarAction.tsx @@ -1,11 +1,5 @@ import * as React from 'react'; -import type { - Animated, - ColorValue, - StyleProp, - View, - ViewStyle, -} from 'react-native'; +import type { Animated, StyleProp, View, ViewStyle } from 'react-native'; import type { ThemeProp } from 'src/types'; @@ -20,10 +14,6 @@ export type Props = React.ComponentPropsWithoutRef & { * Custom color for action icon. */ color?: string; - /** - * Color of the ripple effect. - */ - rippleColor?: ColorValue; /** * Name of the icon to show. */ @@ -91,7 +81,6 @@ const AppbarAction = forwardRef( accessibilityLabel, isLeading, theme: themeOverrides, - rippleColor, ...rest }: Props, ref @@ -115,7 +104,6 @@ const AppbarAction = forwardRef( accessibilityLabel={accessibilityLabel} animated ref={ref} - rippleColor={rippleColor} {...rest} /> ); diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx index 1d1d0d3002..516ff915f7 100644 --- a/src/components/Button/Button.tsx +++ b/src/components/Button/Button.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import { AccessibilityRole, Animated, - ColorValue, GestureResponderEvent, Platform, PressableAndroidRippleConfig, @@ -13,8 +12,6 @@ import { ViewStyle, } from 'react-native'; -import color from 'color'; - import { ButtonMode, getButtonColors, @@ -66,10 +63,6 @@ export type Props = $Omit, 'mode'> & { * Custom button's text color. */ textColor?: string; - /** - * Color of the ripple effect. - */ - rippleColor?: ColorValue; /** * Whether to show a loading indicator. */ @@ -186,7 +179,6 @@ const Button = ( icon, buttonColor: customButtonColor, textColor: customTextColor, - rippleColor: customRippleColor, children, accessibilityLabel, accessibilityHint, @@ -292,9 +284,6 @@ const Button = ( dark, }); - const rippleColor = - customRippleColor || color(textColor).alpha(0.12).rgb().string(); - const touchableStyle = { ...borderRadiusStyles, borderRadius: borderRadiusStyles.borderRadius ?? borderRadius, @@ -363,7 +352,6 @@ const Button = ( accessible={accessible} hitSlop={hitSlop} disabled={disabled} - rippleColor={rippleColor} style={getButtonTouchableRippleStyle(touchableStyle, borderWidth)} testID={testID} theme={theme} diff --git a/src/components/Checkbox/CheckboxItem.tsx b/src/components/Checkbox/CheckboxItem.tsx index 869edd674a..45e86bcced 100644 --- a/src/components/Checkbox/CheckboxItem.tsx +++ b/src/components/Checkbox/CheckboxItem.tsx @@ -1,6 +1,5 @@ import * as React from 'react'; import { - ColorValue, GestureResponderEvent, PressableAndroidRippleConfig, StyleProp, @@ -58,10 +57,6 @@ export type Props = { * Custom color for checkbox. */ color?: string; - /** - * Color of the ripple effect. - */ - rippleColor?: ColorValue; /** * Additional styles for container View. */ @@ -148,7 +143,6 @@ const CheckboxItem = ({ disabled, labelVariant = 'bodyLarge', labelMaxFontSizeMultiplier = 1.5, - rippleColor, background, hitSlop, ...props @@ -187,7 +181,6 @@ const CheckboxItem = ({ onLongPress={onLongPress} testID={testID} disabled={disabled} - rippleColor={rippleColor} theme={theme} background={background} hitSlop={hitSlop} diff --git a/src/components/Chip/Chip.tsx b/src/components/Chip/Chip.tsx index 3706239b71..012cac4fc1 100644 --- a/src/components/Chip/Chip.tsx +++ b/src/components/Chip/Chip.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import { AccessibilityState, Animated, - ColorValue, GestureResponderEvent, Platform, PressableAndroidRippleConfig, @@ -73,10 +72,6 @@ export type Props = $Omit, 'mode'> & { * Note: Check will not be shown if `icon` is specified. If specified, `icon` will be shown regardless of `selected`. */ showSelectedCheck?: boolean; - /** - * Color of the ripple effect. - */ - rippleColor?: ColorValue; /** * Whether the chip is disabled. A disabled chip is greyed out and `onPress` is not called on touch. */ @@ -201,7 +196,6 @@ const Chip = ({ theme: themeOverrides, testID = 'chip', selectedColor, - rippleColor: customRippleColor, showSelectedOverlay = false, showSelectedCheck = true, ellipsizeMode, @@ -263,7 +257,6 @@ const Chip = ({ borderColor, textColor, iconColor, - rippleColor, selectedBackgroundColor, backgroundColor, } = getChipColors({ @@ -273,7 +266,6 @@ const Chip = ({ showSelectedOverlay, customBackgroundColor, disabled, - customRippleColor, }); const accessibilityState: AccessibilityState = { @@ -324,7 +316,6 @@ const Chip = ({ onPressIn={hasPassedTouchHandler ? handlePressIn : undefined} onPressOut={hasPassedTouchHandler ? handlePressOut : undefined} delayLongPress={delayLongPress} - rippleColor={rippleColor} disabled={disabled} accessibilityLabel={accessibilityLabel} accessibilityRole={accessibilityRole} diff --git a/src/components/Chip/helpers.tsx b/src/components/Chip/helpers.tsx index 7c654a22f6..0f191b2ac0 100644 --- a/src/components/Chip/helpers.tsx +++ b/src/components/Chip/helpers.tsx @@ -171,37 +171,6 @@ const getIconColor = ({ return colors.onSecondaryContainer; }; -const getRippleColor = ({ - theme, - isOutlined, - disabled, - selectedColor, - selectedBackgroundColor: _selectedBackgroundColor, - customRippleColor, -}: BaseProps & { - selectedBackgroundColor: string; - selectedColor?: string; - customRippleColor?: ColorValue; -}) => { - if (customRippleColor) { - return customRippleColor; - } - - const isSelectedColor = selectedColor !== undefined; - const textColor = getTextColor({ - theme, - disabled, - selectedColor, - isOutlined, - }); - - if (isSelectedColor) { - return color(selectedColor).alpha(0.12).rgb().string(); - } - - return color(textColor).alpha(0.12).rgb().string(); -}; - export const getChipColors = ({ isOutlined, theme, @@ -209,13 +178,11 @@ export const getChipColors = ({ showSelectedOverlay, customBackgroundColor, disabled, - customRippleColor, }: BaseProps & { customBackgroundColor?: ColorValue; disabled?: boolean; showSelectedOverlay?: boolean; selectedColor?: string; - customRippleColor?: ColorValue; }) => { const baseChipColorProps = { theme, isOutlined, disabled }; @@ -244,12 +211,6 @@ export const getChipColors = ({ ...baseChipColorProps, selectedColor, }), - rippleColor: getRippleColor({ - ...baseChipColorProps, - selectedColor, - selectedBackgroundColor, - customRippleColor, - }), backgroundColor, selectedBackgroundColor, }; diff --git a/src/components/DataTable/DataTablePagination.tsx b/src/components/DataTable/DataTablePagination.tsx index c7a5375f82..6e2612973e 100644 --- a/src/components/DataTable/DataTablePagination.tsx +++ b/src/components/DataTable/DataTablePagination.tsx @@ -1,6 +1,5 @@ import * as React from 'react'; import { - ColorValue, I18nManager, StyleProp, StyleSheet, @@ -57,14 +56,6 @@ type PaginationDropdownProps = { * The function to set the number of rows per page. */ onItemsPerPageChange?: (numberOfItemsPerPage: number) => void; - /** - * Color of the dropdown item ripple effect. - */ - dropdownItemRippleColor?: ColorValue; - /** - * Color of the select page dropdown ripple effect. - */ - selectPageDropdownRippleColor?: ColorValue; /** * @optional */ @@ -88,10 +79,6 @@ type PaginationControlsProps = { * Whether to show fast forward and fast rewind buttons in pagination. False by default. */ showFastPaginationControls?: boolean; - /** - * Color of the pagination control ripple effect. - */ - paginationControlRippleColor?: ColorValue; /** * @optional */ @@ -104,7 +91,6 @@ const PaginationControls = ({ onPageChange, showFastPaginationControls, theme: themeOverrides, - paginationControlRippleColor, }: PaginationControlsProps) => { const theme = useInternalTheme(themeOverrides); @@ -123,7 +109,6 @@ const PaginationControls = ({ /> )} iconColor={textColor} - rippleColor={paginationControlRippleColor} disabled={page === 0} onPress={() => onPageChange(0)} accessibilityLabel="page-first" @@ -140,7 +125,6 @@ const PaginationControls = ({ /> )} iconColor={textColor} - rippleColor={paginationControlRippleColor} disabled={page === 0} onPress={() => onPageChange(page - 1)} accessibilityLabel="chevron-left" @@ -156,7 +140,6 @@ const PaginationControls = ({ /> )} iconColor={textColor} - rippleColor={paginationControlRippleColor} disabled={numberOfPages === 0 || page === numberOfPages - 1} onPress={() => onPageChange(page + 1)} accessibilityLabel="chevron-right" @@ -173,7 +156,6 @@ const PaginationControls = ({ /> )} iconColor={textColor} - rippleColor={paginationControlRippleColor} disabled={numberOfPages === 0 || page === numberOfPages - 1} onPress={() => onPageChange(numberOfPages - 1)} accessibilityLabel="page-last" @@ -189,8 +171,6 @@ const PaginationDropdown = ({ numberOfItemsPerPage, onItemsPerPageChange, theme: themeOverrides, - selectPageDropdownRippleColor, - dropdownItemRippleColor, }: PaginationDropdownProps) => { const theme = useInternalTheme(themeOverrides); const { colors } = theme; @@ -209,7 +189,6 @@ const PaginationDropdown = ({ icon="menu-down" contentStyle={styles.contentStyle} theme={theme} - rippleColor={selectPageDropdownRippleColor} > {`${numberOfItemsPerPage}`} @@ -227,7 +206,6 @@ const PaginationDropdown = ({ onItemsPerPageChange?.(option); toggleSelect(false); }} - rippleColor={dropdownItemRippleColor} title={option} theme={theme} /> @@ -304,8 +282,6 @@ const DataTablePagination = ({ onItemsPerPageChange, selectPageDropdownLabel, selectPageDropdownAccessibilityLabel, - selectPageDropdownRippleColor, - dropdownItemRippleColor, theme: themeOverrides, ...rest }: Props) => { @@ -339,8 +315,6 @@ const DataTablePagination = ({ numberOfItemsPerPageList={numberOfItemsPerPageList} numberOfItemsPerPage={numberOfItemsPerPage} onItemsPerPageChange={onItemsPerPageChange} - selectPageDropdownRippleColor={selectPageDropdownRippleColor} - dropdownItemRippleColor={dropdownItemRippleColor} theme={theme} /> diff --git a/src/components/Drawer/DrawerItem.tsx b/src/components/Drawer/DrawerItem.tsx index 7af3d9fcf4..6902b4b8cb 100644 --- a/src/components/Drawer/DrawerItem.tsx +++ b/src/components/Drawer/DrawerItem.tsx @@ -1,6 +1,5 @@ import * as React from 'react'; import { - ColorValue, GestureResponderEvent, PressableAndroidRippleConfig, StyleProp, @@ -9,8 +8,6 @@ import { ViewStyle, } from 'react-native'; -import color from 'color'; - import { useInternalTheme } from '../../core/theming'; import type { ThemeProp } from '../../types'; import Icon, { IconSource } from '../Icon'; @@ -57,10 +54,6 @@ export type Props = React.ComponentPropsWithRef & { * Specifies the largest possible scale a label font can reach. */ labelMaxFontSizeMultiplier?: number; - /** - * Color of the ripple effect. - */ - rippleColor?: ColorValue; /** * Sets additional distance outside of element in which a press can be detected. */ @@ -97,7 +90,6 @@ const DrawerItem = ({ active, disabled, theme: themeOverrides, - rippleColor: customRippleColor, style, onPress, background, @@ -117,7 +109,6 @@ const DrawerItem = ({ const labelMargin = icon ? 12 : 0; const borderRadius = 7 * roundness; - const rippleColor = color(contentColor).alpha(0.12).rgb().string(); const font = theme.fonts.labelLarge; return ( @@ -136,7 +127,6 @@ const DrawerItem = ({ accessibilityRole="button" accessibilityState={{ selected: active }} accessibilityLabel={accessibilityLabel} - rippleColor={customRippleColor || rippleColor} theme={theme} hitSlop={hitSlop} > diff --git a/src/components/FAB/AnimatedFAB.tsx b/src/components/FAB/AnimatedFAB.tsx index 6b6964a4a9..c39144705c 100644 --- a/src/components/FAB/AnimatedFAB.tsx +++ b/src/components/FAB/AnimatedFAB.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import type { AccessibilityState, - ColorValue, NativeSyntheticEvent, PressableAndroidRippleConfig, TextLayoutEventData, @@ -20,8 +19,6 @@ import { Text, } from 'react-native'; -import color from 'color'; - import { getCombinedStyles, getFABColors, getLabelSizeWeb } from './utils'; import { useInternalTheme } from '../../core/theming'; import type { $Omit, $RemoveChildren, ThemeProp } from '../../types'; @@ -67,10 +64,6 @@ export type Props = $Omit<$RemoveChildren, 'mode'> & { * Custom color for the icon and label of the `FAB`. */ color?: string; - /** - * Color of the ripple effect. - */ - rippleColor?: ColorValue; /** * Whether `FAB` is disabled. A disabled button is greyed out and `onPress` is not called on touch. */ @@ -213,7 +206,6 @@ const AnimatedFAB = ({ accessibilityLabel = label, accessibilityState, color: customColor, - rippleColor: customRippleColor, disabled, onPress, onLongPress, @@ -313,9 +305,6 @@ const AnimatedFAB = ({ customBackgroundColor, }); - const rippleColor = - customRippleColor || color(foregroundColor).alpha(0.12).rgb().string(); - const extendedWidth = textWidth + SIZE + borderRadius; const distance = isAnimatedFromRight @@ -462,7 +451,6 @@ const AnimatedFAB = ({ onPress={onPress} onLongPress={onLongPress} delayLongPress={delayLongPress} - rippleColor={rippleColor} disabled={disabled} accessibilityLabel={accessibilityLabel} accessibilityRole="button" diff --git a/src/components/FAB/FAB.tsx b/src/components/FAB/FAB.tsx index 9ac9cf3435..ae8c3f193d 100644 --- a/src/components/FAB/FAB.tsx +++ b/src/components/FAB/FAB.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import { AccessibilityState, Animated, - ColorValue, GestureResponderEvent, PressableAndroidRippleConfig, StyleProp, @@ -79,10 +78,6 @@ export type Props = $Omit<$RemoveChildren, 'mode'> & { * Custom color for the icon and label of the `FAB`. */ color?: string; - /** - * Color of the ripple effect. - */ - rippleColor?: ColorValue; /** * Whether `FAB` is disabled. A disabled button is greyed out and `onPress` is not called on touch. */ @@ -189,7 +184,6 @@ const FAB = forwardRef( accessibilityState, animated = true, color: customColor, - rippleColor: customRippleColor, disabled, onPress, onLongPress, @@ -242,13 +236,12 @@ const FAB = forwardRef( backgroundColor: customBackgroundColor, } = (StyleSheet.flatten(style) || {}) as ViewStyle; - const { backgroundColor, foregroundColor, rippleColor } = getFABColors({ + const { backgroundColor, foregroundColor } = getFABColors({ theme, variant, disabled, customColor, customBackgroundColor, - customRippleColor, }); const isLargeSize = size === 'large'; @@ -295,7 +288,6 @@ const FAB = forwardRef( onPress={onPress} onLongPress={onLongPress} delayLongPress={delayLongPress} - rippleColor={rippleColor} disabled={disabled} accessibilityLabel={accessibilityLabel} accessibilityRole="button" diff --git a/src/components/FAB/FABGroup.tsx b/src/components/FAB/FABGroup.tsx index de88de8185..5579728d98 100644 --- a/src/components/FAB/FABGroup.tsx +++ b/src/components/FAB/FABGroup.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import { Animated, - ColorValue, GestureResponderEvent, Pressable, StyleProp, @@ -43,7 +42,6 @@ export type Props = { * - `toggleStackOnLongPress`: callback that is called when `FAB` is long pressed * - `size`: size of action item. Defaults to `small`. @supported Available in v5.x * - `testID`: testID to be used on tests - * - `rippleColor`: color of the ripple effect. */ actions: Array<{ icon: IconSource; @@ -60,7 +58,6 @@ export type Props = { onPress: (e: GestureResponderEvent) => void; size?: 'small' | 'medium'; testID?: string; - rippleColor?: ColorValue; }>; /** * Icon to display for the `FAB`. @@ -79,10 +76,6 @@ export type Props = { * Custom backdrop color for opened speed dial background. */ backdropColor?: string; - /** - * Color of the ripple effect. - */ - rippleColor?: ColorValue; /** * Function to execute on pressing the `FAB`. */ @@ -221,7 +214,6 @@ const FABGroup = ({ variant = 'primary', enableLongPressWhenStackOpened = false, backdropColor: customBackdropColor, - rippleColor, }: Props) => { const theme = useInternalTheme(themeOverrides); const { top, bottom, right, left } = useSafeAreaInsets(); @@ -466,7 +458,6 @@ const FABGroup = ({ importantForAccessibility="no-hide-descendants" testID={it.testID} visible={open} - rippleColor={it.rippleColor} /> ); @@ -487,7 +478,6 @@ const FABGroup = ({ label={label} testID={testID} variant={variant} - rippleColor={rippleColor} /> diff --git a/src/components/FAB/utils.ts b/src/components/FAB/utils.ts index 42dd05ff7e..384fcc6c45 100644 --- a/src/components/FAB/utils.ts +++ b/src/components/FAB/utils.ts @@ -234,14 +234,12 @@ export const getFABColors = ({ disabled, customColor, customBackgroundColor, - customRippleColor, }: { theme: InternalTheme; variant: string; disabled?: boolean; customColor?: string; customBackgroundColor?: ColorValue; - customRippleColor?: ColorValue; }) => { const isVariant = (variantToCompare: Variant) => { return variant === variantToCompare; @@ -262,8 +260,6 @@ export const getFABColors = ({ return { backgroundColor, foregroundColor, - rippleColor: - customRippleColor || color(foregroundColor).alpha(0.12).rgb().string(), }; }; diff --git a/src/components/IconButton/IconButton.tsx b/src/components/IconButton/IconButton.tsx index 2da6e12fcf..dbe7de4841 100644 --- a/src/components/IconButton/IconButton.tsx +++ b/src/components/IconButton/IconButton.tsx @@ -6,7 +6,6 @@ import { ViewStyle, View, Animated, - ColorValue, } from 'react-native'; import { getIconButtonColor } from './utils'; @@ -43,11 +42,6 @@ export type Props = Omit<$RemoveChildren, 'style'> & { */ containerColor?: string; /** - * Color of the ripple effect. - */ - rippleColor?: ColorValue; - /** - * @supported Available in v5.x with theme version 3 * Whether icon button is selected. A selected button receives alternative combination of icon and container colors. */ selected?: boolean; @@ -120,7 +114,6 @@ const IconButton = forwardRef( icon, iconColor: customIconColor, containerColor: customContainerColor, - rippleColor: customRippleColor, size = 24, accessibilityLabel, disabled, @@ -141,16 +134,14 @@ const IconButton = forwardRef( const IconComponent = animated ? CrossFadeIcon : Icon; - const { iconColor, rippleColor, backgroundColor, borderColor } = - getIconButtonColor({ - theme, - disabled, - selected, - mode, - customIconColor, - customContainerColor, - customRippleColor, - }); + const { iconColor, backgroundColor, borderColor } = getIconButtonColor({ + theme, + disabled, + selected, + mode, + customIconColor, + customContainerColor, + }); const buttonSize = size + 2 * PADDING; @@ -186,7 +177,6 @@ const IconButton = forwardRef( borderless centered onPress={onPress} - rippleColor={rippleColor} accessibilityLabel={accessibilityLabel} style={[styles.touchable, contentStyle]} // @ts-expect-error We keep old a11y props for backwards compat with old RN versions diff --git a/src/components/IconButton/utils.ts b/src/components/IconButton/utils.ts index f808ec6970..fd985b04aa 100644 --- a/src/components/IconButton/utils.ts +++ b/src/components/IconButton/utils.ts @@ -1,7 +1,3 @@ -import type { ColorValue } from 'react-native'; - -import color from 'color'; - import type { InternalTheme } from '../../types'; type IconButtonMode = 'outlined' | 'contained' | 'contained-tonal'; @@ -109,19 +105,6 @@ const getIconColor = ({ return theme.colors.onSurfaceVariant; }; -const getRippleColor = ({ - iconColor, - customRippleColor, -}: { - iconColor: string; - customRippleColor?: ColorValue; -}) => { - if (customRippleColor) { - return customRippleColor; - } - return color(iconColor).alpha(0.12).rgb().string(); -}; - export const getIconButtonColor = ({ theme, disabled, @@ -129,7 +112,6 @@ export const getIconButtonColor = ({ selected, customIconColor, customContainerColor, - customRippleColor, }: { theme: InternalTheme; disabled?: boolean; @@ -137,7 +119,6 @@ export const getIconButtonColor = ({ mode?: IconButtonMode; customIconColor?: string; customContainerColor?: string; - customRippleColor?: ColorValue; }) => { const isMode = (modeToCompare: IconButtonMode) => { return mode === modeToCompare; @@ -161,7 +142,6 @@ export const getIconButtonColor = ({ ...baseIconColorProps, customContainerColor, }), - rippleColor: getRippleColor({ iconColor, customRippleColor }), borderColor: getBorderColor({ theme, disabled }), }; }; diff --git a/src/components/List/ListAccordion.tsx b/src/components/List/ListAccordion.tsx index ace8810a71..3eaee97d61 100644 --- a/src/components/List/ListAccordion.tsx +++ b/src/components/List/ListAccordion.tsx @@ -1,6 +1,5 @@ import * as React from 'react'; import { - ColorValue, GestureResponderEvent, I18nManager, NativeSyntheticEvent, @@ -93,10 +92,6 @@ export type Props = { * Style that is passed to Description element. */ descriptionStyle?: StyleProp; - /** - * Color of the ripple effect. - */ - rippleColor?: ColorValue; /** * Truncate Title text such that the total number of lines does not * exceed this number. @@ -186,7 +181,6 @@ const ListAccordion = ({ descriptionStyle, titleNumberOfLines = 1, descriptionNumberOfLines = 2, - rippleColor: customRippleColor, style, containerStyle, contentStyle, @@ -238,10 +232,9 @@ const ListAccordion = ({ ? groupContext.expandedId === id : expandedInternal; - const { descriptionColor, titleTextColor, rippleColor } = getAccordionColors({ + const { descriptionColor, titleTextColor } = getAccordionColors({ theme, isExpanded, - customRippleColor, }); const handlePress = @@ -256,7 +249,6 @@ const ListAccordion = ({ onPress={handlePress} onLongPress={onLongPress} delayLongPress={delayLongPress} - rippleColor={rippleColor} accessibilityRole="button" accessibilityState={{ expanded: isExpanded }} accessibilityLabel={accessibilityLabel} diff --git a/src/components/List/utils.ts b/src/components/List/utils.ts index 05186efe8e..11a1618fbc 100644 --- a/src/components/List/utils.ts +++ b/src/components/List/utils.ts @@ -1,6 +1,5 @@ -import { ColorValue, StyleSheet, StyleProp, ViewStyle } from 'react-native'; +import { StyleSheet, StyleProp, ViewStyle } from 'react-native'; -import color from 'color'; import type { EllipsizeProp, InternalTheme, ThemeProp } from 'src/types'; type Description = @@ -90,11 +89,9 @@ const styles = StyleSheet.create({ export const getAccordionColors = ({ theme, isExpanded, - customRippleColor, }: { theme: InternalTheme; isExpanded?: boolean; - customRippleColor?: ColorValue; }) => { const titleColor = theme.colors.onSurface; @@ -102,12 +99,8 @@ export const getAccordionColors = ({ const titleTextColor = isExpanded ? theme.colors?.primary : titleColor; - const rippleColor = - customRippleColor || color(titleTextColor).alpha(0.12).rgb().string(); - return { descriptionColor, titleTextColor, - rippleColor, }; }; diff --git a/src/components/Menu/MenuItem.tsx b/src/components/Menu/MenuItem.tsx index 652ffc9a4f..725e38cd5b 100644 --- a/src/components/Menu/MenuItem.tsx +++ b/src/components/Menu/MenuItem.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import { AccessibilityState, - ColorValue, GestureResponderEvent, PressableAndroidRippleConfig, StyleProp, @@ -82,10 +81,6 @@ export type Props = { * Style that is passed to the Title element. */ titleStyle?: StyleProp; - /** - * Color of the ripple effect. - */ - rippleColor?: ColorValue; /** * @optional */ @@ -142,7 +137,6 @@ const MenuItem = ({ containerStyle, contentStyle, titleStyle, - rippleColor: customRippleColor, testID = 'menu-item', accessibilityLabel, accessibilityState, @@ -151,10 +145,9 @@ const MenuItem = ({ hitSlop, }: Props) => { const theme = useInternalTheme(themeOverrides); - const { titleColor, iconColor, rippleColor } = getMenuItemColor({ + const { titleColor, iconColor } = getMenuItemColor({ theme, disabled, - customRippleColor, }); const containerPadding = 12; @@ -190,7 +183,6 @@ const MenuItem = ({ accessibilityLabel={accessibilityLabel} accessibilityRole="menuitem" accessibilityState={newAccessibilityState} - rippleColor={rippleColor} hitSlop={hitSlop} > diff --git a/src/components/Menu/utils.ts b/src/components/Menu/utils.ts index 71c503bcc2..8fc73ca082 100644 --- a/src/components/Menu/utils.ts +++ b/src/components/Menu/utils.ts @@ -1,7 +1,3 @@ -import type { ColorValue } from 'react-native'; - -import color from 'color'; - import type { InternalTheme, MD3Theme } from '../../types'; import type { IconSource } from '../Icon'; @@ -17,7 +13,6 @@ type ContentProps = { type ColorProps = { theme: InternalTheme; disabled?: boolean; - customRippleColor?: ColorValue; }; const getDisabledColor = (theme: InternalTheme) => { @@ -42,29 +37,10 @@ const getIconColor = ({ theme, disabled }: ColorProps) => { return colors.onSurfaceVariant; }; -const getRippleColor = ({ - theme, - customRippleColor, -}: Omit) => { - if (customRippleColor) { - return customRippleColor; - } - - return color((theme as MD3Theme).colors.onSurfaceVariant) - .alpha(0.12) - .rgb() - .string(); -}; - -export const getMenuItemColor = ({ - theme, - disabled, - customRippleColor, -}: ColorProps) => { +export const getMenuItemColor = ({ theme, disabled }: ColorProps) => { return { titleColor: getTitleColor({ theme, disabled }), iconColor: getIconColor({ theme, disabled }), - rippleColor: getRippleColor({ theme, customRippleColor }), }; }; diff --git a/src/components/RadioButton/RadioButtonItem.tsx b/src/components/RadioButton/RadioButtonItem.tsx index eeff5c3d26..aa6c401c1f 100644 --- a/src/components/RadioButton/RadioButtonItem.tsx +++ b/src/components/RadioButton/RadioButtonItem.tsx @@ -1,6 +1,5 @@ import * as React from 'react'; import { - ColorValue, GestureResponderEvent, PressableAndroidRippleConfig, StyleProp, @@ -60,10 +59,6 @@ export type Props = { * Custom color for radio. */ color?: string; - /** - * Color of the ripple effect. - */ - rippleColor?: ColorValue; /** * Status of radio button. */ @@ -152,7 +147,6 @@ const RadioButtonItem = ({ disabled, color, uncheckedColor, - rippleColor, status, theme: themeOverrides, background, @@ -223,7 +217,6 @@ const RadioButtonItem = ({ disabled={disabled} background={background} theme={theme} - rippleColor={rippleColor} hitSlop={hitSlop} > diff --git a/src/components/Searchbar.tsx b/src/components/Searchbar.tsx index 6377899280..1f49d7925c 100644 --- a/src/components/Searchbar.tsx +++ b/src/components/Searchbar.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import { Animated, - ColorValue, GestureResponderEvent, I18nManager, Platform, @@ -14,8 +13,6 @@ import { ViewStyle, } from 'react-native'; -import color from 'color'; - import ActivityIndicator from './ActivityIndicator'; import Divider from './Divider'; import type { IconSource } from './Icon'; @@ -56,10 +53,6 @@ export type Props = React.ComponentPropsWithRef & { * Custom color for icon, default will be derived from theme */ iconColor?: string; - /** - * Color of the ripple effect. - */ - rippleColor?: ColorValue; /** * Callback to execute if we want the left icon to act as button. */ @@ -94,12 +87,6 @@ export type Props = React.ComponentPropsWithRef & { */ traileringIconColor?: string; /** - * @supported Available in v5.x with theme version 3 - * Color of the trailering icon ripple effect. - */ - traileringRippleColor?: ColorValue; - /** - * @supported Available in v5.x with theme version 3 * Callback to execute on the right trailering icon button press. */ onTraileringIconPress?: (e: GestureResponderEvent) => void; @@ -181,7 +168,6 @@ const Searchbar = forwardRef( { icon, iconColor: customIconColor, - rippleColor: customRippleColor, onIconPress, searchAccessibilityLabel = 'search', clearIcon, @@ -190,7 +176,6 @@ const Searchbar = forwardRef( traileringIcon, traileringIconColor, traileringIconAccessibilityLabel, - traileringRippleColor: customTraileringRippleColor, onTraileringIconPress, right, mode = 'bar', @@ -230,14 +215,9 @@ const Searchbar = forwardRef( const { roundness, dark } = theme; - const placeholderTextColor = colors.onSurface; - const textColor = colors.onSurfaceVariant; - const iconColor = customIconColor || colors.onSurfaceVariant; - const rippleColor = - customRippleColor || color(textColor).alpha(0.32).rgb().string(); - const traileringRippleColor = - customTraileringRippleColor || - color(textColor).alpha(0.32).rgb().string(); + const placeholderTextColor = theme.colors.onSurface; + const textColor = theme.colors.onSurfaceVariant; + const iconColor = customIconColor || theme.colors.onSurfaceVariant; const font = { ...fonts.bodyLarge, @@ -273,7 +253,6 @@ const Searchbar = forwardRef( ( borderless accessibilityLabel={clearAccessibilityLabel} iconColor={value ? iconColor : 'rgba(255, 255, 255, 0)'} - rippleColor={rippleColor} onPress={handleClearPress} icon={ clearIcon || @@ -360,8 +338,7 @@ const Searchbar = forwardRef( accessibilityRole="button" borderless onPress={onTraileringIconPress} - iconColor={traileringIconColor || colors.onSurfaceVariant} - rippleColor={traileringRippleColor} + iconColor={traileringIconColor || theme.colors.onSurfaceVariant} icon={traileringIcon} accessibilityLabel={traileringIconAccessibilityLabel} testID={`${testID}-trailering-icon`} diff --git a/src/components/SegmentedButtons/SegmentedButtonItem.tsx b/src/components/SegmentedButtons/SegmentedButtonItem.tsx index 64471f59fd..6f04b6aeb7 100644 --- a/src/components/SegmentedButtons/SegmentedButtonItem.tsx +++ b/src/components/SegmentedButtons/SegmentedButtonItem.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import { Animated, - ColorValue, GestureResponderEvent, PressableAndroidRippleConfig, StyleProp, @@ -11,7 +10,6 @@ import { ViewStyle, } from 'react-native'; -import color from 'color'; import type { ThemeProp } from 'src/types'; import { @@ -46,10 +44,6 @@ export type Props = { * Custom color for checked Text and Icon. */ checkedColor?: string; - /** - * Color of the ripple effect. - */ - rippleColor?: ColorValue; /** * Whether the button is disabled. */ @@ -119,7 +113,6 @@ const SegmentedButtonItem = ({ showSelectedCheck, checkedColor, uncheckedColor, - rippleColor: customRippleColor, background, icon, testID, @@ -167,9 +160,6 @@ const SegmentedButtonItem = ({ theme, segment, }); - const rippleColor = - customRippleColor || color(textColor).alpha(0.12).rgb().string(); - const showIcon = !icon ? false : label && checked ? !showSelectedCheck : true; const showCheckedIcon = checked && showSelectedCheck; @@ -214,7 +204,6 @@ const SegmentedButtonItem = ({ accessibilityState={{ disabled, checked }} accessibilityRole="button" disabled={disabled} - rippleColor={rippleColor} testID={testID} style={rippleStyle} background={background} diff --git a/src/components/Snackbar.tsx b/src/components/Snackbar.tsx index 22b55bb02a..6151e23ae2 100644 --- a/src/components/Snackbar.tsx +++ b/src/components/Snackbar.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import { Animated, - ColorValue, Easing, I18nManager, StyleProp, @@ -41,12 +40,6 @@ export type Props = $Omit, 'mode'> & { */ icon?: IconSource; /** - * @supported Available in v5.x with theme version 3 - * Color of the ripple effect. - */ - rippleColor?: ColorValue; - /** - * @supported Available in v5.x with theme version 3 * Function to execute on icon button press. The icon button appears only when this prop is specified. */ onIconPress?: () => void; @@ -161,7 +154,6 @@ const Snackbar = ({ contentStyle, theme: themeOverrides, maxFontSizeMultiplier, - rippleColor, testID, ...rest }: Props) => { @@ -253,7 +245,6 @@ const Snackbar = ({ style: actionStyle, label: actionLabel, onPress: onPressAction, - rippleColor: actionRippleColor, ...actionProps } = action || {}; @@ -338,7 +329,6 @@ const Snackbar = ({ compact={false} mode="text" theme={theme} - rippleColor={actionRippleColor} {...actionProps} > {actionLabel} @@ -349,8 +339,7 @@ const Snackbar = ({ accessibilityRole="button" borderless onPress={onIconPress} - iconColor={colors.inverseOnSurface} - rippleColor={rippleColor} + iconColor={theme.colors.inverseOnSurface} theme={theme} icon={ icon || diff --git a/src/components/TextInput/Adornment/TextInputIcon.tsx b/src/components/TextInput/Adornment/TextInputIcon.tsx index 8f4ce7c4df..0005071fe3 100644 --- a/src/components/TextInput/Adornment/TextInputIcon.tsx +++ b/src/components/TextInput/Adornment/TextInputIcon.tsx @@ -1,6 +1,5 @@ import React from 'react'; import { - ColorValue, GestureResponderEvent, StyleProp, StyleSheet, @@ -37,10 +36,6 @@ export type Props = $Omit< * Color of the icon or a function receiving a boolean indicating whether the TextInput is focused and returning the color. */ color?: ((isTextInputFocused: boolean) => string | undefined) | string; - /** - * Color of the ripple effect. - */ - rippleColor?: ColorValue; style?: StyleProp; /** * @optional @@ -129,7 +124,6 @@ const TextInputIcon = ({ forceTextInputFocus = true, color: customColor, theme: themeOverrides, - rippleColor, ...rest }: Props) => { const { style, isTextInputFocused, forceFocus, testID, disabled } = @@ -165,7 +159,6 @@ const TextInputIcon = ({ iconColor={iconColor} testID={testID} theme={themeOverrides} - rippleColor={rippleColor} {...rest} /> diff --git a/src/components/ToggleButton/ToggleButton.tsx b/src/components/ToggleButton/ToggleButton.tsx index e115dec7ec..ba4bd138a3 100644 --- a/src/components/ToggleButton/ToggleButton.tsx +++ b/src/components/ToggleButton/ToggleButton.tsx @@ -6,7 +6,6 @@ import { ViewStyle, View, Animated, - ColorValue, } from 'react-native'; import { ToggleButtonGroupContext } from './ToggleButtonGroup'; @@ -30,10 +29,6 @@ export type Props = { * Custom text color for button. */ iconColor?: string; - /** - * Color of the ripple effect. - */ - rippleColor?: ColorValue; /** * Whether the button is disabled. */ @@ -108,7 +103,6 @@ const ToggleButton = forwardRef( value, status, onPress, - rippleColor, ...rest }: Props, ref @@ -155,7 +149,6 @@ const ToggleButton = forwardRef( ]} ref={ref} theme={theme} - rippleColor={rippleColor} {...rest} /> ); diff --git a/src/components/TouchableRipple/utils.ts b/src/components/TouchableRipple/utils.ts index e3a1e9726f..83308eb228 100644 --- a/src/components/TouchableRipple/utils.ts +++ b/src/components/TouchableRipple/utils.ts @@ -29,7 +29,7 @@ const getRippleColor = ({ return rippleColor; } - return color(theme.colors.onSurface).alpha(0.12).rgb().string(); + return color(theme.colors.onSurface).alpha(0.1).rgb().string(); }; export const getTouchableRippleColors = ({ diff --git a/src/components/__tests__/Chip.test.tsx b/src/components/__tests__/Chip.test.tsx index 6c0e851f22..5505a3726e 100644 --- a/src/components/__tests__/Chip.test.tsx +++ b/src/components/__tests__/Chip.test.tsx @@ -186,48 +186,6 @@ describe('getChipColors - icon color', () => { }); }); -describe('getChipColors - ripple color', () => { - it('should return theme color, for theme version 3, flat mode', () => { - expect( - getChipColors({ - theme: getTheme(), - isOutlined: false, - }) - ).toMatchObject({ - rippleColor: color(getTheme().colors.onSecondaryContainer) - .alpha(0.12) - .rgb() - .string(), - }); - }); - - it('should return theme color, for theme version 3, outline mode', () => { - expect( - getChipColors({ - theme: getTheme(), - isOutlined: true, - }) - ).toMatchObject({ - rippleColor: color(getTheme().colors.onSurfaceVariant) - .alpha(0.12) - .rgb() - .string(), - }); - }); - - it('should return custom color, for theme version 3', () => { - expect( - getChipColors({ - theme: getTheme(), - selectedColor: 'purple', - isOutlined: false, - }) - ).toMatchObject({ - rippleColor: color('purple').alpha(0.12).rgb().string(), - }); - }); -}); - describe('getChipColor - selected background color', () => { it('should return custom color, for theme version 3, outlined mode', () => { expect( diff --git a/src/components/__tests__/FABGroup.test.tsx b/src/components/__tests__/FABGroup.test.tsx index 3eb51c78d6..7009526e42 100644 --- a/src/components/__tests__/FABGroup.test.tsx +++ b/src/components/__tests__/FABGroup.test.tsx @@ -137,37 +137,6 @@ it('correctly adds label prop', () => { expect(getByText('Label test')).toBeTruthy(); }); -it('correct renders custom ripple color passed to FAB.Group and its item', () => { - const { getByTestId } = render( - {}} - actions={[ - { - label: 'testing', - onPress() {}, - icon: '', - rippleColor: 'yellow', - testID: 'fab-group-item', - }, - ]} - /> - ); - - expect( - getByTestId('fab-group-container').props.children.props.rippleColor - ).toBe('orange'); - - expect( - getByTestId('fab-group-item-container').props.children.props.rippleColor - ).toBe('yellow'); -}); - it('animated value changes correctly', () => { const value = new Animated.Value(1); const { getByTestId } = render( diff --git a/src/components/__tests__/IconButton.test.tsx b/src/components/__tests__/IconButton.test.tsx index 11f47cb49c..39d1eb8663 100644 --- a/src/components/__tests__/IconButton.test.tsx +++ b/src/components/__tests__/IconButton.test.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import { Animated, StyleSheet } from 'react-native'; import { act, render } from '@testing-library/react-native'; -import color from 'color'; import { getTheme } from '../../core/theming'; import { pink500 } from '../../styles/themes/v2/colors'; @@ -308,21 +307,6 @@ describe('getIconButtonColor - border color', () => { }); }); -describe('getIconButtonColor - ripple color', () => { - it('should return theme color, for theme version 3', () => { - expect( - getIconButtonColor({ - theme: getTheme(), - }) - ).toMatchObject({ - rippleColor: color(getTheme().colors.onSurfaceVariant) - .alpha(0.12) - .rgb() - .string(), - }); - }); -}); - it('action animated value changes correctly', () => { const value = new Animated.Value(1); const { getByTestId } = render( diff --git a/src/components/__tests__/ListAccordion.test.tsx b/src/components/__tests__/ListAccordion.test.tsx index 9695b3c186..65a6a9d4de 100644 --- a/src/components/__tests__/ListAccordion.test.tsx +++ b/src/components/__tests__/ListAccordion.test.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import { StyleSheet, View } from 'react-native'; import { render } from '@testing-library/react-native'; -import color from 'color'; import { getTheme } from '../../core/theming'; import { red500 } from '../../styles/themes/v2/colors'; @@ -149,29 +148,3 @@ describe('getAccordionColors - title text color', () => { }); }); }); - -describe('getAccordionColors - ripple color', () => { - it('should return theme color, for theme version 3', () => { - expect( - getAccordionColors({ - theme: getTheme(), - }) - ).toMatchObject({ - rippleColor: color(getTheme().colors.onSurface) - .alpha(0.12) - .rgb() - .string(), - }); - }); - - it('should return primary color if it is expanded', () => { - expect( - getAccordionColors({ - theme: getTheme(), - isExpanded: true, - }) - ).toMatchObject({ - rippleColor: color(getTheme().colors.primary).alpha(0.12).rgb().string(), - }); - }); -}); diff --git a/src/components/__tests__/MenuItem.test.tsx b/src/components/__tests__/MenuItem.test.tsx index d482800582..10fb008b5e 100644 --- a/src/components/__tests__/MenuItem.test.tsx +++ b/src/components/__tests__/MenuItem.test.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import { render } from '@testing-library/react-native'; -import color from 'color'; import { getTheme } from '../../core/theming'; import Menu from '../Menu/Menu'; @@ -105,18 +104,3 @@ describe('getMenuItemColor - icon color', () => { }); }); }); - -describe('getMenuItemColor - ripple color', () => { - it('should return correct theme color, for theme version 3', () => { - expect( - getMenuItemColor({ - theme: getTheme(), - }) - ).toMatchObject({ - rippleColor: color(getTheme().colors.onSurfaceVariant) - .alpha(0.12) - .rgb() - .string(), - }); - }); -}); diff --git a/src/components/__tests__/Searchbar.test.tsx b/src/components/__tests__/Searchbar.test.tsx index 59ade128e4..eb44e85481 100644 --- a/src/components/__tests__/Searchbar.test.tsx +++ b/src/components/__tests__/Searchbar.test.tsx @@ -38,15 +38,6 @@ it('renders without ActivityIndicator', () => { expect(() => getByTestId('activity-indicator')).toThrow(); }); -it('render icon with custom ripple color', () => { - const { getByTestId } = render( - - ); - - const iconContainer = getByTestId('search-bar-icon-container').props.children; - expect(iconContainer.props.rippleColor).toBe('purple'); -}); - it('renders clear icon with custom color', () => { const { getByTestId } = render( @@ -141,16 +132,6 @@ it('renders clear icon wrapper, with appropriate style for v3', () => { }); }); -it('render clear icon with custom ripple color', () => { - const { getByTestId } = render( - - ); - - const clearIconContainer = getByTestId('search-bar-clear-icon-container') - .props.children; - expect(clearIconContainer.props.rippleColor).toBe('purple'); -}); - it('renders trailering icon when mode is set to "bar"', () => { const { getByTestId } = render( { expect(onTraileringIconPressMock).toHaveBeenCalledTimes(1); }); -it('renders trailering icon with custom ripple colors', () => { - const { getByTestId } = render( - - ); - - const traileringIconContainer = getByTestId( - 'search-bar-trailering-icon-container' - ).props.children; - expect(traileringIconContainer.props.rippleColor).toBe('purple'); -}); - it('renders clear icon instead of trailering icon', () => { const { getByTestId, update, queryByTestId } = render( { expect(tree).toMatchSnapshot(); }); -it('renders with custom ripple color', () => { - const { getByTestId } = render( - {}} - onIconPress={() => {}} - rippleColor="purple" - testID="snackbar" - > - Snackbar content - - ); - - const iconContainer = getByTestId('snackbar-icon-container').props.children; - expect(iconContainer.props.rippleColor).toBe('purple'); -}); - it('animated value changes correctly', () => { const value = new Animated.Value(1); const { getByTestId } = render( diff --git a/src/components/__tests__/ToggleButton.test.tsx b/src/components/__tests__/ToggleButton.test.tsx index a0e2bbafcb..61936f4909 100644 --- a/src/components/__tests__/ToggleButton.test.tsx +++ b/src/components/__tests__/ToggleButton.test.tsx @@ -33,22 +33,6 @@ it('renders unchecked toggle button', () => { expect(tree).toMatchSnapshot(); }); -it('render toggle button with custom ripple color', () => { - const { getByTestId } = render( - - ); - - const iconContainer = getByTestId('toggle-button-container').props.children; - expect(iconContainer.props.rippleColor).toBe('purple'); -}); - describe('getToggleButtonColor', () => { it('should return correct color when checked and theme version 3', () => { expect(getToggleButtonColor({ theme: getTheme(), checked: true })).toBe( From b49a6ff41882c0541d085c107646b6aaeee0f0ac Mon Sep 17 00:00:00 2001 From: Adrian Cotfas Date: Tue, 31 Mar 2026 16:07:01 +0300 Subject: [PATCH 07/13] fix: update colors as per material-components color tokens * see https://github.com/material-components/material-components-android/blob/master/lib/java/com/google/android/material/color/res/values/tokens.xml --- .../Appbar/__snapshots__/Appbar.test.tsx.snap | 16 +-- .../Card/__snapshots__/Card.test.tsx.snap | 4 +- .../__snapshots__/CheckboxItem.test.tsx.snap | 16 +-- .../RadioButtonItem.test.tsx.snap | 16 +-- .../__snapshots__/Caption.test.tsx.snap | 8 +- .../__snapshots__/Text.test.tsx.snap | 32 ++--- .../__snapshots__/Avatar.test.tsx.snap | 8 +- .../__snapshots__/Banner.test.tsx.snap | 30 ++--- .../BottomNavigation.test.tsx.snap | 122 +++++++++--------- .../__snapshots__/Button.test.tsx.snap | 28 ++-- .../__snapshots__/Chip.test.tsx.snap | 14 +- .../__snapshots__/DataTable.test.tsx.snap | 70 +++++----- .../__snapshots__/DrawerItem.test.tsx.snap | 6 +- .../__tests__/__snapshots__/FAB.test.tsx.snap | 10 +- .../__snapshots__/IconButton.test.tsx.snap | 4 +- .../__snapshots__/ListAccordion.test.tsx.snap | 36 +++--- .../__snapshots__/ListItem.test.tsx.snap | 38 +++--- .../__snapshots__/ListSection.test.tsx.snap | 76 +++++------ .../__snapshots__/Menu.test.tsx.snap | 22 ++-- .../__snapshots__/MenuItem.test.tsx.snap | 24 ++-- .../__snapshots__/Searchbar.test.tsx.snap | 6 +- .../SegmentedButton.test.tsx.snap | 6 +- .../__snapshots__/Snackbar.test.tsx.snap | 26 ++-- .../__snapshots__/TextInput.test.tsx.snap | 22 ++-- .../__snapshots__/ToggleButton.test.tsx.snap | 4 +- src/styles/themes/v3/tokens.tsx | 38 ++++-- 26 files changed, 349 insertions(+), 333 deletions(-) diff --git a/src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap b/src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap index 14afac63f3..6a2a882d9d 100644 --- a/src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap +++ b/src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap @@ -5,7 +5,7 @@ exports[`Appbar does not pass any additional props to Searchbar 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(255, 251, 254, 1)", + "backgroundColor": "rgba(255, 251, 255, 1)", "height": 64, "shadowColor": "#000", "shadowOffset": { @@ -23,7 +23,7 @@ exports[`Appbar does not pass any additional props to Searchbar 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgba(255, 251, 254, 1)", + "backgroundColor": "rgba(255, 251, 255, 1)", "flex": 1, "flexDirection": "row", "paddingBottom": undefined, @@ -217,7 +217,7 @@ exports[`Appbar does not pass any additional props to Searchbar 1`] = ` accessibilityRole="search" keyboardAppearance="light" placeholder="Search" - placeholderTextColor="rgba(28, 27, 31, 1)" + placeholderTextColor="rgba(29, 27, 32, 1)" returnKeyType="search" selectionColor="rgba(103, 80, 164, 1)" style={ @@ -409,7 +409,7 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A collapsable={false} style={ { - "backgroundColor": "rgba(255, 251, 254, 1)", + "backgroundColor": "rgba(255, 251, 255, 1)", "height": 64, "shadowColor": "#000", "shadowOffset": { @@ -427,7 +427,7 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A style={ { "alignItems": "center", - "backgroundColor": "rgba(255, 251, 254, 1)", + "backgroundColor": "rgba(255, 251, 255, 1)", "flex": 1, "flexDirection": "row", "paddingBottom": undefined, @@ -614,7 +614,7 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A }, { "height": 21, - "tintColor": "rgba(28, 27, 31, 1)", + "tintColor": "rgba(29, 27, 32, 1)", "width": 21, }, ] @@ -659,7 +659,7 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -672,7 +672,7 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A }, [ { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 22, "fontWeight": "400", diff --git a/src/components/__tests__/Card/__snapshots__/Card.test.tsx.snap b/src/components/__tests__/Card/__snapshots__/Card.test.tsx.snap index 301eea942c..4739d5009c 100644 --- a/src/components/__tests__/Card/__snapshots__/Card.test.tsx.snap +++ b/src/components/__tests__/Card/__snapshots__/Card.test.tsx.snap @@ -5,7 +5,7 @@ exports[`Card renders an outlined card 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(255, 251, 254, 1)", + "backgroundColor": "rgba(255, 251, 255, 1)", "borderRadius": 12, "shadowColor": "#000", "shadowOffset": { @@ -22,7 +22,7 @@ exports[`Card renders an outlined card 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(255, 251, 254, 1)", + "backgroundColor": "rgba(255, 251, 255, 1)", "borderRadius": 12, "flex": undefined, "shadowColor": "#000", diff --git a/src/components/__tests__/Checkbox/__snapshots__/CheckboxItem.test.tsx.snap b/src/components/__tests__/Checkbox/__snapshots__/CheckboxItem.test.tsx.snap index dbd992a134..3325829520 100644 --- a/src/components/__tests__/Checkbox/__snapshots__/CheckboxItem.test.tsx.snap +++ b/src/components/__tests__/Checkbox/__snapshots__/CheckboxItem.test.tsx.snap @@ -147,7 +147,7 @@ exports[`can render leading checkbox control 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -164,7 +164,7 @@ exports[`can render leading checkbox control 1`] = ` "flexShrink": 1, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "textAlign": "right", }, undefined, @@ -244,7 +244,7 @@ exports[`can render the Android checkbox on different platforms 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -261,7 +261,7 @@ exports[`can render the Android checkbox on different platforms 1`] = ` "flexShrink": 1, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "textAlign": "left", }, undefined, @@ -460,7 +460,7 @@ exports[`can render the iOS checkbox on different platforms 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -477,7 +477,7 @@ exports[`can render the iOS checkbox on different platforms 1`] = ` "flexShrink": 1, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "textAlign": "left", }, undefined, @@ -640,7 +640,7 @@ exports[`renders unchecked 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -657,7 +657,7 @@ exports[`renders unchecked 1`] = ` "flexShrink": 1, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "textAlign": "left", }, undefined, diff --git a/src/components/__tests__/RadioButton/__snapshots__/RadioButtonItem.test.tsx.snap b/src/components/__tests__/RadioButton/__snapshots__/RadioButtonItem.test.tsx.snap index e74650efd2..de667249ae 100644 --- a/src/components/__tests__/RadioButton/__snapshots__/RadioButtonItem.test.tsx.snap +++ b/src/components/__tests__/RadioButton/__snapshots__/RadioButtonItem.test.tsx.snap @@ -145,7 +145,7 @@ exports[`can render leading radio button control 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -162,7 +162,7 @@ exports[`can render leading radio button control 1`] = ` "flexShrink": 1, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "textAlign": "right", }, undefined, @@ -239,7 +239,7 @@ exports[`can render the Android radio button on different platforms 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -256,7 +256,7 @@ exports[`can render the Android radio button on different platforms 1`] = ` "flexShrink": 1, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "textAlign": "left", }, undefined, @@ -390,7 +390,7 @@ exports[`can render the iOS radio button on different platforms 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -407,7 +407,7 @@ exports[`can render the iOS radio button on different platforms 1`] = ` "flexShrink": 1, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "textAlign": "left", }, undefined, @@ -567,7 +567,7 @@ exports[`renders unchecked 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -584,7 +584,7 @@ exports[`renders unchecked 1`] = ` "flexShrink": 1, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "textAlign": "left", }, undefined, diff --git a/src/components/__tests__/Typography/__snapshots__/Caption.test.tsx.snap b/src/components/__tests__/Typography/__snapshots__/Caption.test.tsx.snap index 1120e943ca..8433f85658 100644 --- a/src/components/__tests__/Typography/__snapshots__/Caption.test.tsx.snap +++ b/src/components/__tests__/Typography/__snapshots__/Caption.test.tsx.snap @@ -5,7 +5,7 @@ exports[`renders caption applying style 1`] = ` style={ [ { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, { "textAlign": "left", @@ -15,7 +15,7 @@ exports[`renders caption applying style 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 0.54)", + "color": "rgba(29, 27, 32, 0.54)", "writingDirection": "ltr", }, [ @@ -43,7 +43,7 @@ exports[`renders caption with children as content 1`] = ` style={ [ { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, { "textAlign": "left", @@ -53,7 +53,7 @@ exports[`renders caption with children as content 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 0.54)", + "color": "rgba(29, 27, 32, 0.54)", "writingDirection": "ltr", }, [ diff --git a/src/components/__tests__/Typography/__snapshots__/Text.test.tsx.snap b/src/components/__tests__/Typography/__snapshots__/Text.test.tsx.snap index a47cd14611..5b87989124 100644 --- a/src/components/__tests__/Typography/__snapshots__/Text.test.tsx.snap +++ b/src/components/__tests__/Typography/__snapshots__/Text.test.tsx.snap @@ -9,7 +9,7 @@ exports[`renders every variant of Text with children as content 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -34,7 +34,7 @@ exports[`renders every variant of Text with children as content 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -59,7 +59,7 @@ exports[`renders every variant of Text with children as content 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -84,7 +84,7 @@ exports[`renders every variant of Text with children as content 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -109,7 +109,7 @@ exports[`renders every variant of Text with children as content 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -134,7 +134,7 @@ exports[`renders every variant of Text with children as content 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -159,7 +159,7 @@ exports[`renders every variant of Text with children as content 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -184,7 +184,7 @@ exports[`renders every variant of Text with children as content 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -209,7 +209,7 @@ exports[`renders every variant of Text with children as content 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -234,7 +234,7 @@ exports[`renders every variant of Text with children as content 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -259,7 +259,7 @@ exports[`renders every variant of Text with children as content 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -284,7 +284,7 @@ exports[`renders every variant of Text with children as content 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -309,7 +309,7 @@ exports[`renders every variant of Text with children as content 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -334,7 +334,7 @@ exports[`renders every variant of Text with children as content 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -359,7 +359,7 @@ exports[`renders every variant of Text with children as content 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -386,7 +386,7 @@ exports[`renders v3 Text component with custom variant correctly 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ diff --git a/src/components/__tests__/__snapshots__/Avatar.test.tsx.snap b/src/components/__tests__/__snapshots__/Avatar.test.tsx.snap index c73f2ae180..9e55666cef 100644 --- a/src/components/__tests__/__snapshots__/Avatar.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Avatar.test.tsx.snap @@ -158,7 +158,7 @@ exports[`renders avatar with text 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -212,7 +212,7 @@ exports[`renders avatar with text and custom background color 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -266,7 +266,7 @@ exports[`renders avatar with text and custom colors 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -320,7 +320,7 @@ exports[`renders avatar with text and custom size 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, diff --git a/src/components/__tests__/__snapshots__/Banner.test.tsx.snap b/src/components/__tests__/__snapshots__/Banner.test.tsx.snap index 175383e4ad..e92d72a81a 100644 --- a/src/components/__tests__/__snapshots__/Banner.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Banner.test.tsx.snap @@ -81,7 +81,7 @@ exports[`render visible banner, with custom theme 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -221,7 +221,7 @@ exports[`render visible banner, with custom theme 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -366,7 +366,7 @@ exports[`renders hidden banner, without action buttons and without image 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -383,7 +383,7 @@ exports[`renders hidden banner, without action buttons and without image 1`] = ` "margin": 8, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, ], ], @@ -511,7 +511,7 @@ exports[`renders visible banner, with action buttons and with image 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -528,7 +528,7 @@ exports[`renders visible banner, with action buttons and with image 1`] = ` "margin": 8, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, ], ], @@ -651,7 +651,7 @@ exports[`renders visible banner, with action buttons and with image 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -784,7 +784,7 @@ exports[`renders visible banner, with action buttons and without image 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -801,7 +801,7 @@ exports[`renders visible banner, with action buttons and without image 1`] = ` "margin": 8, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, ], ], @@ -924,7 +924,7 @@ exports[`renders visible banner, with action buttons and without image 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -1073,7 +1073,7 @@ exports[`renders visible banner, with action buttons and without image 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -1228,7 +1228,7 @@ exports[`renders visible banner, without action buttons and with image 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -1245,7 +1245,7 @@ exports[`renders visible banner, without action buttons and with image 1`] = ` "margin": 8, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, ], ], @@ -1351,7 +1351,7 @@ exports[`renders visible banner, without action buttons and without image 1`] = "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -1368,7 +1368,7 @@ exports[`renders visible banner, without action buttons and without image 1`] = "margin": 8, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, ], ], diff --git a/src/components/__tests__/__snapshots__/BottomNavigation.test.tsx.snap b/src/components/__tests__/__snapshots__/BottomNavigation.test.tsx.snap index cc788ce0b9..276f2b1bb3 100644 --- a/src/components/__tests__/__snapshots__/BottomNavigation.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/BottomNavigation.test.tsx.snap @@ -20,7 +20,7 @@ exports[`allows customizing Route's type via generics 1`] = ` "flex": 1, }, { - "backgroundColor": "rgba(255, 251, 254, 1)", + "backgroundColor": "rgba(255, 251, 255, 1)", }, ] } @@ -313,7 +313,7 @@ exports[`allows customizing Route's type via generics 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -332,7 +332,7 @@ exports[`allows customizing Route's type via generics 1`] = ` "textAlign": "center", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 12, "fontWeight": "500", @@ -369,7 +369,7 @@ exports[`allows customizing Route's type via generics 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -388,7 +388,7 @@ exports[`allows customizing Route's type via generics 1`] = ` "textAlign": "center", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 12, "fontWeight": "500", @@ -567,7 +567,7 @@ exports[`allows customizing Route's type via generics 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -623,7 +623,7 @@ exports[`allows customizing Route's type via generics 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -687,7 +687,7 @@ exports[`hides labels in non-shifting bottom navigation 1`] = ` "flex": 1, }, { - "backgroundColor": "rgba(255, 251, 254, 1)", + "backgroundColor": "rgba(255, 251, 255, 1)", }, ] } @@ -1428,7 +1428,7 @@ exports[`hides labels in shifting bottom navigation 1`] = ` "flex": 1, }, { - "backgroundColor": "rgba(255, 251, 254, 1)", + "backgroundColor": "rgba(255, 251, 255, 1)", }, ] } @@ -2169,7 +2169,7 @@ exports[`renders bottom navigation with getLazy 1`] = ` "flex": 1, }, { - "backgroundColor": "rgba(255, 251, 254, 1)", + "backgroundColor": "rgba(255, 251, 255, 1)", }, ] } @@ -2654,7 +2654,7 @@ exports[`renders bottom navigation with getLazy 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -2673,7 +2673,7 @@ exports[`renders bottom navigation with getLazy 1`] = ` "textAlign": "center", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 12, "fontWeight": "500", @@ -2710,7 +2710,7 @@ exports[`renders bottom navigation with getLazy 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -2729,7 +2729,7 @@ exports[`renders bottom navigation with getLazy 1`] = ` "textAlign": "center", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 12, "fontWeight": "500", @@ -2968,7 +2968,7 @@ exports[`renders bottom navigation with getLazy 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -3024,7 +3024,7 @@ exports[`renders bottom navigation with getLazy 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -3282,7 +3282,7 @@ exports[`renders bottom navigation with getLazy 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -3338,7 +3338,7 @@ exports[`renders bottom navigation with getLazy 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -3596,7 +3596,7 @@ exports[`renders bottom navigation with getLazy 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -3652,7 +3652,7 @@ exports[`renders bottom navigation with getLazy 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -3910,7 +3910,7 @@ exports[`renders bottom navigation with getLazy 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -3966,7 +3966,7 @@ exports[`renders bottom navigation with getLazy 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -4030,7 +4030,7 @@ exports[`renders bottom navigation with scene animation 1`] = ` "flex": 1, }, { - "backgroundColor": "rgba(255, 251, 254, 1)", + "backgroundColor": "rgba(255, 251, 255, 1)", }, ] } @@ -4388,7 +4388,7 @@ exports[`renders bottom navigation with scene animation 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -4407,7 +4407,7 @@ exports[`renders bottom navigation with scene animation 1`] = ` "textAlign": "center", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 12, "fontWeight": "500", @@ -4651,7 +4651,7 @@ exports[`renders bottom navigation with scene animation 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -4914,7 +4914,7 @@ exports[`renders bottom navigation with scene animation 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -5177,7 +5177,7 @@ exports[`renders bottom navigation with scene animation 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -5440,7 +5440,7 @@ exports[`renders bottom navigation with scene animation 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -5504,7 +5504,7 @@ exports[`renders custom icon and label in non-shifting bottom navigation 1`] = ` "flex": 1, }, { - "backgroundColor": "rgba(255, 251, 254, 1)", + "backgroundColor": "rgba(255, 251, 255, 1)", }, ] } @@ -5790,7 +5790,7 @@ exports[`renders custom icon and label in non-shifting bottom navigation 1`] = ` } > Route: 0 @@ -5809,7 +5809,7 @@ exports[`renders custom icon and label in non-shifting bottom navigation 1`] = ` } > Route: 0 @@ -6206,7 +6206,7 @@ exports[`renders custom icon and label in shifting bottom navigation 1`] = ` "flex": 1, }, { - "backgroundColor": "rgba(255, 251, 254, 1)", + "backgroundColor": "rgba(255, 251, 255, 1)", }, ] } @@ -6497,7 +6497,7 @@ exports[`renders custom icon and label in shifting bottom navigation 1`] = ` } > Route: 0 @@ -7200,7 +7200,7 @@ exports[`renders custom icon and label with custom colors in non-shifting bottom "flex": 1, }, { - "backgroundColor": "rgba(255, 251, 254, 1)", + "backgroundColor": "rgba(255, 251, 255, 1)", }, ] } @@ -7553,7 +7553,7 @@ exports[`renders custom icon and label with custom colors in non-shifting bottom "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -7609,7 +7609,7 @@ exports[`renders custom icon and label with custom colors in non-shifting bottom "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -7867,7 +7867,7 @@ exports[`renders custom icon and label with custom colors in non-shifting bottom "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -7923,7 +7923,7 @@ exports[`renders custom icon and label with custom colors in non-shifting bottom "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -8181,7 +8181,7 @@ exports[`renders custom icon and label with custom colors in non-shifting bottom "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -8237,7 +8237,7 @@ exports[`renders custom icon and label with custom colors in non-shifting bottom "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -8301,7 +8301,7 @@ exports[`renders custom icon and label with custom colors in shifting bottom nav "flex": 1, }, { - "backgroundColor": "rgba(255, 251, 254, 1)", + "backgroundColor": "rgba(255, 251, 255, 1)", }, ] } @@ -8659,7 +8659,7 @@ exports[`renders custom icon and label with custom colors in shifting bottom nav "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -8922,7 +8922,7 @@ exports[`renders custom icon and label with custom colors in shifting bottom nav "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -9185,7 +9185,7 @@ exports[`renders custom icon and label with custom colors in shifting bottom nav "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -9249,7 +9249,7 @@ exports[`renders non-shifting bottom navigation 1`] = ` "flex": 1, }, { - "backgroundColor": "rgba(255, 251, 254, 1)", + "backgroundColor": "rgba(255, 251, 255, 1)", }, ] } @@ -9602,7 +9602,7 @@ exports[`renders non-shifting bottom navigation 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -9621,7 +9621,7 @@ exports[`renders non-shifting bottom navigation 1`] = ` "textAlign": "center", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 12, "fontWeight": "500", @@ -9658,7 +9658,7 @@ exports[`renders non-shifting bottom navigation 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -9677,7 +9677,7 @@ exports[`renders non-shifting bottom navigation 1`] = ` "textAlign": "center", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 12, "fontWeight": "500", @@ -9916,7 +9916,7 @@ exports[`renders non-shifting bottom navigation 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -9972,7 +9972,7 @@ exports[`renders non-shifting bottom navigation 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -10230,7 +10230,7 @@ exports[`renders non-shifting bottom navigation 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -10286,7 +10286,7 @@ exports[`renders non-shifting bottom navigation 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -10350,7 +10350,7 @@ exports[`renders shifting bottom navigation 1`] = ` "flex": 1, }, { - "backgroundColor": "rgba(255, 251, 254, 1)", + "backgroundColor": "rgba(255, 251, 255, 1)", }, ] } @@ -10708,7 +10708,7 @@ exports[`renders shifting bottom navigation 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -10727,7 +10727,7 @@ exports[`renders shifting bottom navigation 1`] = ` "textAlign": "center", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 12, "fontWeight": "500", @@ -10971,7 +10971,7 @@ exports[`renders shifting bottom navigation 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -11234,7 +11234,7 @@ exports[`renders shifting bottom navigation 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -11497,7 +11497,7 @@ exports[`renders shifting bottom navigation 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -11760,7 +11760,7 @@ exports[`renders shifting bottom navigation 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ diff --git a/src/components/__tests__/__snapshots__/Button.test.tsx.snap b/src/components/__tests__/__snapshots__/Button.test.tsx.snap index d5f335c3f1..fddcd2bc10 100644 --- a/src/components/__tests__/__snapshots__/Button.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Button.test.tsx.snap @@ -105,7 +105,7 @@ exports[`renders button with an accessibility hint 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -255,7 +255,7 @@ exports[`renders button with an accessibility label 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -404,7 +404,7 @@ exports[`renders button with button color 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -553,7 +553,7 @@ exports[`renders button with color 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -702,7 +702,7 @@ exports[`renders button with custom testID 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -900,7 +900,7 @@ exports[`renders button with icon 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -1100,7 +1100,7 @@ exports[`renders button with icon in reverse order 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -1249,7 +1249,7 @@ exports[`renders contained contained with mode 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -1399,7 +1399,7 @@ exports[`renders disabled button 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -1422,7 +1422,7 @@ exports[`renders disabled button 1`] = ` undefined, false, { - "color": "rgba(28, 27, 31, 0.38)", + "color": "rgba(29, 27, 32, 0.38)", "fontFamily": "System", "fontSize": 14, "fontWeight": "500", @@ -1756,7 +1756,7 @@ exports[`renders loading button 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -1905,7 +1905,7 @@ exports[`renders outlined button with mode 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -2055,7 +2055,7 @@ exports[`renders text button by default 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -2204,7 +2204,7 @@ exports[`renders text button with mode 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ diff --git a/src/components/__tests__/__snapshots__/Chip.test.tsx.snap b/src/components/__tests__/__snapshots__/Chip.test.tsx.snap index 2994761722..f6d6b1379f 100644 --- a/src/components/__tests__/__snapshots__/Chip.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Chip.test.tsx.snap @@ -160,7 +160,7 @@ exports[`renders chip with close button 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -455,7 +455,7 @@ exports[`renders chip with custom close button 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -750,7 +750,7 @@ exports[`renders chip with icon 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -907,7 +907,7 @@ exports[`renders chip with onPress 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -1064,7 +1064,7 @@ exports[`renders outlined disabled chip 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -1081,7 +1081,7 @@ exports[`renders outlined disabled chip 1`] = ` "textAlignVertical": "center", }, { - "color": "rgba(28, 27, 31, 0.38)", + "color": "rgba(29, 27, 32, 0.38)", "fontFamily": "System", "fontSize": 14, "fontWeight": "500", @@ -1266,7 +1266,7 @@ exports[`renders selected chip 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ diff --git a/src/components/__tests__/__snapshots__/DataTable.test.tsx.snap b/src/components/__tests__/__snapshots__/DataTable.test.tsx.snap index 59e80d0aef..7fde640799 100644 --- a/src/components/__tests__/__snapshots__/DataTable.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/DataTable.test.tsx.snap @@ -54,7 +54,7 @@ exports[`DataTable.Cell renders data table cell 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -128,7 +128,7 @@ exports[`DataTable.Cell renders right aligned data table cell 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -213,7 +213,7 @@ exports[`DataTable.Header renders data table header 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -233,7 +233,7 @@ exports[`DataTable.Header renders data table header 1`] = ` }, {}, { - "color": "rgba(28, 27, 31, 0.6)", + "color": "rgba(29, 27, 32, 0.6)", }, undefined, ], @@ -294,7 +294,7 @@ exports[`DataTable.Header renders data table header 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -314,7 +314,7 @@ exports[`DataTable.Header renders data table header 1`] = ` }, {}, { - "color": "rgba(28, 27, 31, 0.6)", + "color": "rgba(29, 27, 32, 0.6)", }, undefined, ], @@ -352,7 +352,7 @@ exports[`DataTable.Pagination renders data table pagination 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -366,7 +366,7 @@ exports[`DataTable.Pagination renders data table pagination 1`] = ` "marginRight": 16, }, { - "color": "rgba(28, 27, 31, 0.6)", + "color": "rgba(29, 27, 32, 0.6)", }, ], ] @@ -489,7 +489,7 @@ exports[`DataTable.Pagination renders data table pagination 1`] = ` style={ [ { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontSize": 24, }, [ @@ -623,7 +623,7 @@ exports[`DataTable.Pagination renders data table pagination 1`] = ` style={ [ { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontSize": 24, }, [ @@ -676,7 +676,7 @@ exports[`DataTable.Pagination renders data table pagination with fast-forward bu "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -690,7 +690,7 @@ exports[`DataTable.Pagination renders data table pagination with fast-forward bu "marginRight": 16, }, { - "color": "rgba(28, 27, 31, 0.6)", + "color": "rgba(29, 27, 32, 0.6)", }, ], ] @@ -815,7 +815,7 @@ exports[`DataTable.Pagination renders data table pagination with fast-forward bu style={ [ { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontSize": 24, }, [ @@ -949,7 +949,7 @@ exports[`DataTable.Pagination renders data table pagination with fast-forward bu style={ [ { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontSize": 24, }, [ @@ -1083,7 +1083,7 @@ exports[`DataTable.Pagination renders data table pagination with fast-forward bu style={ [ { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontSize": 24, }, [ @@ -1217,7 +1217,7 @@ exports[`DataTable.Pagination renders data table pagination with fast-forward bu style={ [ { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontSize": 24, }, [ @@ -1270,7 +1270,7 @@ exports[`DataTable.Pagination renders data table pagination with label 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -1284,7 +1284,7 @@ exports[`DataTable.Pagination renders data table pagination with label 1`] = ` "marginRight": 16, }, { - "color": "rgba(28, 27, 31, 0.6)", + "color": "rgba(29, 27, 32, 0.6)", }, ], ] @@ -1409,7 +1409,7 @@ exports[`DataTable.Pagination renders data table pagination with label 1`] = ` style={ [ { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontSize": 24, }, [ @@ -1543,7 +1543,7 @@ exports[`DataTable.Pagination renders data table pagination with label 1`] = ` style={ [ { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontSize": 24, }, [ @@ -1606,7 +1606,7 @@ exports[`DataTable.Pagination renders data table pagination with options select "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -1620,7 +1620,7 @@ exports[`DataTable.Pagination renders data table pagination with options select "marginRight": 16, }, { - "color": "rgba(28, 27, 31, 0.6)", + "color": "rgba(29, 27, 32, 0.6)", }, ], ] @@ -1784,7 +1784,7 @@ exports[`DataTable.Pagination renders data table pagination with options select "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -1839,7 +1839,7 @@ exports[`DataTable.Pagination renders data table pagination with options select "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -1853,7 +1853,7 @@ exports[`DataTable.Pagination renders data table pagination with options select "marginRight": 16, }, { - "color": "rgba(28, 27, 31, 0.6)", + "color": "rgba(29, 27, 32, 0.6)", }, ], ] @@ -1978,7 +1978,7 @@ exports[`DataTable.Pagination renders data table pagination with options select style={ [ { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontSize": 24, }, [ @@ -2112,7 +2112,7 @@ exports[`DataTable.Pagination renders data table pagination with options select style={ [ { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontSize": 24, }, [ @@ -2246,7 +2246,7 @@ exports[`DataTable.Pagination renders data table pagination with options select style={ [ { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontSize": 24, }, [ @@ -2380,7 +2380,7 @@ exports[`DataTable.Pagination renders data table pagination with options select style={ [ { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontSize": 24, }, [ @@ -2474,7 +2474,7 @@ exports[`DataTable.Title renders data table title with press handler 1`] = ` style={ [ { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontSize": 16, }, [ @@ -2504,7 +2504,7 @@ exports[`DataTable.Title renders data table title with press handler 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -2602,7 +2602,7 @@ exports[`DataTable.Title renders data table title with sort icon 1`] = ` style={ [ { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontSize": 16, }, [ @@ -2632,7 +2632,7 @@ exports[`DataTable.Title renders data table title with sort icon 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -2718,7 +2718,7 @@ exports[`DataTable.Title renders right aligned data table title 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -2738,7 +2738,7 @@ exports[`DataTable.Title renders right aligned data table title 1`] = ` }, {}, { - "color": "rgba(28, 27, 31, 0.6)", + "color": "rgba(29, 27, 32, 0.6)", }, undefined, ], diff --git a/src/components/__tests__/__snapshots__/DrawerItem.test.tsx.snap b/src/components/__tests__/__snapshots__/DrawerItem.test.tsx.snap index e3d5e8ca8b..5746cc089b 100644 --- a/src/components/__tests__/__snapshots__/DrawerItem.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/DrawerItem.test.tsx.snap @@ -122,7 +122,7 @@ exports[`renders DrawerItem with icon 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -281,7 +281,7 @@ exports[`renders active DrawerItem 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -411,7 +411,7 @@ exports[`renders basic DrawerItem 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ diff --git a/src/components/__tests__/__snapshots__/FAB.test.tsx.snap b/src/components/__tests__/__snapshots__/FAB.test.tsx.snap index b4a42c20fa..3eb29a581a 100644 --- a/src/components/__tests__/__snapshots__/FAB.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/FAB.test.tsx.snap @@ -527,7 +527,7 @@ exports[`renders disabled FAB 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(28, 27, 31, 0.12)", + "backgroundColor": "rgba(29, 27, 32, 0.12)", "borderRadius": 16, "opacity": 1, "shadowColor": "#000", @@ -551,7 +551,7 @@ exports[`renders disabled FAB 1`] = ` pointerEvents="auto" style={ { - "backgroundColor": "rgba(28, 27, 31, 0.12)", + "backgroundColor": "rgba(29, 27, 32, 0.12)", "borderRadius": 16, "flex": undefined, "shadowColor": "#000", @@ -667,7 +667,7 @@ exports[`renders disabled FAB 1`] = ` style={ [ { - "color": "rgba(28, 27, 31, 0.38)", + "color": "rgba(29, 27, 32, 0.38)", "fontSize": 24, }, [ @@ -873,7 +873,7 @@ exports[`renders extended FAB 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -1087,7 +1087,7 @@ exports[`renders extended FAB with custom size prop 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ diff --git a/src/components/__tests__/__snapshots__/IconButton.test.tsx.snap b/src/components/__tests__/__snapshots__/IconButton.test.tsx.snap index 1fe2b72a3d..82bcdbac24 100644 --- a/src/components/__tests__/__snapshots__/IconButton.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/IconButton.test.tsx.snap @@ -26,7 +26,7 @@ exports[`renders disabled icon button 1`] = ` style={ { "backgroundColor": "transparent", - "borderColor": "rgba(28, 27, 31, 0.12)", + "borderColor": "rgba(29, 27, 32, 0.12)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -115,7 +115,7 @@ exports[`renders disabled icon button 1`] = ` style={ [ { - "color": "rgba(28, 27, 31, 0.38)", + "color": "rgba(29, 27, 32, 0.38)", "fontSize": 24, }, [ diff --git a/src/components/__tests__/__snapshots__/ListAccordion.test.tsx.snap b/src/components/__tests__/__snapshots__/ListAccordion.test.tsx.snap index 0857e59773..9999e424d2 100644 --- a/src/components/__tests__/__snapshots__/ListAccordion.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/ListAccordion.test.tsx.snap @@ -5,7 +5,7 @@ exports[`renders expanded accordion 1`] = ` @@ -90,7 +90,7 @@ exports[`renders expanded accordion 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -237,7 +237,7 @@ exports[`renders expanded accordion 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -250,7 +250,7 @@ exports[`renders expanded accordion 1`] = ` "fontSize": 16, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, undefined, ], @@ -270,7 +270,7 @@ exports[`renders list accordion with children 1`] = ` @@ -402,7 +402,7 @@ exports[`renders list accordion with children 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -415,7 +415,7 @@ exports[`renders list accordion with children 1`] = ` "fontSize": 16, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, undefined, ], @@ -477,7 +477,7 @@ exports[`renders list accordion with custom title and description styles 1`] = ` @@ -562,7 +562,7 @@ exports[`renders list accordion with custom title and description styles 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -575,7 +575,7 @@ exports[`renders list accordion with custom title and description styles 1`] = ` "fontSize": 16, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, { "color": "#f44336", @@ -596,7 +596,7 @@ exports[`renders list accordion with custom title and description styles 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -677,7 +677,7 @@ exports[`renders list accordion with left items 1`] = ` @@ -809,7 +809,7 @@ exports[`renders list accordion with left items 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -822,7 +822,7 @@ exports[`renders list accordion with left items 1`] = ` "fontSize": 16, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, undefined, ], @@ -884,7 +884,7 @@ exports[`renders multiline list accordion 1`] = ` @@ -969,7 +969,7 @@ exports[`renders multiline list accordion 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -982,7 +982,7 @@ exports[`renders multiline list accordion 1`] = ` "fontSize": 16, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, undefined, ], @@ -1001,7 +1001,7 @@ exports[`renders multiline list accordion 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, diff --git a/src/components/__tests__/__snapshots__/ListItem.test.tsx.snap b/src/components/__tests__/__snapshots__/ListItem.test.tsx.snap index 1f8c683d3a..2ae673d6d3 100644 --- a/src/components/__tests__/__snapshots__/ListItem.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/ListItem.test.tsx.snap @@ -82,7 +82,7 @@ exports[`renders list item with custom description 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -95,7 +95,7 @@ exports[`renders list item with custom description 1`] = ` "fontSize": 16, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, undefined, ], @@ -276,7 +276,7 @@ exports[`renders list item with custom description 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -405,7 +405,7 @@ exports[`renders list item with custom title and description styles 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -418,7 +418,7 @@ exports[`renders list item with custom title and description styles 1`] = ` "fontSize": 16, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, { "fontSize": 20, @@ -439,7 +439,7 @@ exports[`renders list item with custom title and description styles 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -553,7 +553,7 @@ exports[`renders list item with left and right items 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -566,7 +566,7 @@ exports[`renders list item with left and right items 1`] = ` "fontSize": 16, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, undefined, ], @@ -585,7 +585,7 @@ exports[`renders list item with left and right items 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -787,7 +787,7 @@ exports[`renders list item with left item 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -800,7 +800,7 @@ exports[`renders list item with left item 1`] = ` "fontSize": 16, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, undefined, ], @@ -896,7 +896,7 @@ exports[`renders list item with right item 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -909,7 +909,7 @@ exports[`renders list item with right item 1`] = ` "fontSize": 16, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, undefined, ], @@ -1008,7 +1008,7 @@ exports[`renders list item with title and description 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -1021,7 +1021,7 @@ exports[`renders list item with title and description 1`] = ` "fontSize": 16, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, undefined, ], @@ -1040,7 +1040,7 @@ exports[`renders list item with title and description 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -1149,7 +1149,7 @@ exports[`renders with a description with typeof number 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -1162,7 +1162,7 @@ exports[`renders with a description with typeof number 1`] = ` "fontSize": 16, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, { "fontSize": 20, @@ -1183,7 +1183,7 @@ exports[`renders with a description with typeof number 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, diff --git a/src/components/__tests__/__snapshots__/ListSection.test.tsx.snap b/src/components/__tests__/__snapshots__/ListSection.test.tsx.snap index b5bc07c4b8..eccc060089 100644 --- a/src/components/__tests__/__snapshots__/ListSection.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/ListSection.test.tsx.snap @@ -17,7 +17,7 @@ exports[`renders list section with custom title style 1`] = ` }, "colors": { "backdrop": "rgba(50, 47, 55, 0.4)", - "background": "rgba(255, 251, 254, 1)", + "background": "rgba(255, 251, 255, 1)", "elevation": { "level0": "transparent", "level1": "rgb(247, 243, 249)", @@ -28,18 +28,18 @@ exports[`renders list section with custom title style 1`] = ` }, "error": "rgba(179, 38, 30, 1)", "errorContainer": "rgba(249, 222, 220, 1)", - "inverseOnSurface": "rgba(244, 239, 244, 1)", + "inverseOnSurface": "rgba(245, 239, 247, 1)", "inversePrimary": "rgba(208, 188, 255, 1)", - "inverseSurface": "rgba(49, 48, 51, 1)", - "onBackground": "rgba(28, 27, 31, 1)", + "inverseSurface": "rgba(50, 47, 53, 1)", + "onBackground": "rgba(29, 27, 32, 1)", "onError": "rgba(255, 255, 255, 1)", "onErrorContainer": "rgba(65, 14, 11, 1)", "onPrimary": "rgba(255, 255, 255, 1)", "onPrimaryContainer": "rgba(33, 0, 93, 1)", "onSecondary": "rgba(255, 255, 255, 1)", "onSecondaryContainer": "rgba(29, 25, 43, 1)", - "onSurface": "rgba(28, 27, 31, 1)", - "onSurfaceDisabled": "rgba(28, 27, 31, 0.38)", + "onSurface": "rgba(29, 27, 32, 1)", + "onSurfaceDisabled": "rgba(29, 27, 32, 0.38)", "onSurfaceVariant": "rgba(73, 69, 79, 1)", "onTertiary": "rgba(255, 255, 255, 1)", "onTertiaryContainer": "rgba(49, 17, 29, 1)", @@ -51,8 +51,8 @@ exports[`renders list section with custom title style 1`] = ` "secondary": "rgba(98, 91, 113, 1)", "secondaryContainer": "rgba(232, 222, 248, 1)", "shadow": "rgba(0, 0, 0, 1)", - "surface": "rgba(255, 251, 254, 1)", - "surfaceDisabled": "rgba(28, 27, 31, 0.12)", + "surface": "rgba(255, 251, 255, 1)", + "surfaceDisabled": "rgba(29, 27, 32, 0.12)", "surfaceVariant": "rgba(231, 224, 236, 1)", "tertiary": "rgba(125, 82, 96, 1)", "tertiaryContainer": "rgba(255, 216, 228, 1)", @@ -184,7 +184,7 @@ exports[`renders list section with custom title style 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -346,7 +346,7 @@ exports[`renders list section with custom title style 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -359,7 +359,7 @@ exports[`renders list section with custom title style 1`] = ` "fontSize": 16, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, undefined, ], @@ -499,7 +499,7 @@ exports[`renders list section with custom title style 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -512,7 +512,7 @@ exports[`renders list section with custom title style 1`] = ` "fontSize": 16, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, undefined, ], @@ -544,7 +544,7 @@ exports[`renders list section with subheader 1`] = ` }, "colors": { "backdrop": "rgba(50, 47, 55, 0.4)", - "background": "rgba(255, 251, 254, 1)", + "background": "rgba(255, 251, 255, 1)", "elevation": { "level0": "transparent", "level1": "rgb(247, 243, 249)", @@ -555,18 +555,18 @@ exports[`renders list section with subheader 1`] = ` }, "error": "rgba(179, 38, 30, 1)", "errorContainer": "rgba(249, 222, 220, 1)", - "inverseOnSurface": "rgba(244, 239, 244, 1)", + "inverseOnSurface": "rgba(245, 239, 247, 1)", "inversePrimary": "rgba(208, 188, 255, 1)", - "inverseSurface": "rgba(49, 48, 51, 1)", - "onBackground": "rgba(28, 27, 31, 1)", + "inverseSurface": "rgba(50, 47, 53, 1)", + "onBackground": "rgba(29, 27, 32, 1)", "onError": "rgba(255, 255, 255, 1)", "onErrorContainer": "rgba(65, 14, 11, 1)", "onPrimary": "rgba(255, 255, 255, 1)", "onPrimaryContainer": "rgba(33, 0, 93, 1)", "onSecondary": "rgba(255, 255, 255, 1)", "onSecondaryContainer": "rgba(29, 25, 43, 1)", - "onSurface": "rgba(28, 27, 31, 1)", - "onSurfaceDisabled": "rgba(28, 27, 31, 0.38)", + "onSurface": "rgba(29, 27, 32, 1)", + "onSurfaceDisabled": "rgba(29, 27, 32, 0.38)", "onSurfaceVariant": "rgba(73, 69, 79, 1)", "onTertiary": "rgba(255, 255, 255, 1)", "onTertiaryContainer": "rgba(49, 17, 29, 1)", @@ -578,8 +578,8 @@ exports[`renders list section with subheader 1`] = ` "secondary": "rgba(98, 91, 113, 1)", "secondaryContainer": "rgba(232, 222, 248, 1)", "shadow": "rgba(0, 0, 0, 1)", - "surface": "rgba(255, 251, 254, 1)", - "surfaceDisabled": "rgba(28, 27, 31, 0.12)", + "surface": "rgba(255, 251, 255, 1)", + "surfaceDisabled": "rgba(29, 27, 32, 0.12)", "surfaceVariant": "rgba(231, 224, 236, 1)", "tertiary": "rgba(125, 82, 96, 1)", "tertiaryContainer": "rgba(255, 216, 228, 1)", @@ -711,7 +711,7 @@ exports[`renders list section with subheader 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -871,7 +871,7 @@ exports[`renders list section with subheader 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -884,7 +884,7 @@ exports[`renders list section with subheader 1`] = ` "fontSize": 16, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, undefined, ], @@ -1024,7 +1024,7 @@ exports[`renders list section with subheader 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -1037,7 +1037,7 @@ exports[`renders list section with subheader 1`] = ` "fontSize": 16, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, undefined, ], @@ -1069,7 +1069,7 @@ exports[`renders list section without subheader 1`] = ` }, "colors": { "backdrop": "rgba(50, 47, 55, 0.4)", - "background": "rgba(255, 251, 254, 1)", + "background": "rgba(255, 251, 255, 1)", "elevation": { "level0": "transparent", "level1": "rgb(247, 243, 249)", @@ -1080,18 +1080,18 @@ exports[`renders list section without subheader 1`] = ` }, "error": "rgba(179, 38, 30, 1)", "errorContainer": "rgba(249, 222, 220, 1)", - "inverseOnSurface": "rgba(244, 239, 244, 1)", + "inverseOnSurface": "rgba(245, 239, 247, 1)", "inversePrimary": "rgba(208, 188, 255, 1)", - "inverseSurface": "rgba(49, 48, 51, 1)", - "onBackground": "rgba(28, 27, 31, 1)", + "inverseSurface": "rgba(50, 47, 53, 1)", + "onBackground": "rgba(29, 27, 32, 1)", "onError": "rgba(255, 255, 255, 1)", "onErrorContainer": "rgba(65, 14, 11, 1)", "onPrimary": "rgba(255, 255, 255, 1)", "onPrimaryContainer": "rgba(33, 0, 93, 1)", "onSecondary": "rgba(255, 255, 255, 1)", "onSecondaryContainer": "rgba(29, 25, 43, 1)", - "onSurface": "rgba(28, 27, 31, 1)", - "onSurfaceDisabled": "rgba(28, 27, 31, 0.38)", + "onSurface": "rgba(29, 27, 32, 1)", + "onSurfaceDisabled": "rgba(29, 27, 32, 0.38)", "onSurfaceVariant": "rgba(73, 69, 79, 1)", "onTertiary": "rgba(255, 255, 255, 1)", "onTertiaryContainer": "rgba(49, 17, 29, 1)", @@ -1103,8 +1103,8 @@ exports[`renders list section without subheader 1`] = ` "secondary": "rgba(98, 91, 113, 1)", "secondaryContainer": "rgba(232, 222, 248, 1)", "shadow": "rgba(0, 0, 0, 1)", - "surface": "rgba(255, 251, 254, 1)", - "surfaceDisabled": "rgba(28, 27, 31, 0.12)", + "surface": "rgba(255, 251, 255, 1)", + "surfaceDisabled": "rgba(29, 27, 32, 0.12)", "surfaceVariant": "rgba(231, 224, 236, 1)", "tertiary": "rgba(125, 82, 96, 1)", "tertiaryContainer": "rgba(255, 216, 228, 1)", @@ -1356,7 +1356,7 @@ exports[`renders list section without subheader 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -1369,7 +1369,7 @@ exports[`renders list section without subheader 1`] = ` "fontSize": 16, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, undefined, ], @@ -1509,7 +1509,7 @@ exports[`renders list section without subheader 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontWeight": "400", "letterSpacing": 0, @@ -1522,7 +1522,7 @@ exports[`renders list section without subheader 1`] = ` "fontSize": 16, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", }, undefined, ], diff --git a/src/components/__tests__/__snapshots__/Menu.test.tsx.snap b/src/components/__tests__/__snapshots__/Menu.test.tsx.snap index f2a20c8047..a20d7ed8d7 100644 --- a/src/components/__tests__/__snapshots__/Menu.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Menu.test.tsx.snap @@ -117,7 +117,7 @@ exports[`renders menu with content styles 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -394,7 +394,7 @@ exports[`renders menu with content styles 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -407,7 +407,7 @@ exports[`renders menu with content styles 1`] = ` }, [ { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 16, "fontWeight": "400", @@ -515,7 +515,7 @@ exports[`renders menu with content styles 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -528,7 +528,7 @@ exports[`renders menu with content styles 1`] = ` }, [ { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 16, "fontWeight": "400", @@ -671,7 +671,7 @@ exports[`renders not visible menu 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -836,7 +836,7 @@ exports[`renders visible menu 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -1109,7 +1109,7 @@ exports[`renders visible menu 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -1122,7 +1122,7 @@ exports[`renders visible menu 1`] = ` }, [ { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 16, "fontWeight": "400", @@ -1230,7 +1230,7 @@ exports[`renders visible menu 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -1243,7 +1243,7 @@ exports[`renders visible menu 1`] = ` }, [ { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 16, "fontWeight": "400", diff --git a/src/components/__tests__/__snapshots__/MenuItem.test.tsx.snap b/src/components/__tests__/__snapshots__/MenuItem.test.tsx.snap index a34067f576..069b8c854d 100644 --- a/src/components/__tests__/__snapshots__/MenuItem.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/MenuItem.test.tsx.snap @@ -131,7 +131,7 @@ exports[`Menu Item renders menu item 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -144,7 +144,7 @@ exports[`Menu Item renders menu item 1`] = ` }, [ { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 16, "fontWeight": "400", @@ -292,7 +292,7 @@ exports[`Menu Item renders menu item 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -305,7 +305,7 @@ exports[`Menu Item renders menu item 1`] = ` }, [ { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 16, "fontWeight": "400", @@ -403,7 +403,7 @@ exports[`Menu Item renders menu item 1`] = ` style={ [ { - "color": "rgba(28, 27, 31, 0.38)", + "color": "rgba(29, 27, 32, 0.38)", "fontSize": 24, }, [ @@ -453,7 +453,7 @@ exports[`Menu Item renders menu item 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -466,7 +466,7 @@ exports[`Menu Item renders menu item 1`] = ` }, [ { - "color": "rgba(28, 27, 31, 0.38)", + "color": "rgba(29, 27, 32, 0.38)", "fontFamily": "System", "fontSize": 16, "fontWeight": "400", @@ -564,7 +564,7 @@ exports[`Menu Item renders menu item 1`] = ` style={ [ { - "color": "rgba(28, 27, 31, 0.38)", + "color": "rgba(29, 27, 32, 0.38)", "fontSize": 24, }, [ @@ -614,7 +614,7 @@ exports[`Menu Item renders menu item 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -627,7 +627,7 @@ exports[`Menu Item renders menu item 1`] = ` }, [ { - "color": "rgba(28, 27, 31, 0.38)", + "color": "rgba(29, 27, 32, 0.38)", "fontFamily": "System", "fontSize": 16, "fontWeight": "400", @@ -735,7 +735,7 @@ exports[`Menu Item renders menu item 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -748,7 +748,7 @@ exports[`Menu Item renders menu item 1`] = ` }, [ { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 16, "fontWeight": "400", diff --git a/src/components/__tests__/__snapshots__/Searchbar.test.tsx.snap b/src/components/__tests__/__snapshots__/Searchbar.test.tsx.snap index f30e19f3f8..769a053662 100644 --- a/src/components/__tests__/__snapshots__/Searchbar.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Searchbar.test.tsx.snap @@ -176,7 +176,7 @@ exports[`activity indicator snapshot test 1`] = ` accessibilityRole="search" keyboardAppearance="light" placeholder="" - placeholderTextColor="rgba(28, 27, 31, 1)" + placeholderTextColor="rgba(29, 27, 32, 1)" returnKeyType="search" selectionColor="rgba(103, 80, 164, 1)" style={ @@ -586,7 +586,7 @@ exports[`renders with placeholder 1`] = ` accessibilityRole="search" keyboardAppearance="light" placeholder="Search" - placeholderTextColor="rgba(28, 27, 31, 1)" + placeholderTextColor="rgba(29, 27, 32, 1)" returnKeyType="search" selectionColor="rgba(103, 80, 164, 1)" style={ @@ -947,7 +947,7 @@ exports[`renders with text 1`] = ` accessibilityRole="search" keyboardAppearance="light" placeholder="Search" - placeholderTextColor="rgba(28, 27, 31, 1)" + placeholderTextColor="rgba(29, 27, 32, 1)" returnKeyType="search" selectionColor="rgba(103, 80, 164, 1)" style={ diff --git a/src/components/__tests__/__snapshots__/SegmentedButton.test.tsx.snap b/src/components/__tests__/__snapshots__/SegmentedButton.test.tsx.snap index 83f1541397..914c9d8c8a 100644 --- a/src/components/__tests__/__snapshots__/SegmentedButton.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/SegmentedButton.test.tsx.snap @@ -105,7 +105,7 @@ exports[`renders segmented button 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -230,7 +230,7 @@ exports[`renders segmented button 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -246,7 +246,7 @@ exports[`renders segmented button 1`] = ` "textAlign": "center", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 14, "fontWeight": "500", diff --git a/src/components/__tests__/__snapshots__/Snackbar.test.tsx.snap b/src/components/__tests__/__snapshots__/Snackbar.test.tsx.snap index b859166348..401868fabf 100644 --- a/src/components/__tests__/__snapshots__/Snackbar.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Snackbar.test.tsx.snap @@ -24,7 +24,7 @@ exports[`renders snackbar with Text as a child 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(49, 48, 51, 1)", + "backgroundColor": "rgba(50, 47, 53, 1)", "borderRadius": 4, "margin": 8, "opacity": 0, @@ -50,7 +50,7 @@ exports[`renders snackbar with Text as a child 1`] = ` pointerEvents="box-none" style={ { - "backgroundColor": "rgba(49, 48, 51, 1)", + "backgroundColor": "rgba(50, 47, 53, 1)", "borderRadius": 4, "flex": undefined, "flexDirection": "row", @@ -112,7 +112,7 @@ exports[`renders snackbar with View & Text as a child 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(49, 48, 51, 1)", + "backgroundColor": "rgba(50, 47, 53, 1)", "borderRadius": 4, "margin": 8, "opacity": 0, @@ -138,7 +138,7 @@ exports[`renders snackbar with View & Text as a child 1`] = ` pointerEvents="box-none" style={ { - "backgroundColor": "rgba(49, 48, 51, 1)", + "backgroundColor": "rgba(50, 47, 53, 1)", "borderRadius": 4, "flex": undefined, "flexDirection": "row", @@ -226,7 +226,7 @@ exports[`renders snackbar with action button 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(49, 48, 51, 1)", + "backgroundColor": "rgba(50, 47, 53, 1)", "borderRadius": 4, "margin": 8, "opacity": 0, @@ -252,7 +252,7 @@ exports[`renders snackbar with action button 1`] = ` pointerEvents="box-none" style={ { - "backgroundColor": "rgba(49, 48, 51, 1)", + "backgroundColor": "rgba(50, 47, 53, 1)", "borderRadius": 4, "flex": undefined, "flexDirection": "row", @@ -276,7 +276,7 @@ exports[`renders snackbar with action button 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -294,7 +294,7 @@ exports[`renders snackbar with action button 1`] = ` "marginVertical": 14, }, { - "color": "rgba(244, 239, 244, 1)", + "color": "rgba(245, 239, 247, 1)", }, ], ], @@ -423,7 +423,7 @@ exports[`renders snackbar with action button 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -494,7 +494,7 @@ exports[`renders snackbar with content 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(49, 48, 51, 1)", + "backgroundColor": "rgba(50, 47, 53, 1)", "borderRadius": 4, "margin": 8, "opacity": 0, @@ -520,7 +520,7 @@ exports[`renders snackbar with content 1`] = ` pointerEvents="box-none" style={ { - "backgroundColor": "rgba(49, 48, 51, 1)", + "backgroundColor": "rgba(50, 47, 53, 1)", "borderRadius": 4, "flex": undefined, "flexDirection": "row", @@ -544,7 +544,7 @@ exports[`renders snackbar with content 1`] = ` "textAlign": "left", }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "writingDirection": "ltr", }, [ @@ -562,7 +562,7 @@ exports[`renders snackbar with content 1`] = ` "marginVertical": 14, }, { - "color": "rgba(244, 239, 244, 1)", + "color": "rgba(245, 239, 247, 1)", }, ], ], diff --git a/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap b/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap index 76ad8d4e54..4bc6f8107f 100644 --- a/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap @@ -199,7 +199,7 @@ exports[`call onPress when affix adornment pressed 1`] = ` "paddingTop": 24, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, @@ -513,7 +513,7 @@ exports[`correctly applies a component as the text label 1`] = ` "paddingTop": 24, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, @@ -739,7 +739,7 @@ exports[`correctly applies cursorColor prop 1`] = ` "paddingTop": 24, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, @@ -965,7 +965,7 @@ exports[`correctly applies default textAlign based on default RTL 1`] = ` "paddingTop": 24, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, @@ -1009,7 +1009,7 @@ exports[`correctly applies height to multiline Outline TextInput 1`] = ` }, false, { - "backgroundColor": "rgba(255, 251, 254, 1)", + "backgroundColor": "rgba(255, 251, 255, 1)", "borderColor": "rgba(121, 116, 126, 1)", "borderRadius": 4, "borderWidth": 1, @@ -1086,7 +1086,7 @@ exports[`correctly applies height to multiline Outline TextInput 1`] = ` numberOfLines={1} style={ { - "backgroundColor": "rgba(255, 251, 254, 1)", + "backgroundColor": "rgba(255, 251, 255, 1)", "color": "transparent", "fontFamily": "System", "fontSize": 16, @@ -1225,7 +1225,7 @@ exports[`correctly applies height to multiline Outline TextInput 1`] = ` "paddingTop": 24, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, @@ -1450,7 +1450,7 @@ exports[`correctly applies paddingLeft from contentStyleProp 1`] = ` "paddingTop": 24, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, @@ -1678,7 +1678,7 @@ exports[`correctly applies textAlign center 1`] = ` "paddingTop": 24, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, @@ -1904,7 +1904,7 @@ exports[`correctly renders left-side affix adornment, and right-side icon adornm "paddingTop": 24, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, @@ -2323,7 +2323,7 @@ exports[`correctly renders left-side icon adornment, and right-side affix adornm "paddingTop": 24, }, { - "color": "rgba(28, 27, 31, 1)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, diff --git a/src/components/__tests__/__snapshots__/ToggleButton.test.tsx.snap b/src/components/__tests__/__snapshots__/ToggleButton.test.tsx.snap index 456c0402fa..0e475cd073 100644 --- a/src/components/__tests__/__snapshots__/ToggleButton.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/ToggleButton.test.tsx.snap @@ -113,7 +113,7 @@ exports[`renders disabled toggle button 1`] = ` style={ [ { - "color": "rgba(28, 27, 31, 0.38)", + "color": "rgba(29, 27, 32, 0.38)", "fontSize": 24, }, [ @@ -386,7 +386,7 @@ exports[`renders unchecked toggle button 1`] = ` style={ [ { - "color": "rgba(28, 27, 31, 0.38)", + "color": "rgba(29, 27, 32, 0.38)", "fontSize": 24, }, [ diff --git a/src/styles/themes/v3/tokens.tsx b/src/styles/themes/v3/tokens.tsx index d008944d86..6eb27445fd 100644 --- a/src/styles/themes/v3/tokens.tsx +++ b/src/styles/themes/v3/tokens.tsx @@ -6,6 +6,7 @@ const ref = { palette: { primary100: 'rgba(255, 255, 255, 1)', primary99: 'rgba(255, 251, 254, 1)', + primary98: 'rgba(254, 247, 255, 1)', primary95: 'rgba(246, 237, 255, 1)', primary90: 'rgba(234, 221, 255, 1)', primary80: 'rgba(208, 188, 255, 1)', @@ -19,6 +20,7 @@ const ref = { primary0: 'rgba(0, 0, 0, 1)', secondary100: 'rgba(255, 255, 255, 1)', secondary99: 'rgba(255, 251, 254, 1)', + secondary98: 'rgba(254, 247, 255, 1)', secondary95: 'rgba(246, 237, 255, 1)', secondary90: 'rgba(232, 222, 248, 1)', secondary80: 'rgba(204, 194, 220, 1)', @@ -32,6 +34,7 @@ const ref = { secondary0: 'rgba(0, 0, 0, 1)', tertiary100: 'rgba(255, 255, 255, 1)', tertiary99: 'rgba(255, 251, 250, 1)', + tertiary98: 'rgba(255, 248, 248, 1)', tertiary95: 'rgba(255, 236, 241, 1)', tertiary90: 'rgba(255, 216, 228, 1)', tertiary80: 'rgba(239, 184, 200, 1)', @@ -44,20 +47,32 @@ const ref = { tertiary10: 'rgba(49, 17, 29, 1)', tertiary0: 'rgba(0, 0, 0, 1)', neutral100: 'rgba(255, 255, 255, 1)', - neutral99: 'rgba(255, 251, 254, 1)', - neutral95: 'rgba(244, 239, 244, 1)', - neutral90: 'rgba(230, 225, 229, 1)', - neutral80: 'rgba(201, 197, 202, 1)', - neutral70: 'rgba(174, 170, 174, 1)', - neutral60: 'rgba(147, 144, 148, 1)', - neutral50: 'rgba(120, 117, 121, 1)', - neutral40: 'rgba(96, 93, 98, 1)', - neutral30: 'rgba(72, 70, 73, 1)', - neutral20: 'rgba(49, 48, 51, 1)', - neutral10: 'rgba(28, 27, 31, 1)', + neutral99: 'rgba(255, 251, 255, 1)', + neutral98: 'rgba(254, 247, 255, 1)', + neutral96: 'rgba(247, 242, 250, 1)', + neutral95: 'rgba(245, 239, 247, 1)', + neutral94: 'rgba(243, 237, 247, 1)', + neutral92: 'rgba(236, 230, 240, 1)', + neutral90: 'rgba(230, 224, 233, 1)', + neutral87: 'rgba(222, 216, 225, 1)', + neutral80: 'rgba(202, 197, 205, 1)', + neutral70: 'rgba(174, 169, 177, 1)', + neutral60: 'rgba(147, 143, 150, 1)', + neutral50: 'rgba(121, 118, 125, 1)', + neutral40: 'rgba(96, 93, 100, 1)', + neutral30: 'rgba(72, 70, 76, 1)', + neutral24: 'rgba(59, 56, 62, 1)', + neutral22: 'rgba(54, 52, 59, 1)', + neutral20: 'rgba(50, 47, 53, 1)', + neutral17: 'rgba(43, 41, 48, 1)', + neutral12: 'rgba(33, 31, 38, 1)', + neutral10: 'rgba(29, 27, 32, 1)', + neutral6: 'rgba(20, 18, 24, 1)', + neutral4: 'rgba(15, 13, 19, 1)', neutral0: 'rgba(0, 0, 0, 1)', neutralVariant100: 'rgba(255, 255, 255, 1)', neutralVariant99: 'rgba(255, 251, 254, 1)', + neutralVariant98: 'rgba(253, 247, 255, 1)', neutralVariant95: 'rgba(245, 238, 250, 1)', neutralVariant90: 'rgba(231, 224, 236, 1)', neutralVariant80: 'rgba(202, 196, 208, 1)', @@ -71,6 +86,7 @@ const ref = { neutralVariant0: 'rgba(0, 0, 0, 1)', error100: 'rgba(255, 255, 255, 1)', error99: 'rgba(255, 251, 249, 1)', + error98: 'rgba(255, 248, 247, 1)', error95: 'rgba(252, 238, 238, 1)', error90: 'rgba(249, 222, 220, 1)', error80: 'rgba(242, 184, 181, 1)', From dacdfae5dbeda8e98be7574a8f1578f9c901a109 Mon Sep 17 00:00:00 2001 From: Adrian Cotfas Date: Fri, 10 Apr 2026 15:15:22 +0300 Subject: [PATCH 08/13] fix: update the color schema for LightTheme and DarkTheme * see: https://m3.material.io/styles/color/roles --- example/src/index.native.tsx | 7 +- example/utils/index.ts | 28 +++--- .../__tests__/Appbar/Appbar.test.tsx | 4 +- .../Appbar/__snapshots__/Appbar.test.tsx.snap | 12 +-- .../Card/__snapshots__/Card.test.tsx.snap | 4 +- .../__snapshots__/Banner.test.tsx.snap | 24 ++--- .../BottomNavigation.test.tsx.snap | 44 ++++----- .../__snapshots__/ListAccordion.test.tsx.snap | 10 +- .../__snapshots__/ListSection.test.tsx.snap | 99 +++++++++++++++---- .../__snapshots__/Menu.test.tsx.snap | 8 +- .../__snapshots__/Searchbar.test.tsx.snap | 12 +-- .../__snapshots__/TextInput.test.tsx.snap | 4 +- src/styles/themes/v3/DarkTheme.tsx | 36 +++++-- src/styles/themes/v3/LightTheme.tsx | 36 +++++-- src/types.tsx | 19 ++++ 15 files changed, 229 insertions(+), 118 deletions(-) diff --git a/example/src/index.native.tsx b/example/src/index.native.tsx index fae347d85d..6ca9b27077 100644 --- a/example/src/index.native.tsx +++ b/example/src/index.native.tsx @@ -57,8 +57,11 @@ export default function PaperExample() { } return isDarkMode - ? { ...MD3DarkTheme, colors: mdTheme.dark } - : { ...MD3LightTheme, colors: mdTheme.light }; + ? { ...MD3DarkTheme, colors: { ...MD3DarkTheme.colors, ...mdTheme.dark } } + : { + ...MD3LightTheme, + colors: { ...MD3LightTheme.colors, ...mdTheme.light }, + }; }, [isDarkMode, mdTheme, shouldUseDeviceColors]); React.useEffect(() => { diff --git a/example/utils/index.ts b/example/utils/index.ts index 5c15917644..f86f3a0307 100644 --- a/example/utils/index.ts +++ b/example/utils/index.ts @@ -1162,71 +1162,71 @@ export const colorThemes = { pink: { light: { ...MD3LightTheme, - ...lightPinkColors, + colors: { ...MD3LightTheme.colors, ...lightPinkColors.colors }, }, dark: { ...MD3DarkTheme, - ...darkPinkColors, + colors: { ...MD3DarkTheme.colors, ...darkPinkColors.colors }, }, }, green: { light: { ...MD3LightTheme, - ...lightGreenColors, + colors: { ...MD3LightTheme.colors, ...lightGreenColors.colors }, }, dark: { ...MD3DarkTheme, - ...darkGreenColors, + colors: { ...MD3DarkTheme.colors, ...darkGreenColors.colors }, }, }, blue: { light: { ...MD3LightTheme, - ...lightBlueColors, + colors: { ...MD3LightTheme.colors, ...lightBlueColors.colors }, }, dark: { ...MD3DarkTheme, - ...darkBlueColors, + colors: { ...MD3DarkTheme.colors, ...darkBlueColors.colors }, }, }, orange: { light: { ...MD3LightTheme, - ...lightOrangeColors, + colors: { ...MD3LightTheme.colors, ...lightOrangeColors.colors }, }, dark: { ...MD3DarkTheme, - ...darkOrangeColors, + colors: { ...MD3DarkTheme.colors, ...darkOrangeColors.colors }, }, }, red: { light: { ...MD3LightTheme, - ...lightRedColors, + colors: { ...MD3LightTheme.colors, ...lightRedColors.colors }, }, dark: { ...MD3DarkTheme, - ...darkRedColors, + colors: { ...MD3DarkTheme.colors, ...darkRedColors.colors }, }, }, yellow: { light: { ...MD3LightTheme, - ...lightYellowColors, + colors: { ...MD3LightTheme.colors, ...lightYellowColors.colors }, }, dark: { ...MD3DarkTheme, - ...darkYellowColors, + colors: { ...MD3DarkTheme.colors, ...darkYellowColors.colors }, }, }, cyan: { light: { ...MD3LightTheme, - ...lightCyanColors, + colors: { ...MD3LightTheme.colors, ...lightCyanColors.colors }, }, dark: { ...MD3DarkTheme, - ...darkCyanColors, + colors: { ...MD3DarkTheme.colors, ...darkCyanColors.colors }, }, }, } as { [key: string]: { light: MD3Theme; dark: MD3Theme } }; diff --git a/src/components/__tests__/Appbar/Appbar.test.tsx b/src/components/__tests__/Appbar/Appbar.test.tsx index 60a7827b6e..6c80269a0f 100644 --- a/src/components/__tests__/Appbar/Appbar.test.tsx +++ b/src/components/__tests__/Appbar/Appbar.test.tsx @@ -303,13 +303,13 @@ describe('getAppbarColors', () => { it('should return v3 light color if theme version is 3', () => { expect(getAppbarBackgroundColor(getTheme(), elevation)).toBe( - tokens.md.ref.palette.neutral99 + tokens.md.ref.palette.neutral98 ); }); it('should return v3 dark color if theme version is 3', () => { expect(getAppbarBackgroundColor(getTheme(true), elevation)).toBe( - tokens.md.ref.palette.neutral10 + tokens.md.ref.palette.neutral6 ); }); }); diff --git a/src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap b/src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap index 6a2a882d9d..50ab8e3cd6 100644 --- a/src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap +++ b/src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap @@ -5,7 +5,7 @@ exports[`Appbar does not pass any additional props to Searchbar 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(255, 251, 255, 1)", + "backgroundColor": "rgba(254, 247, 255, 1)", "height": 64, "shadowColor": "#000", "shadowOffset": { @@ -23,7 +23,7 @@ exports[`Appbar does not pass any additional props to Searchbar 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgba(255, 251, 255, 1)", + "backgroundColor": "rgba(254, 247, 255, 1)", "flex": 1, "flexDirection": "row", "paddingBottom": undefined, @@ -46,7 +46,7 @@ exports[`Appbar does not pass any additional props to Searchbar 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgb(238, 232, 244)", + "backgroundColor": "rgba(243, 237, 247, 1)", "borderRadius": 28, "shadowColor": "#000", "shadowOffset": { @@ -64,7 +64,7 @@ exports[`Appbar does not pass any additional props to Searchbar 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgb(238, 232, 244)", + "backgroundColor": "rgba(243, 237, 247, 1)", "borderRadius": 28, "flex": undefined, "flexDirection": "row", @@ -409,7 +409,7 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A collapsable={false} style={ { - "backgroundColor": "rgba(255, 251, 255, 1)", + "backgroundColor": "rgba(254, 247, 255, 1)", "height": 64, "shadowColor": "#000", "shadowOffset": { @@ -427,7 +427,7 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A style={ { "alignItems": "center", - "backgroundColor": "rgba(255, 251, 255, 1)", + "backgroundColor": "rgba(254, 247, 255, 1)", "flex": 1, "flexDirection": "row", "paddingBottom": undefined, diff --git a/src/components/__tests__/Card/__snapshots__/Card.test.tsx.snap b/src/components/__tests__/Card/__snapshots__/Card.test.tsx.snap index 4739d5009c..a5a8abd1ac 100644 --- a/src/components/__tests__/Card/__snapshots__/Card.test.tsx.snap +++ b/src/components/__tests__/Card/__snapshots__/Card.test.tsx.snap @@ -5,7 +5,7 @@ exports[`Card renders an outlined card 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(255, 251, 255, 1)", + "backgroundColor": "rgba(254, 247, 255, 1)", "borderRadius": 12, "shadowColor": "#000", "shadowOffset": { @@ -22,7 +22,7 @@ exports[`Card renders an outlined card 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(255, 251, 255, 1)", + "backgroundColor": "rgba(254, 247, 255, 1)", "borderRadius": 12, "flex": undefined, "shadowColor": "#000", diff --git a/src/components/__tests__/__snapshots__/Banner.test.tsx.snap b/src/components/__tests__/__snapshots__/Banner.test.tsx.snap index e92d72a81a..0a61a1a3de 100644 --- a/src/components/__tests__/__snapshots__/Banner.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Banner.test.tsx.snap @@ -5,7 +5,7 @@ exports[`render visible banner, with custom theme 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgb(247, 243, 249)", + "backgroundColor": "rgba(255, 255, 255, 1)", "opacity": 1, "shadowColor": "#000", "shadowOffset": { @@ -22,7 +22,7 @@ exports[`render visible banner, with custom theme 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgb(247, 243, 249)", + "backgroundColor": "rgba(255, 255, 255, 1)", "flex": undefined, "shadowColor": "#000", "shadowOffset": { @@ -278,7 +278,7 @@ exports[`renders hidden banner, without action buttons and without image 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgb(247, 243, 249)", + "backgroundColor": "rgba(255, 255, 255, 1)", "opacity": 0, "shadowColor": "#000", "shadowOffset": { @@ -295,7 +295,7 @@ exports[`renders hidden banner, without action buttons and without image 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgb(247, 243, 249)", + "backgroundColor": "rgba(255, 255, 255, 1)", "flex": undefined, "shadowColor": "#000", "shadowOffset": { @@ -413,7 +413,7 @@ exports[`renders visible banner, with action buttons and with image 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgb(247, 243, 249)", + "backgroundColor": "rgba(255, 255, 255, 1)", "opacity": 1, "shadowColor": "#000", "shadowOffset": { @@ -430,7 +430,7 @@ exports[`renders visible banner, with action buttons and with image 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgb(247, 243, 249)", + "backgroundColor": "rgba(255, 255, 255, 1)", "flex": undefined, "shadowColor": "#000", "shadowOffset": { @@ -708,7 +708,7 @@ exports[`renders visible banner, with action buttons and without image 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgb(247, 243, 249)", + "backgroundColor": "rgba(255, 255, 255, 1)", "opacity": 1, "shadowColor": "#000", "shadowOffset": { @@ -725,7 +725,7 @@ exports[`renders visible banner, with action buttons and without image 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgb(247, 243, 249)", + "backgroundColor": "rgba(255, 255, 255, 1)", "flex": undefined, "shadowColor": "#000", "shadowOffset": { @@ -1130,7 +1130,7 @@ exports[`renders visible banner, without action buttons and with image 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgb(247, 243, 249)", + "backgroundColor": "rgba(255, 255, 255, 1)", "opacity": 1, "shadowColor": "#000", "shadowOffset": { @@ -1147,7 +1147,7 @@ exports[`renders visible banner, without action buttons and with image 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgb(247, 243, 249)", + "backgroundColor": "rgba(255, 255, 255, 1)", "flex": undefined, "shadowColor": "#000", "shadowOffset": { @@ -1275,7 +1275,7 @@ exports[`renders visible banner, without action buttons and without image 1`] = collapsable={false} style={ { - "backgroundColor": "rgb(247, 243, 249)", + "backgroundColor": "rgba(255, 255, 255, 1)", "opacity": 1, "shadowColor": "#000", "shadowOffset": { @@ -1292,7 +1292,7 @@ exports[`renders visible banner, without action buttons and without image 1`] = collapsable={false} style={ { - "backgroundColor": "rgb(247, 243, 249)", + "backgroundColor": "rgba(255, 255, 255, 1)", "flex": undefined, "shadowColor": "#000", "shadowOffset": { diff --git a/src/components/__tests__/__snapshots__/BottomNavigation.test.tsx.snap b/src/components/__tests__/__snapshots__/BottomNavigation.test.tsx.snap index 276f2b1bb3..6bc02934ba 100644 --- a/src/components/__tests__/__snapshots__/BottomNavigation.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/BottomNavigation.test.tsx.snap @@ -20,7 +20,7 @@ exports[`allows customizing Route's type via generics 1`] = ` "flex": 1, }, { - "backgroundColor": "rgba(255, 251, 255, 1)", + "backgroundColor": "rgba(254, 247, 255, 1)", }, ] } @@ -113,7 +113,7 @@ exports[`allows customizing Route's type via generics 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgb(243, 237, 246)", + "backgroundColor": "rgba(247, 242, 250, 1)", "overflow": "hidden", } } @@ -687,7 +687,7 @@ exports[`hides labels in non-shifting bottom navigation 1`] = ` "flex": 1, }, { - "backgroundColor": "rgba(255, 251, 255, 1)", + "backgroundColor": "rgba(254, 247, 255, 1)", }, ] } @@ -780,7 +780,7 @@ exports[`hides labels in non-shifting bottom navigation 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgb(243, 237, 246)", + "backgroundColor": "rgba(247, 242, 250, 1)", "overflow": "hidden", } } @@ -1428,7 +1428,7 @@ exports[`hides labels in shifting bottom navigation 1`] = ` "flex": 1, }, { - "backgroundColor": "rgba(255, 251, 255, 1)", + "backgroundColor": "rgba(254, 247, 255, 1)", }, ] } @@ -1521,7 +1521,7 @@ exports[`hides labels in shifting bottom navigation 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgb(243, 237, 246)", + "backgroundColor": "rgba(247, 242, 250, 1)", "overflow": "hidden", } } @@ -2169,7 +2169,7 @@ exports[`renders bottom navigation with getLazy 1`] = ` "flex": 1, }, { - "backgroundColor": "rgba(255, 251, 255, 1)", + "backgroundColor": "rgba(254, 247, 255, 1)", }, ] } @@ -2394,7 +2394,7 @@ exports[`renders bottom navigation with getLazy 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgb(243, 237, 246)", + "backgroundColor": "rgba(247, 242, 250, 1)", "overflow": "hidden", } } @@ -4030,7 +4030,7 @@ exports[`renders bottom navigation with scene animation 1`] = ` "flex": 1, }, { - "backgroundColor": "rgba(255, 251, 255, 1)", + "backgroundColor": "rgba(254, 247, 255, 1)", }, ] } @@ -4123,7 +4123,7 @@ exports[`renders bottom navigation with scene animation 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgb(243, 237, 246)", + "backgroundColor": "rgba(247, 242, 250, 1)", "overflow": "hidden", } } @@ -5504,7 +5504,7 @@ exports[`renders custom icon and label in non-shifting bottom navigation 1`] = ` "flex": 1, }, { - "backgroundColor": "rgba(255, 251, 255, 1)", + "backgroundColor": "rgba(254, 247, 255, 1)", }, ] } @@ -5597,7 +5597,7 @@ exports[`renders custom icon and label in non-shifting bottom navigation 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgb(243, 237, 246)", + "backgroundColor": "rgba(247, 242, 250, 1)", "overflow": "hidden", } } @@ -6206,7 +6206,7 @@ exports[`renders custom icon and label in shifting bottom navigation 1`] = ` "flex": 1, }, { - "backgroundColor": "rgba(255, 251, 255, 1)", + "backgroundColor": "rgba(254, 247, 255, 1)", }, ] } @@ -6299,7 +6299,7 @@ exports[`renders custom icon and label in shifting bottom navigation 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgb(243, 237, 246)", + "backgroundColor": "rgba(247, 242, 250, 1)", "overflow": "hidden", } } @@ -7200,7 +7200,7 @@ exports[`renders custom icon and label with custom colors in non-shifting bottom "flex": 1, }, { - "backgroundColor": "rgba(255, 251, 255, 1)", + "backgroundColor": "rgba(254, 247, 255, 1)", }, ] } @@ -7293,7 +7293,7 @@ exports[`renders custom icon and label with custom colors in non-shifting bottom style={ { "alignItems": "center", - "backgroundColor": "rgb(243, 237, 246)", + "backgroundColor": "rgba(247, 242, 250, 1)", "overflow": "hidden", } } @@ -8301,7 +8301,7 @@ exports[`renders custom icon and label with custom colors in shifting bottom nav "flex": 1, }, { - "backgroundColor": "rgba(255, 251, 255, 1)", + "backgroundColor": "rgba(254, 247, 255, 1)", }, ] } @@ -8394,7 +8394,7 @@ exports[`renders custom icon and label with custom colors in shifting bottom nav style={ { "alignItems": "center", - "backgroundColor": "rgb(243, 237, 246)", + "backgroundColor": "rgba(247, 242, 250, 1)", "overflow": "hidden", } } @@ -9249,7 +9249,7 @@ exports[`renders non-shifting bottom navigation 1`] = ` "flex": 1, }, { - "backgroundColor": "rgba(255, 251, 255, 1)", + "backgroundColor": "rgba(254, 247, 255, 1)", }, ] } @@ -9342,7 +9342,7 @@ exports[`renders non-shifting bottom navigation 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgb(243, 237, 246)", + "backgroundColor": "rgba(247, 242, 250, 1)", "overflow": "hidden", } } @@ -10350,7 +10350,7 @@ exports[`renders shifting bottom navigation 1`] = ` "flex": 1, }, { - "backgroundColor": "rgba(255, 251, 255, 1)", + "backgroundColor": "rgba(254, 247, 255, 1)", }, ] } @@ -10443,7 +10443,7 @@ exports[`renders shifting bottom navigation 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgb(243, 237, 246)", + "backgroundColor": "rgba(247, 242, 250, 1)", "overflow": "hidden", } } diff --git a/src/components/__tests__/__snapshots__/ListAccordion.test.tsx.snap b/src/components/__tests__/__snapshots__/ListAccordion.test.tsx.snap index 9999e424d2..ec3393cb29 100644 --- a/src/components/__tests__/__snapshots__/ListAccordion.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/ListAccordion.test.tsx.snap @@ -5,7 +5,7 @@ exports[`renders expanded accordion 1`] = ` @@ -270,7 +270,7 @@ exports[`renders list accordion with children 1`] = ` @@ -477,7 +477,7 @@ exports[`renders list accordion with custom title and description styles 1`] = ` @@ -677,7 +677,7 @@ exports[`renders list accordion with left items 1`] = ` @@ -884,7 +884,7 @@ exports[`renders multiline list accordion 1`] = ` diff --git a/src/components/__tests__/__snapshots__/ListSection.test.tsx.snap b/src/components/__tests__/__snapshots__/ListSection.test.tsx.snap index eccc060089..fa4dd4024d 100644 --- a/src/components/__tests__/__snapshots__/ListSection.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/ListSection.test.tsx.snap @@ -17,14 +17,14 @@ exports[`renders list section with custom title style 1`] = ` }, "colors": { "backdrop": "rgba(50, 47, 55, 0.4)", - "background": "rgba(255, 251, 255, 1)", + "background": "rgba(254, 247, 255, 1)", "elevation": { "level0": "transparent", - "level1": "rgb(247, 243, 249)", - "level2": "rgb(243, 237, 246)", - "level3": "rgb(238, 232, 244)", - "level4": "rgb(236, 230, 243)", - "level5": "rgb(233, 227, 241)", + "level1": "rgba(255, 255, 255, 1)", + "level2": "rgba(247, 242, 250, 1)", + "level3": "rgba(243, 237, 247, 1)", + "level4": "rgba(236, 230, 240, 1)", + "level5": "rgba(230, 224, 233, 1)", }, "error": "rgba(179, 38, 30, 1)", "errorContainer": "rgba(249, 222, 220, 1)", @@ -36,26 +36,45 @@ exports[`renders list section with custom title style 1`] = ` "onErrorContainer": "rgba(65, 14, 11, 1)", "onPrimary": "rgba(255, 255, 255, 1)", "onPrimaryContainer": "rgba(33, 0, 93, 1)", + "onPrimaryFixed": "rgba(33, 0, 93, 1)", + "onPrimaryFixedVariant": "rgba(79, 55, 139, 1)", "onSecondary": "rgba(255, 255, 255, 1)", "onSecondaryContainer": "rgba(29, 25, 43, 1)", + "onSecondaryFixed": "rgba(29, 25, 43, 1)", + "onSecondaryFixedVariant": "rgba(74, 68, 88, 1)", "onSurface": "rgba(29, 27, 32, 1)", "onSurfaceDisabled": "rgba(29, 27, 32, 0.38)", "onSurfaceVariant": "rgba(73, 69, 79, 1)", "onTertiary": "rgba(255, 255, 255, 1)", "onTertiaryContainer": "rgba(49, 17, 29, 1)", + "onTertiaryFixed": "rgba(49, 17, 29, 1)", + "onTertiaryFixedVariant": "rgba(99, 59, 72, 1)", "outline": "rgba(121, 116, 126, 1)", "outlineVariant": "rgba(202, 196, 208, 1)", "primary": "rgba(103, 80, 164, 1)", "primaryContainer": "rgba(234, 221, 255, 1)", + "primaryFixed": "rgba(234, 221, 255, 1)", + "primaryFixedDim": "rgba(208, 188, 255, 1)", "scrim": "rgba(0, 0, 0, 1)", "secondary": "rgba(98, 91, 113, 1)", "secondaryContainer": "rgba(232, 222, 248, 1)", + "secondaryFixed": "rgba(232, 222, 248, 1)", + "secondaryFixedDim": "rgba(204, 194, 220, 1)", "shadow": "rgba(0, 0, 0, 1)", - "surface": "rgba(255, 251, 255, 1)", + "surface": "rgba(254, 247, 255, 1)", + "surfaceBright": "rgba(254, 247, 255, 1)", + "surfaceContainer": "rgba(243, 237, 247, 1)", + "surfaceContainerHigh": "rgba(236, 230, 240, 1)", + "surfaceContainerHighest": "rgba(230, 224, 233, 1)", + "surfaceContainerLow": "rgba(247, 242, 250, 1)", + "surfaceContainerLowest": "rgba(255, 255, 255, 1)", + "surfaceDim": "rgba(222, 216, 225, 1)", "surfaceDisabled": "rgba(29, 27, 32, 0.12)", "surfaceVariant": "rgba(231, 224, 236, 1)", "tertiary": "rgba(125, 82, 96, 1)", "tertiaryContainer": "rgba(255, 216, 228, 1)", + "tertiaryFixed": "rgba(255, 216, 228, 1)", + "tertiaryFixedDim": "rgba(239, 184, 200, 1)", }, "dark": false, "fonts": { @@ -544,14 +563,14 @@ exports[`renders list section with subheader 1`] = ` }, "colors": { "backdrop": "rgba(50, 47, 55, 0.4)", - "background": "rgba(255, 251, 255, 1)", + "background": "rgba(254, 247, 255, 1)", "elevation": { "level0": "transparent", - "level1": "rgb(247, 243, 249)", - "level2": "rgb(243, 237, 246)", - "level3": "rgb(238, 232, 244)", - "level4": "rgb(236, 230, 243)", - "level5": "rgb(233, 227, 241)", + "level1": "rgba(255, 255, 255, 1)", + "level2": "rgba(247, 242, 250, 1)", + "level3": "rgba(243, 237, 247, 1)", + "level4": "rgba(236, 230, 240, 1)", + "level5": "rgba(230, 224, 233, 1)", }, "error": "rgba(179, 38, 30, 1)", "errorContainer": "rgba(249, 222, 220, 1)", @@ -563,26 +582,45 @@ exports[`renders list section with subheader 1`] = ` "onErrorContainer": "rgba(65, 14, 11, 1)", "onPrimary": "rgba(255, 255, 255, 1)", "onPrimaryContainer": "rgba(33, 0, 93, 1)", + "onPrimaryFixed": "rgba(33, 0, 93, 1)", + "onPrimaryFixedVariant": "rgba(79, 55, 139, 1)", "onSecondary": "rgba(255, 255, 255, 1)", "onSecondaryContainer": "rgba(29, 25, 43, 1)", + "onSecondaryFixed": "rgba(29, 25, 43, 1)", + "onSecondaryFixedVariant": "rgba(74, 68, 88, 1)", "onSurface": "rgba(29, 27, 32, 1)", "onSurfaceDisabled": "rgba(29, 27, 32, 0.38)", "onSurfaceVariant": "rgba(73, 69, 79, 1)", "onTertiary": "rgba(255, 255, 255, 1)", "onTertiaryContainer": "rgba(49, 17, 29, 1)", + "onTertiaryFixed": "rgba(49, 17, 29, 1)", + "onTertiaryFixedVariant": "rgba(99, 59, 72, 1)", "outline": "rgba(121, 116, 126, 1)", "outlineVariant": "rgba(202, 196, 208, 1)", "primary": "rgba(103, 80, 164, 1)", "primaryContainer": "rgba(234, 221, 255, 1)", + "primaryFixed": "rgba(234, 221, 255, 1)", + "primaryFixedDim": "rgba(208, 188, 255, 1)", "scrim": "rgba(0, 0, 0, 1)", "secondary": "rgba(98, 91, 113, 1)", "secondaryContainer": "rgba(232, 222, 248, 1)", + "secondaryFixed": "rgba(232, 222, 248, 1)", + "secondaryFixedDim": "rgba(204, 194, 220, 1)", "shadow": "rgba(0, 0, 0, 1)", - "surface": "rgba(255, 251, 255, 1)", + "surface": "rgba(254, 247, 255, 1)", + "surfaceBright": "rgba(254, 247, 255, 1)", + "surfaceContainer": "rgba(243, 237, 247, 1)", + "surfaceContainerHigh": "rgba(236, 230, 240, 1)", + "surfaceContainerHighest": "rgba(230, 224, 233, 1)", + "surfaceContainerLow": "rgba(247, 242, 250, 1)", + "surfaceContainerLowest": "rgba(255, 255, 255, 1)", + "surfaceDim": "rgba(222, 216, 225, 1)", "surfaceDisabled": "rgba(29, 27, 32, 0.12)", "surfaceVariant": "rgba(231, 224, 236, 1)", "tertiary": "rgba(125, 82, 96, 1)", "tertiaryContainer": "rgba(255, 216, 228, 1)", + "tertiaryFixed": "rgba(255, 216, 228, 1)", + "tertiaryFixedDim": "rgba(239, 184, 200, 1)", }, "dark": false, "fonts": { @@ -1069,14 +1107,14 @@ exports[`renders list section without subheader 1`] = ` }, "colors": { "backdrop": "rgba(50, 47, 55, 0.4)", - "background": "rgba(255, 251, 255, 1)", + "background": "rgba(254, 247, 255, 1)", "elevation": { "level0": "transparent", - "level1": "rgb(247, 243, 249)", - "level2": "rgb(243, 237, 246)", - "level3": "rgb(238, 232, 244)", - "level4": "rgb(236, 230, 243)", - "level5": "rgb(233, 227, 241)", + "level1": "rgba(255, 255, 255, 1)", + "level2": "rgba(247, 242, 250, 1)", + "level3": "rgba(243, 237, 247, 1)", + "level4": "rgba(236, 230, 240, 1)", + "level5": "rgba(230, 224, 233, 1)", }, "error": "rgba(179, 38, 30, 1)", "errorContainer": "rgba(249, 222, 220, 1)", @@ -1088,26 +1126,45 @@ exports[`renders list section without subheader 1`] = ` "onErrorContainer": "rgba(65, 14, 11, 1)", "onPrimary": "rgba(255, 255, 255, 1)", "onPrimaryContainer": "rgba(33, 0, 93, 1)", + "onPrimaryFixed": "rgba(33, 0, 93, 1)", + "onPrimaryFixedVariant": "rgba(79, 55, 139, 1)", "onSecondary": "rgba(255, 255, 255, 1)", "onSecondaryContainer": "rgba(29, 25, 43, 1)", + "onSecondaryFixed": "rgba(29, 25, 43, 1)", + "onSecondaryFixedVariant": "rgba(74, 68, 88, 1)", "onSurface": "rgba(29, 27, 32, 1)", "onSurfaceDisabled": "rgba(29, 27, 32, 0.38)", "onSurfaceVariant": "rgba(73, 69, 79, 1)", "onTertiary": "rgba(255, 255, 255, 1)", "onTertiaryContainer": "rgba(49, 17, 29, 1)", + "onTertiaryFixed": "rgba(49, 17, 29, 1)", + "onTertiaryFixedVariant": "rgba(99, 59, 72, 1)", "outline": "rgba(121, 116, 126, 1)", "outlineVariant": "rgba(202, 196, 208, 1)", "primary": "rgba(103, 80, 164, 1)", "primaryContainer": "rgba(234, 221, 255, 1)", + "primaryFixed": "rgba(234, 221, 255, 1)", + "primaryFixedDim": "rgba(208, 188, 255, 1)", "scrim": "rgba(0, 0, 0, 1)", "secondary": "rgba(98, 91, 113, 1)", "secondaryContainer": "rgba(232, 222, 248, 1)", + "secondaryFixed": "rgba(232, 222, 248, 1)", + "secondaryFixedDim": "rgba(204, 194, 220, 1)", "shadow": "rgba(0, 0, 0, 1)", - "surface": "rgba(255, 251, 255, 1)", + "surface": "rgba(254, 247, 255, 1)", + "surfaceBright": "rgba(254, 247, 255, 1)", + "surfaceContainer": "rgba(243, 237, 247, 1)", + "surfaceContainerHigh": "rgba(236, 230, 240, 1)", + "surfaceContainerHighest": "rgba(230, 224, 233, 1)", + "surfaceContainerLow": "rgba(247, 242, 250, 1)", + "surfaceContainerLowest": "rgba(255, 255, 255, 1)", + "surfaceDim": "rgba(222, 216, 225, 1)", "surfaceDisabled": "rgba(29, 27, 32, 0.12)", "surfaceVariant": "rgba(231, 224, 236, 1)", "tertiary": "rgba(125, 82, 96, 1)", "tertiaryContainer": "rgba(255, 216, 228, 1)", + "tertiaryFixed": "rgba(255, 216, 228, 1)", + "tertiaryFixedDim": "rgba(239, 184, 200, 1)", }, "dark": false, "fonts": { diff --git a/src/components/__tests__/__snapshots__/Menu.test.tsx.snap b/src/components/__tests__/__snapshots__/Menu.test.tsx.snap index a20d7ed8d7..d3a7c1b1a1 100644 --- a/src/components/__tests__/__snapshots__/Menu.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Menu.test.tsx.snap @@ -259,7 +259,7 @@ exports[`renders menu with content styles 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgb(243, 237, 246)", + "backgroundColor": "rgba(247, 242, 250, 1)", "borderRadius": 4, "borderTopLeftRadius": 0, "borderTopRightRadius": 0, @@ -288,7 +288,7 @@ exports[`renders menu with content styles 1`] = ` pointerEvents="box-none" style={ { - "backgroundColor": "rgb(243, 237, 246)", + "backgroundColor": "rgba(247, 242, 250, 1)", "borderRadius": 4, "borderTopLeftRadius": 0, "borderTopRightRadius": 0, @@ -978,7 +978,7 @@ exports[`renders visible menu 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgb(243, 237, 246)", + "backgroundColor": "rgba(247, 242, 250, 1)", "borderRadius": 4, "opacity": 0, "shadowColor": "#000", @@ -1005,7 +1005,7 @@ exports[`renders visible menu 1`] = ` pointerEvents="box-none" style={ { - "backgroundColor": "rgb(243, 237, 246)", + "backgroundColor": "rgba(247, 242, 250, 1)", "borderRadius": 4, "flex": undefined, "paddingVertical": 8, diff --git a/src/components/__tests__/__snapshots__/Searchbar.test.tsx.snap b/src/components/__tests__/__snapshots__/Searchbar.test.tsx.snap index 769a053662..bbf1c420f7 100644 --- a/src/components/__tests__/__snapshots__/Searchbar.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Searchbar.test.tsx.snap @@ -5,7 +5,7 @@ exports[`activity indicator snapshot test 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgb(238, 232, 244)", + "backgroundColor": "rgba(243, 237, 247, 1)", "borderRadius": 28, "shadowColor": "#000", "shadowOffset": { @@ -23,7 +23,7 @@ exports[`activity indicator snapshot test 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgb(238, 232, 244)", + "backgroundColor": "rgba(243, 237, 247, 1)", "borderRadius": 28, "flex": undefined, "flexDirection": "row", @@ -415,7 +415,7 @@ exports[`renders with placeholder 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgb(238, 232, 244)", + "backgroundColor": "rgba(243, 237, 247, 1)", "borderRadius": 28, "shadowColor": "#000", "shadowOffset": { @@ -433,7 +433,7 @@ exports[`renders with placeholder 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgb(238, 232, 244)", + "backgroundColor": "rgba(243, 237, 247, 1)", "borderRadius": 28, "flex": undefined, "flexDirection": "row", @@ -776,7 +776,7 @@ exports[`renders with text 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgb(238, 232, 244)", + "backgroundColor": "rgba(243, 237, 247, 1)", "borderRadius": 28, "shadowColor": "#000", "shadowOffset": { @@ -794,7 +794,7 @@ exports[`renders with text 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgb(238, 232, 244)", + "backgroundColor": "rgba(243, 237, 247, 1)", "borderRadius": 28, "flex": undefined, "flexDirection": "row", diff --git a/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap b/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap index 4bc6f8107f..090fdaec66 100644 --- a/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap @@ -1009,7 +1009,7 @@ exports[`correctly applies height to multiline Outline TextInput 1`] = ` }, false, { - "backgroundColor": "rgba(255, 251, 255, 1)", + "backgroundColor": "rgba(254, 247, 255, 1)", "borderColor": "rgba(121, 116, 126, 1)", "borderRadius": 4, "borderWidth": 1, @@ -1086,7 +1086,7 @@ exports[`correctly applies height to multiline Outline TextInput 1`] = ` numberOfLines={1} style={ { - "backgroundColor": "rgba(255, 251, 255, 1)", + "backgroundColor": "rgba(254, 247, 255, 1)", "color": "transparent", "fontFamily": "System", "fontSize": 16, diff --git a/src/styles/themes/v3/DarkTheme.tsx b/src/styles/themes/v3/DarkTheme.tsx index 9823e677bd..a8dd709faf 100644 --- a/src/styles/themes/v3/DarkTheme.tsx +++ b/src/styles/themes/v3/DarkTheme.tsx @@ -19,13 +19,20 @@ export const MD3DarkTheme: MD3Theme = { secondaryContainer: palette.secondary30, tertiary: palette.tertiary80, tertiaryContainer: palette.tertiary30, - surface: palette.neutral10, + surface: palette.neutral6, + surfaceDim: palette.neutral6, + surfaceBright: palette.neutral24, + surfaceContainerLowest: palette.neutral4, + surfaceContainerLow: palette.neutral10, + surfaceContainer: palette.neutral12, + surfaceContainerHigh: palette.neutral17, + surfaceContainerHighest: palette.neutral22, surfaceVariant: palette.neutralVariant30, surfaceDisabled: color(palette.neutral90) .alpha(opacity.level2) .rgb() .string(), - background: palette.neutral10, + background: palette.neutral6, error: palette.error80, errorContainer: palette.error30, onPrimary: palette.primary20, @@ -48,19 +55,28 @@ export const MD3DarkTheme: MD3Theme = { inverseSurface: palette.neutral90, inverseOnSurface: palette.neutral20, inversePrimary: palette.primary40, + primaryFixed: palette.primary90, + primaryFixedDim: palette.primary80, + onPrimaryFixed: palette.primary10, + onPrimaryFixedVariant: palette.primary30, + secondaryFixed: palette.secondary90, + secondaryFixedDim: palette.secondary80, + onSecondaryFixed: palette.secondary10, + onSecondaryFixedVariant: palette.secondary30, + tertiaryFixed: palette.tertiary90, + tertiaryFixedDim: palette.tertiary80, + onTertiaryFixed: palette.tertiary10, + onTertiaryFixedVariant: palette.tertiary30, shadow: palette.neutral0, scrim: palette.neutral0, backdrop: color(MD3Colors.neutralVariant20).alpha(0.4).rgb().string(), elevation: { level0: 'transparent', - // Note: Color values with transparency cause RN to transfer shadows to children nodes - // instead of View component in Surface. Providing solid background fixes the issue. - // Opaque color values generated with `palette.primary80` used as background - level1: 'rgb(37, 35, 42)', // palette.primary80, alpha 0.05 - level2: 'rgb(44, 40, 49)', // palette.primary80, alpha 0.08 - level3: 'rgb(49, 44, 56)', // palette.primary80, alpha 0.11 - level4: 'rgb(51, 46, 58)', // palette.primary80, alpha 0.12 - level5: 'rgb(52, 49, 63)', // palette.primary80, alpha 0.14 + level1: palette.neutral4, + level2: palette.neutral10, + level3: palette.neutral12, + level4: palette.neutral17, + level5: palette.neutral22, }, }, }; diff --git a/src/styles/themes/v3/LightTheme.tsx b/src/styles/themes/v3/LightTheme.tsx index 99e0d11ab4..c7b32d6013 100644 --- a/src/styles/themes/v3/LightTheme.tsx +++ b/src/styles/themes/v3/LightTheme.tsx @@ -18,13 +18,20 @@ export const MD3LightTheme: MD3Theme = { secondaryContainer: palette.secondary90, tertiary: palette.tertiary40, tertiaryContainer: palette.tertiary90, - surface: palette.neutral99, + surface: palette.neutral98, + surfaceDim: palette.neutral87, + surfaceBright: palette.neutral98, + surfaceContainerLowest: palette.neutral100, + surfaceContainerLow: palette.neutral96, + surfaceContainer: palette.neutral94, + surfaceContainerHigh: palette.neutral92, + surfaceContainerHighest: palette.neutral90, surfaceVariant: palette.neutralVariant90, surfaceDisabled: color(palette.neutral10) .alpha(opacity.level2) .rgb() .string(), - background: palette.neutral99, + background: palette.neutral98, error: palette.error40, errorContainer: palette.error90, onPrimary: palette.primary100, @@ -47,19 +54,28 @@ export const MD3LightTheme: MD3Theme = { inverseSurface: palette.neutral20, inverseOnSurface: palette.neutral95, inversePrimary: palette.primary80, + primaryFixed: palette.primary90, + primaryFixedDim: palette.primary80, + onPrimaryFixed: palette.primary10, + onPrimaryFixedVariant: palette.primary30, + secondaryFixed: palette.secondary90, + secondaryFixedDim: palette.secondary80, + onSecondaryFixed: palette.secondary10, + onSecondaryFixedVariant: palette.secondary30, + tertiaryFixed: palette.tertiary90, + tertiaryFixedDim: palette.tertiary80, + onTertiaryFixed: palette.tertiary10, + onTertiaryFixedVariant: palette.tertiary30, shadow: palette.neutral0, scrim: palette.neutral0, backdrop: color(MD3Colors.neutralVariant20).alpha(0.4).rgb().string(), elevation: { level0: 'transparent', - // Note: Color values with transparency cause RN to transfer shadows to children nodes - // instead of View component in Surface. Providing solid background fixes the issue. - // Opaque color values generated with `palette.primary99` used as background - level1: 'rgb(247, 243, 249)', // palette.primary40, alpha 0.05 - level2: 'rgb(243, 237, 246)', // palette.primary40, alpha 0.08 - level3: 'rgb(238, 232, 244)', // palette.primary40, alpha 0.11 - level4: 'rgb(236, 230, 243)', // palette.primary40, alpha 0.12 - level5: 'rgb(233, 227, 241)', // palette.primary40, alpha 0.14 + level1: palette.neutral100, + level2: palette.neutral96, + level3: palette.neutral94, + level4: palette.neutral92, + level5: palette.neutral90, }, }, fonts: configureFonts(), diff --git a/src/types.tsx b/src/types.tsx index 4208fa0d64..d8d0e81125 100644 --- a/src/types.tsx +++ b/src/types.tsx @@ -36,6 +36,13 @@ export type MD3Colors = { tertiary: string; tertiaryContainer: string; surface: string; + surfaceDim: string; + surfaceBright: string; + surfaceContainerLowest: string; + surfaceContainerLow: string; + surfaceContainer: string; + surfaceContainerHigh: string; + surfaceContainerHighest: string; surfaceVariant: string; surfaceDisabled: string; background: string; @@ -58,6 +65,18 @@ export type MD3Colors = { inverseSurface: string; inverseOnSurface: string; inversePrimary: string; + primaryFixed: string; + primaryFixedDim: string; + onPrimaryFixed: string; + onPrimaryFixedVariant: string; + secondaryFixed: string; + secondaryFixedDim: string; + onSecondaryFixed: string; + onSecondaryFixedVariant: string; + tertiaryFixed: string; + tertiaryFixedDim: string; + onTertiaryFixed: string; + onTertiaryFixedVariant: string; shadow: string; scrim: string; backdrop: string; From 3c59976436b52e51cc4d902574a0a4d5f98a42ed Mon Sep 17 00:00:00 2001 From: Adrian Cotfas Date: Wed, 1 Apr 2026 11:59:37 +0300 Subject: [PATCH 09/13] feat: add DynamicTheme * Known limitation: surface/container roles on API 31-33 use * @color/m3_ref_palette_dynamic_neutral_variant* (MCL resources that require a * native DynamicColors setup). No @android:color/ equivalent exists for those * slots. Reference palette values are used as fallback on API 31-33. --- src/styles/themes/DynamicTheme.android.tsx | 502 +++++++++++++++++++++ src/styles/themes/DynamicTheme.tsx | 2 + 2 files changed, 504 insertions(+) create mode 100644 src/styles/themes/DynamicTheme.android.tsx create mode 100644 src/styles/themes/DynamicTheme.tsx diff --git a/src/styles/themes/DynamicTheme.android.tsx b/src/styles/themes/DynamicTheme.android.tsx new file mode 100644 index 0000000000..f2791670e8 --- /dev/null +++ b/src/styles/themes/DynamicTheme.android.tsx @@ -0,0 +1,502 @@ +import { Platform, PlatformColor } from 'react-native'; + +import { DarkTheme } from './DarkTheme'; +import { LightTheme } from './LightTheme'; +import type { Theme } from '../../types'; + +const isApi34 = (Platform.Version as number) >= 34; +const isApi31 = (Platform.Version as number) >= 31; + +const ac = (name: string) => + PlatformColor(`@android:color/${name}`) as unknown as string; + +/** + * Picks the correct color value for the current Android API level. + * - API 34+: uses the named role resource (system_*_light/dark) + * - API 31-33: uses the tonal accent resource (system_accent*_NNN), or ref + * - API < 31: uses the reference palette string from the base theme + * @see https://github.com/material-components/material-components-android/blob/master/docs/theming/Color.md + */ +const pick = (api34: string, api31: string, ref: string): string => + isApi34 ? ac(api34) : isApi31 && api31 != null ? ac(api31) : ref; + +// Known limitation: surface/container roles on API 31-33 use +// @color/m3_ref_palette_dynamic_neutral_variant* (MCL resources that require a +// native DynamicColors setup). No @android:color/ equivalent exists for those +// slots. Reference palette values are used as fallback on API 31-33. + +const lightColors = { + primary: pick( + 'system_primary_light', + 'system_accent1_600', + LightTheme.colors.primary + ), + onPrimary: pick( + 'system_on_primary_light', + 'system_accent1_0', + LightTheme.colors.onPrimary + ), + primaryContainer: pick( + 'system_primary_container_light', + 'system_accent1_100', + LightTheme.colors.primaryContainer + ), + onPrimaryContainer: pick( + 'system_on_primary_container_light', + 'system_accent1_900', + LightTheme.colors.onPrimaryContainer + ), + inversePrimary: pick( + 'system_primary_dark', + 'system_accent1_200', + LightTheme.colors.inversePrimary + ), + secondary: pick( + 'system_secondary_light', + 'system_accent2_600', + LightTheme.colors.secondary + ), + onSecondary: pick( + 'system_on_secondary_light', + 'system_accent2_0', + LightTheme.colors.onSecondary + ), + secondaryContainer: pick( + 'system_secondary_container_light', + 'system_accent2_100', + LightTheme.colors.secondaryContainer + ), + onSecondaryContainer: pick( + 'system_on_secondary_container_light', + 'system_accent2_900', + LightTheme.colors.onSecondaryContainer + ), + tertiary: pick( + 'system_tertiary_light', + 'system_accent3_600', + LightTheme.colors.tertiary + ), + onTertiary: pick( + 'system_on_tertiary_light', + 'system_accent3_0', + LightTheme.colors.onTertiary + ), + tertiaryContainer: pick( + 'system_tertiary_container_light', + 'system_accent3_100', + LightTheme.colors.tertiaryContainer + ), + onTertiaryContainer: pick( + 'system_on_tertiary_container_light', + 'system_accent3_900', + LightTheme.colors.onTertiaryContainer + ), + error: pick( + 'system_error_light', + LightTheme.colors.error, + LightTheme.colors.error + ), + onError: pick( + 'system_on_error_light', + LightTheme.colors.onError, + LightTheme.colors.onError + ), + errorContainer: pick( + 'system_error_container_light', + LightTheme.colors.errorContainer, + LightTheme.colors.errorContainer + ), + onErrorContainer: pick( + 'system_on_error_container_light', + LightTheme.colors.onErrorContainer, + LightTheme.colors.onErrorContainer + ), + onSurface: pick( + 'system_on_surface_light', + 'system_neutral1_900', + LightTheme.colors.onSurface + ), + onBackground: pick( + 'system_on_background_light', + 'system_neutral1_900', + LightTheme.colors.onBackground + ), + onSurfaceVariant: pick( + 'system_on_surface_variant_light', + 'system_neutral2_700', + LightTheme.colors.onSurfaceVariant + ), + outline: pick( + 'system_outline_light', + 'system_neutral2_500', + LightTheme.colors.outline + ), + outlineVariant: pick( + 'system_outline_variant_light', + 'system_neutral2_200', + LightTheme.colors.outlineVariant + ), + inverseSurface: pick( + 'system_surface_dark', + 'system_neutral1_800', + LightTheme.colors.inverseSurface + ), + inverseOnSurface: pick( + 'system_on_surface_dark', + 'system_neutral1_50', + LightTheme.colors.inverseOnSurface + ), + surfaceContainerLowest: pick( + 'system_surface_container_lowest_light', + 'system_neutral2_0', + LightTheme.colors.surfaceContainerLowest + ), + surfaceContainerLow: pick( + 'system_surface_container_low_light', + LightTheme.colors.surfaceContainerLow, + LightTheme.colors.surfaceContainerLow + ), + surfaceContainerHighest: pick( + 'system_surface_container_highest_light', + 'system_neutral2_100', + LightTheme.colors.surfaceContainerHighest + ), + surface: pick( + 'system_surface_light', + LightTheme.colors.surface, + LightTheme.colors.surface + ), + surfaceDim: pick( + 'system_surface_dim_light', + LightTheme.colors.surfaceDim, + LightTheme.colors.surfaceDim + ), + surfaceBright: pick( + 'system_surface_bright_light', + LightTheme.colors.surfaceBright, + LightTheme.colors.surfaceBright + ), + surfaceContainer: pick( + 'system_surface_container_light', + LightTheme.colors.surfaceContainer, + LightTheme.colors.surfaceContainer + ), + surfaceContainerHigh: pick( + 'system_surface_container_high_light', + LightTheme.colors.surfaceContainerHigh, + LightTheme.colors.surfaceContainerHigh + ), + background: pick( + 'system_background_light', + LightTheme.colors.background, + LightTheme.colors.background + ), + surfaceVariant: pick( + 'system_surface_variant_light', + LightTheme.colors.surfaceVariant, + LightTheme.colors.surfaceVariant + ), + primaryFixed: pick( + 'system_primary_fixed', + 'system_accent1_100', + LightTheme.colors.primaryFixed + ), + primaryFixedDim: pick( + 'system_primary_fixed_dim', + 'system_accent1_200', + LightTheme.colors.primaryFixedDim + ), + onPrimaryFixed: pick( + 'system_on_primary_fixed', + 'system_accent1_900', + LightTheme.colors.onPrimaryFixed + ), + onPrimaryFixedVariant: pick( + 'system_on_primary_fixed_variant', + 'system_accent1_700', + LightTheme.colors.onPrimaryFixedVariant + ), + secondaryFixed: pick( + 'system_secondary_fixed', + 'system_accent2_100', + LightTheme.colors.secondaryFixed + ), + secondaryFixedDim: pick( + 'system_secondary_fixed_dim', + 'system_accent2_200', + LightTheme.colors.secondaryFixedDim + ), + onSecondaryFixed: pick( + 'system_on_secondary_fixed', + 'system_accent2_900', + LightTheme.colors.onSecondaryFixed + ), + onSecondaryFixedVariant: pick( + 'system_on_secondary_fixed_variant', + 'system_accent2_700', + LightTheme.colors.onSecondaryFixedVariant + ), + tertiaryFixed: pick( + 'system_tertiary_fixed', + 'system_accent3_100', + LightTheme.colors.tertiaryFixed + ), + tertiaryFixedDim: pick( + 'system_tertiary_fixed_dim', + 'system_accent3_200', + LightTheme.colors.tertiaryFixedDim + ), + onTertiaryFixed: pick( + 'system_on_tertiary_fixed', + 'system_accent3_900', + LightTheme.colors.onTertiaryFixed + ), + onTertiaryFixedVariant: pick( + 'system_on_tertiary_fixed_variant', + 'system_accent3_700', + LightTheme.colors.onTertiaryFixedVariant + ), +}; + +const darkColors = { + primary: pick( + 'system_primary_dark', + 'system_accent1_200', + DarkTheme.colors.primary + ), + onPrimary: pick( + 'system_on_primary_dark', + 'system_accent1_800', + DarkTheme.colors.onPrimary + ), + primaryContainer: pick( + 'system_primary_container_dark', + 'system_accent1_700', + DarkTheme.colors.primaryContainer + ), + onPrimaryContainer: pick( + 'system_on_primary_container_dark', + 'system_accent1_100', + DarkTheme.colors.onPrimaryContainer + ), + inversePrimary: pick( + 'system_primary_light', + 'system_accent1_600', + DarkTheme.colors.inversePrimary + ), + secondary: pick( + 'system_secondary_dark', + 'system_accent2_200', + DarkTheme.colors.secondary + ), + onSecondary: pick( + 'system_on_secondary_dark', + 'system_accent2_800', + DarkTheme.colors.onSecondary + ), + secondaryContainer: pick( + 'system_secondary_container_dark', + 'system_accent2_700', + DarkTheme.colors.secondaryContainer + ), + onSecondaryContainer: pick( + 'system_on_secondary_container_dark', + 'system_accent2_100', + DarkTheme.colors.onSecondaryContainer + ), + tertiary: pick( + 'system_tertiary_dark', + 'system_accent3_200', + DarkTheme.colors.tertiary + ), + onTertiary: pick( + 'system_on_tertiary_dark', + 'system_accent3_800', + DarkTheme.colors.onTertiary + ), + tertiaryContainer: pick( + 'system_tertiary_container_dark', + 'system_accent3_700', + DarkTheme.colors.tertiaryContainer + ), + onTertiaryContainer: pick( + 'system_on_tertiary_container_dark', + 'system_accent3_100', + DarkTheme.colors.onTertiaryContainer + ), + error: pick( + 'system_error_dark', + DarkTheme.colors.error, + DarkTheme.colors.error + ), + onError: pick( + 'system_on_error_dark', + DarkTheme.colors.onError, + DarkTheme.colors.onError + ), + errorContainer: pick( + 'system_error_container_dark', + DarkTheme.colors.errorContainer, + DarkTheme.colors.errorContainer + ), + onErrorContainer: pick( + 'system_on_error_container_dark', + DarkTheme.colors.onErrorContainer, + DarkTheme.colors.onErrorContainer + ), + onSurface: pick( + 'system_on_surface_dark', + 'system_neutral1_100', + DarkTheme.colors.onSurface + ), + onBackground: pick( + 'system_on_background_dark', + 'system_neutral1_100', + DarkTheme.colors.onBackground + ), + onSurfaceVariant: pick( + 'system_on_surface_variant_dark', + 'system_neutral2_200', + DarkTheme.colors.onSurfaceVariant + ), + outline: pick( + 'system_outline_dark', + 'system_neutral2_400', + DarkTheme.colors.outline + ), + outlineVariant: pick( + 'system_outline_variant_dark', + 'system_neutral2_700', + DarkTheme.colors.outlineVariant + ), + inverseSurface: pick( + 'system_surface_light', + 'system_neutral1_100', + DarkTheme.colors.inverseSurface + ), + inverseOnSurface: pick( + 'system_on_surface_light', + 'system_neutral1_800', + DarkTheme.colors.inverseOnSurface + ), + surfaceContainerLowest: pick( + 'system_surface_container_lowest_dark', + DarkTheme.colors.surfaceContainerLowest, + DarkTheme.colors.surfaceContainerLowest + ), + surfaceContainerLow: pick( + 'system_surface_container_low_dark', + 'system_neutral2_900', + DarkTheme.colors.surfaceContainerLow + ), + surfaceContainerHighest: pick( + 'system_surface_container_highest_dark', + DarkTheme.colors.surfaceContainerHighest, + DarkTheme.colors.surfaceContainerHighest + ), + surface: pick( + 'system_surface_dark', + DarkTheme.colors.surface, + DarkTheme.colors.surface + ), + surfaceDim: pick( + 'system_surface_dim_dark', + DarkTheme.colors.surfaceDim, + DarkTheme.colors.surfaceDim + ), + surfaceBright: pick( + 'system_surface_bright_dark', + DarkTheme.colors.surfaceBright, + DarkTheme.colors.surfaceBright + ), + surfaceContainer: pick( + 'system_surface_container_dark', + DarkTheme.colors.surfaceContainer, + DarkTheme.colors.surfaceContainer + ), + surfaceContainerHigh: pick( + 'system_surface_container_high_dark', + DarkTheme.colors.surfaceContainerHigh, + DarkTheme.colors.surfaceContainerHigh + ), + background: pick( + 'system_background_dark', + DarkTheme.colors.background, + DarkTheme.colors.background + ), + surfaceVariant: pick( + 'system_surface_variant_dark', + DarkTheme.colors.surfaceVariant, + DarkTheme.colors.surfaceVariant + ), + primaryFixed: pick( + 'system_primary_fixed', + 'system_accent1_100', + DarkTheme.colors.primaryFixed + ), + primaryFixedDim: pick( + 'system_primary_fixed_dim', + 'system_accent1_200', + DarkTheme.colors.primaryFixedDim + ), + onPrimaryFixed: pick( + 'system_on_primary_fixed', + 'system_accent1_900', + DarkTheme.colors.onPrimaryFixed + ), + onPrimaryFixedVariant: pick( + 'system_on_primary_fixed_variant', + 'system_accent1_700', + DarkTheme.colors.onPrimaryFixedVariant + ), + secondaryFixed: pick( + 'system_secondary_fixed', + 'system_accent2_100', + DarkTheme.colors.secondaryFixed + ), + secondaryFixedDim: pick( + 'system_secondary_fixed_dim', + 'system_accent2_200', + DarkTheme.colors.secondaryFixedDim + ), + onSecondaryFixed: pick( + 'system_on_secondary_fixed', + 'system_accent2_900', + DarkTheme.colors.onSecondaryFixed + ), + onSecondaryFixedVariant: pick( + 'system_on_secondary_fixed_variant', + 'system_accent2_700', + DarkTheme.colors.onSecondaryFixedVariant + ), + tertiaryFixed: pick( + 'system_tertiary_fixed', + 'system_accent3_100', + DarkTheme.colors.tertiaryFixed + ), + tertiaryFixedDim: pick( + 'system_tertiary_fixed_dim', + 'system_accent3_200', + DarkTheme.colors.tertiaryFixedDim + ), + onTertiaryFixed: pick( + 'system_on_tertiary_fixed', + 'system_accent3_900', + DarkTheme.colors.onTertiaryFixed + ), + onTertiaryFixedVariant: pick( + 'system_on_tertiary_fixed_variant', + 'system_accent3_700', + DarkTheme.colors.onTertiaryFixedVariant + ), +}; + +export const DynamicLightTheme: Theme = { + ...LightTheme, + colors: { ...LightTheme.colors, ...lightColors }, +}; + +export const DynamicDarkTheme: Theme = { + ...DarkTheme, + colors: { ...DarkTheme.colors, ...darkColors }, +}; diff --git a/src/styles/themes/DynamicTheme.tsx b/src/styles/themes/DynamicTheme.tsx new file mode 100644 index 0000000000..78e3cc5c8d --- /dev/null +++ b/src/styles/themes/DynamicTheme.tsx @@ -0,0 +1,2 @@ +export { DarkTheme as MD3DynamicDarkTheme } from './DarkTheme'; +export { LightTheme as MD3DynamicLightTheme } from './LightTheme'; From 31c7a90ba3b2cde727cc9a1a407d6f87dde61295 Mon Sep 17 00:00:00 2001 From: Adrian Cotfas Date: Thu, 2 Apr 2026 12:47:38 +0300 Subject: [PATCH 10/13] refactor: remove usage of expo-material3-theme --- docs/docs/guides/02-theming.mdx | 23 +- docs/docs/guides/06-recommended-libraries.md | 6 +- example/package.json | 1 - example/src/index.native.tsx | 25 +- example/utils/index.ts | 5 +- src/styles/themes/DynamicTheme.android.tsx | 252 +++++++++---------- src/styles/themes/DynamicTheme.tsx | 4 +- src/styles/themes/index.ts | 1 + yarn.lock | 22 -- 9 files changed, 152 insertions(+), 187 deletions(-) diff --git a/docs/docs/guides/02-theming.mdx b/docs/docs/guides/02-theming.mdx index beeb8bfaff..ffb2f687c9 100644 --- a/docs/docs/guides/02-theming.mdx +++ b/docs/docs/guides/02-theming.mdx @@ -227,31 +227,26 @@ export default function Main() { ### Sync dynamic colors with system colors -Using [`pchmn/expo-material3-theme`](https://github.com/pchmn/expo-material3-theme) library you can easily access the Material 3 system colors from Android 12+ devices and seamlessly integrate them into your dynamic theme. Any changes made by the user to the system colors will be automatically reflected in the theme. +React Native Paper provides built-in support for Android dynamic colors through `DynamicLightTheme` and `DynamicDarkTheme`. These themes use React Native's `PlatformColor` API to map all Material Design 3 color roles to Android system colors, so any changes the user makes to their system palette are automatically reflected in the app. :::info -In case of incompatible devices, the library will revert to a default theme. +Dynamic colors require Android 12 (API 31+). On older Android versions and all other platforms, these themes fall back to the default `LightTheme` / `DarkTheme`. ::: -To get started, follow the [installation instructions](https://github.com/pchmn/expo-material3-theme#installation) and check the following code: - ```tsx -import { useMaterial3Theme } from '@pchmn/expo-material3-theme'; import { useColorScheme } from 'react-native'; -import { MD3DarkTheme, MD3LightTheme, PaperProvider } from 'react-native-paper'; +import { + DynamicDarkTheme, + DynamicLightTheme, + PaperProvider, +} from 'react-native-paper'; import App from './src/App'; export default function Main() { - const colorScheme = useColorScheme(); - const { theme } = useMaterial3Theme(); - - const paperTheme = - colorScheme === 'dark' - ? { ...MD3DarkTheme, colors: theme.dark } - : { ...MD3LightTheme, colors: theme.light }; + const isDarkMode = useColorScheme() === 'dark'; return ( - + ); diff --git a/docs/docs/guides/06-recommended-libraries.md b/docs/docs/guides/06-recommended-libraries.md index e70157ca1d..7be319cedf 100644 --- a/docs/docs/guides/06-recommended-libraries.md +++ b/docs/docs/guides/06-recommended-libraries.md @@ -33,8 +33,4 @@ Material Design themed [date picker](https://material.io/components/date-pickers ## Time Picker [web-ridge/react-native-paper-dates](https://github.com/web-ridge/react-native-paper-dates) -Material Design themed [time picker](https://material.io/components/time-pickers), maintained by [@RichardLindhout](https://twitter.com/RichardLindhout) - -## System Colors -[pchmn/expo-material3-theme](https://github.com/pchmn/expo-material3-theme) -Retrieve Material 3 system colors from Android 12+ devices \ No newline at end of file +Material Design themed [time picker](https://material.io/components/time-pickers), maintained by [@RichardLindhout](https://twitter.com/RichardLindhout) diff --git a/example/package.json b/example/package.json index 667c56cb19..3ae36fb1ec 100644 --- a/example/package.json +++ b/example/package.json @@ -16,7 +16,6 @@ "dependencies": { "@expo/vector-icons": "^15.0.2", "@expo/webpack-config": "~19.0.1", - "@pchmn/expo-material3-theme": "^1.3.2", "@react-native-async-storage/async-storage": "2.2.0", "@react-native-masked-view/masked-view": "0.3.2", "@react-navigation/bottom-tabs": "^7.3.10", diff --git a/example/src/index.native.tsx b/example/src/index.native.tsx index 6ca9b27077..402232ccc6 100644 --- a/example/src/index.native.tsx +++ b/example/src/index.native.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import { I18nManager } from 'react-native'; -import { useMaterial3Theme } from '@pchmn/expo-material3-theme'; import AsyncStorage from '@react-native-async-storage/async-storage'; import { createDrawerNavigator } from '@react-navigation/drawer'; import { InitialState, NavigationContainer } from '@react-navigation/native'; @@ -9,7 +8,13 @@ import { useFonts } from 'expo-font'; import { useKeepAwake } from 'expo-keep-awake'; import { StatusBar } from 'expo-status-bar'; import * as Updates from 'expo-updates'; -import { PaperProvider, MD3DarkTheme, MD3LightTheme } from 'react-native-paper'; +import { + PaperProvider, + MD3DarkTheme, + MD3LightTheme, + DynamicLightTheme, + DynamicDarkTheme, +} from 'react-native-paper'; import { SafeAreaInsetsContext } from 'react-native-safe-area-context'; import DrawerItems from './DrawerItems'; @@ -50,19 +55,13 @@ export default function PaperExample() { const [customFontLoaded, setCustomFont] = React.useState(false); const [rippleEffectEnabled, setRippleEffectEnabled] = React.useState(true); - const { theme: mdTheme } = useMaterial3Theme(); const theme = React.useMemo(() => { - if (!deviceColorsSupported || !shouldUseDeviceColors) { - return isDarkMode ? MD3DarkTheme : MD3LightTheme; + if (deviceColorsSupported && shouldUseDeviceColors) { + return isDarkMode ? DynamicDarkTheme : DynamicLightTheme; } - return isDarkMode - ? { ...MD3DarkTheme, colors: { ...MD3DarkTheme.colors, ...mdTheme.dark } } - : { - ...MD3LightTheme, - colors: { ...MD3LightTheme.colors, ...mdTheme.light }, - }; - }, [isDarkMode, mdTheme, shouldUseDeviceColors]); + return isDarkMode ? MD3DarkTheme : MD3LightTheme; + }, [isDarkMode, shouldUseDeviceColors]); React.useEffect(() => { const restoreState = async () => { @@ -199,7 +198,7 @@ export default function PaperExample() { ); }} - + diff --git a/example/utils/index.ts b/example/utils/index.ts index f86f3a0307..4718acb993 100644 --- a/example/utils/index.ts +++ b/example/utils/index.ts @@ -1,6 +1,5 @@ import { Platform } from 'react-native'; -import ExpoMaterial3ThemeModule from '@pchmn/expo-material3-theme/build/ExpoMaterial3ThemeModule'; import { MD3DarkTheme, MD3LightTheme, MD3Theme } from 'react-native-paper'; type ReducerAction = { @@ -1421,6 +1420,4 @@ export const restaurantsData = [ ]; export const deviceColorsSupported = - Boolean(ExpoMaterial3ThemeModule) && - Platform.OS === 'android' && - Platform.Version >= 31; + Platform.OS === 'android' && (Platform.Version as number) >= 31; diff --git a/src/styles/themes/DynamicTheme.android.tsx b/src/styles/themes/DynamicTheme.android.tsx index f2791670e8..b16b4bd040 100644 --- a/src/styles/themes/DynamicTheme.android.tsx +++ b/src/styles/themes/DynamicTheme.android.tsx @@ -1,8 +1,8 @@ import { Platform, PlatformColor } from 'react-native'; -import { DarkTheme } from './DarkTheme'; -import { LightTheme } from './LightTheme'; -import type { Theme } from '../../types'; +import { MD3DarkTheme } from './v3/DarkTheme'; +import { MD3LightTheme } from './v3/LightTheme'; +import type { MD3Theme } from '../../types'; const isApi34 = (Platform.Version as number) >= 34; const isApi31 = (Platform.Version as number) >= 31; @@ -29,232 +29,232 @@ const lightColors = { primary: pick( 'system_primary_light', 'system_accent1_600', - LightTheme.colors.primary + MD3LightTheme.colors.primary ), onPrimary: pick( 'system_on_primary_light', 'system_accent1_0', - LightTheme.colors.onPrimary + MD3LightTheme.colors.onPrimary ), primaryContainer: pick( 'system_primary_container_light', 'system_accent1_100', - LightTheme.colors.primaryContainer + MD3LightTheme.colors.primaryContainer ), onPrimaryContainer: pick( 'system_on_primary_container_light', 'system_accent1_900', - LightTheme.colors.onPrimaryContainer + MD3LightTheme.colors.onPrimaryContainer ), inversePrimary: pick( 'system_primary_dark', 'system_accent1_200', - LightTheme.colors.inversePrimary + MD3LightTheme.colors.inversePrimary ), secondary: pick( 'system_secondary_light', 'system_accent2_600', - LightTheme.colors.secondary + MD3LightTheme.colors.secondary ), onSecondary: pick( 'system_on_secondary_light', 'system_accent2_0', - LightTheme.colors.onSecondary + MD3LightTheme.colors.onSecondary ), secondaryContainer: pick( 'system_secondary_container_light', 'system_accent2_100', - LightTheme.colors.secondaryContainer + MD3LightTheme.colors.secondaryContainer ), onSecondaryContainer: pick( 'system_on_secondary_container_light', 'system_accent2_900', - LightTheme.colors.onSecondaryContainer + MD3LightTheme.colors.onSecondaryContainer ), tertiary: pick( 'system_tertiary_light', 'system_accent3_600', - LightTheme.colors.tertiary + MD3LightTheme.colors.tertiary ), onTertiary: pick( 'system_on_tertiary_light', 'system_accent3_0', - LightTheme.colors.onTertiary + MD3LightTheme.colors.onTertiary ), tertiaryContainer: pick( 'system_tertiary_container_light', 'system_accent3_100', - LightTheme.colors.tertiaryContainer + MD3LightTheme.colors.tertiaryContainer ), onTertiaryContainer: pick( 'system_on_tertiary_container_light', 'system_accent3_900', - LightTheme.colors.onTertiaryContainer + MD3LightTheme.colors.onTertiaryContainer ), error: pick( 'system_error_light', - LightTheme.colors.error, - LightTheme.colors.error + MD3LightTheme.colors.error, + MD3LightTheme.colors.error ), onError: pick( 'system_on_error_light', - LightTheme.colors.onError, - LightTheme.colors.onError + MD3LightTheme.colors.onError, + MD3LightTheme.colors.onError ), errorContainer: pick( 'system_error_container_light', - LightTheme.colors.errorContainer, - LightTheme.colors.errorContainer + MD3LightTheme.colors.errorContainer, + MD3LightTheme.colors.errorContainer ), onErrorContainer: pick( 'system_on_error_container_light', - LightTheme.colors.onErrorContainer, - LightTheme.colors.onErrorContainer + MD3LightTheme.colors.onErrorContainer, + MD3LightTheme.colors.onErrorContainer ), onSurface: pick( 'system_on_surface_light', 'system_neutral1_900', - LightTheme.colors.onSurface + MD3LightTheme.colors.onSurface ), onBackground: pick( 'system_on_background_light', 'system_neutral1_900', - LightTheme.colors.onBackground + MD3LightTheme.colors.onBackground ), onSurfaceVariant: pick( 'system_on_surface_variant_light', 'system_neutral2_700', - LightTheme.colors.onSurfaceVariant + MD3LightTheme.colors.onSurfaceVariant ), outline: pick( 'system_outline_light', 'system_neutral2_500', - LightTheme.colors.outline + MD3LightTheme.colors.outline ), outlineVariant: pick( 'system_outline_variant_light', 'system_neutral2_200', - LightTheme.colors.outlineVariant + MD3LightTheme.colors.outlineVariant ), inverseSurface: pick( 'system_surface_dark', 'system_neutral1_800', - LightTheme.colors.inverseSurface + MD3LightTheme.colors.inverseSurface ), inverseOnSurface: pick( 'system_on_surface_dark', 'system_neutral1_50', - LightTheme.colors.inverseOnSurface + MD3LightTheme.colors.inverseOnSurface ), surfaceContainerLowest: pick( 'system_surface_container_lowest_light', 'system_neutral2_0', - LightTheme.colors.surfaceContainerLowest + MD3LightTheme.colors.surfaceContainerLowest ), surfaceContainerLow: pick( 'system_surface_container_low_light', - LightTheme.colors.surfaceContainerLow, - LightTheme.colors.surfaceContainerLow + MD3LightTheme.colors.surfaceContainerLow, + MD3LightTheme.colors.surfaceContainerLow ), surfaceContainerHighest: pick( 'system_surface_container_highest_light', 'system_neutral2_100', - LightTheme.colors.surfaceContainerHighest + MD3LightTheme.colors.surfaceContainerHighest ), surface: pick( 'system_surface_light', - LightTheme.colors.surface, - LightTheme.colors.surface + MD3LightTheme.colors.surface, + MD3LightTheme.colors.surface ), surfaceDim: pick( 'system_surface_dim_light', - LightTheme.colors.surfaceDim, - LightTheme.colors.surfaceDim + MD3LightTheme.colors.surfaceDim, + MD3LightTheme.colors.surfaceDim ), surfaceBright: pick( 'system_surface_bright_light', - LightTheme.colors.surfaceBright, - LightTheme.colors.surfaceBright + MD3LightTheme.colors.surfaceBright, + MD3LightTheme.colors.surfaceBright ), surfaceContainer: pick( 'system_surface_container_light', - LightTheme.colors.surfaceContainer, - LightTheme.colors.surfaceContainer + MD3LightTheme.colors.surfaceContainer, + MD3LightTheme.colors.surfaceContainer ), surfaceContainerHigh: pick( 'system_surface_container_high_light', - LightTheme.colors.surfaceContainerHigh, - LightTheme.colors.surfaceContainerHigh + MD3LightTheme.colors.surfaceContainerHigh, + MD3LightTheme.colors.surfaceContainerHigh ), background: pick( 'system_background_light', - LightTheme.colors.background, - LightTheme.colors.background + MD3LightTheme.colors.background, + MD3LightTheme.colors.background ), surfaceVariant: pick( 'system_surface_variant_light', - LightTheme.colors.surfaceVariant, - LightTheme.colors.surfaceVariant + MD3LightTheme.colors.surfaceVariant, + MD3LightTheme.colors.surfaceVariant ), primaryFixed: pick( 'system_primary_fixed', 'system_accent1_100', - LightTheme.colors.primaryFixed + MD3LightTheme.colors.primaryFixed ), primaryFixedDim: pick( 'system_primary_fixed_dim', 'system_accent1_200', - LightTheme.colors.primaryFixedDim + MD3LightTheme.colors.primaryFixedDim ), onPrimaryFixed: pick( 'system_on_primary_fixed', 'system_accent1_900', - LightTheme.colors.onPrimaryFixed + MD3LightTheme.colors.onPrimaryFixed ), onPrimaryFixedVariant: pick( 'system_on_primary_fixed_variant', 'system_accent1_700', - LightTheme.colors.onPrimaryFixedVariant + MD3LightTheme.colors.onPrimaryFixedVariant ), secondaryFixed: pick( 'system_secondary_fixed', 'system_accent2_100', - LightTheme.colors.secondaryFixed + MD3LightTheme.colors.secondaryFixed ), secondaryFixedDim: pick( 'system_secondary_fixed_dim', 'system_accent2_200', - LightTheme.colors.secondaryFixedDim + MD3LightTheme.colors.secondaryFixedDim ), onSecondaryFixed: pick( 'system_on_secondary_fixed', 'system_accent2_900', - LightTheme.colors.onSecondaryFixed + MD3LightTheme.colors.onSecondaryFixed ), onSecondaryFixedVariant: pick( 'system_on_secondary_fixed_variant', 'system_accent2_700', - LightTheme.colors.onSecondaryFixedVariant + MD3LightTheme.colors.onSecondaryFixedVariant ), tertiaryFixed: pick( 'system_tertiary_fixed', 'system_accent3_100', - LightTheme.colors.tertiaryFixed + MD3LightTheme.colors.tertiaryFixed ), tertiaryFixedDim: pick( 'system_tertiary_fixed_dim', 'system_accent3_200', - LightTheme.colors.tertiaryFixedDim + MD3LightTheme.colors.tertiaryFixedDim ), onTertiaryFixed: pick( 'system_on_tertiary_fixed', 'system_accent3_900', - LightTheme.colors.onTertiaryFixed + MD3LightTheme.colors.onTertiaryFixed ), onTertiaryFixedVariant: pick( 'system_on_tertiary_fixed_variant', 'system_accent3_700', - LightTheme.colors.onTertiaryFixedVariant + MD3LightTheme.colors.onTertiaryFixedVariant ), }; @@ -262,241 +262,241 @@ const darkColors = { primary: pick( 'system_primary_dark', 'system_accent1_200', - DarkTheme.colors.primary + MD3DarkTheme.colors.primary ), onPrimary: pick( 'system_on_primary_dark', 'system_accent1_800', - DarkTheme.colors.onPrimary + MD3DarkTheme.colors.onPrimary ), primaryContainer: pick( 'system_primary_container_dark', 'system_accent1_700', - DarkTheme.colors.primaryContainer + MD3DarkTheme.colors.primaryContainer ), onPrimaryContainer: pick( 'system_on_primary_container_dark', 'system_accent1_100', - DarkTheme.colors.onPrimaryContainer + MD3DarkTheme.colors.onPrimaryContainer ), inversePrimary: pick( 'system_primary_light', 'system_accent1_600', - DarkTheme.colors.inversePrimary + MD3DarkTheme.colors.inversePrimary ), secondary: pick( 'system_secondary_dark', 'system_accent2_200', - DarkTheme.colors.secondary + MD3DarkTheme.colors.secondary ), onSecondary: pick( 'system_on_secondary_dark', 'system_accent2_800', - DarkTheme.colors.onSecondary + MD3DarkTheme.colors.onSecondary ), secondaryContainer: pick( 'system_secondary_container_dark', 'system_accent2_700', - DarkTheme.colors.secondaryContainer + MD3DarkTheme.colors.secondaryContainer ), onSecondaryContainer: pick( 'system_on_secondary_container_dark', 'system_accent2_100', - DarkTheme.colors.onSecondaryContainer + MD3DarkTheme.colors.onSecondaryContainer ), tertiary: pick( 'system_tertiary_dark', 'system_accent3_200', - DarkTheme.colors.tertiary + MD3DarkTheme.colors.tertiary ), onTertiary: pick( 'system_on_tertiary_dark', 'system_accent3_800', - DarkTheme.colors.onTertiary + MD3DarkTheme.colors.onTertiary ), tertiaryContainer: pick( 'system_tertiary_container_dark', 'system_accent3_700', - DarkTheme.colors.tertiaryContainer + MD3DarkTheme.colors.tertiaryContainer ), onTertiaryContainer: pick( 'system_on_tertiary_container_dark', 'system_accent3_100', - DarkTheme.colors.onTertiaryContainer + MD3DarkTheme.colors.onTertiaryContainer ), error: pick( 'system_error_dark', - DarkTheme.colors.error, - DarkTheme.colors.error + MD3DarkTheme.colors.error, + MD3DarkTheme.colors.error ), onError: pick( 'system_on_error_dark', - DarkTheme.colors.onError, - DarkTheme.colors.onError + MD3DarkTheme.colors.onError, + MD3DarkTheme.colors.onError ), errorContainer: pick( 'system_error_container_dark', - DarkTheme.colors.errorContainer, - DarkTheme.colors.errorContainer + MD3DarkTheme.colors.errorContainer, + MD3DarkTheme.colors.errorContainer ), onErrorContainer: pick( 'system_on_error_container_dark', - DarkTheme.colors.onErrorContainer, - DarkTheme.colors.onErrorContainer + MD3DarkTheme.colors.onErrorContainer, + MD3DarkTheme.colors.onErrorContainer ), onSurface: pick( 'system_on_surface_dark', 'system_neutral1_100', - DarkTheme.colors.onSurface + MD3DarkTheme.colors.onSurface ), onBackground: pick( 'system_on_background_dark', 'system_neutral1_100', - DarkTheme.colors.onBackground + MD3DarkTheme.colors.onBackground ), onSurfaceVariant: pick( 'system_on_surface_variant_dark', 'system_neutral2_200', - DarkTheme.colors.onSurfaceVariant + MD3DarkTheme.colors.onSurfaceVariant ), outline: pick( 'system_outline_dark', 'system_neutral2_400', - DarkTheme.colors.outline + MD3DarkTheme.colors.outline ), outlineVariant: pick( 'system_outline_variant_dark', 'system_neutral2_700', - DarkTheme.colors.outlineVariant + MD3DarkTheme.colors.outlineVariant ), inverseSurface: pick( 'system_surface_light', 'system_neutral1_100', - DarkTheme.colors.inverseSurface + MD3DarkTheme.colors.inverseSurface ), inverseOnSurface: pick( 'system_on_surface_light', 'system_neutral1_800', - DarkTheme.colors.inverseOnSurface + MD3DarkTheme.colors.inverseOnSurface ), surfaceContainerLowest: pick( 'system_surface_container_lowest_dark', - DarkTheme.colors.surfaceContainerLowest, - DarkTheme.colors.surfaceContainerLowest + MD3DarkTheme.colors.surfaceContainerLowest, + MD3DarkTheme.colors.surfaceContainerLowest ), surfaceContainerLow: pick( 'system_surface_container_low_dark', 'system_neutral2_900', - DarkTheme.colors.surfaceContainerLow + MD3DarkTheme.colors.surfaceContainerLow ), surfaceContainerHighest: pick( 'system_surface_container_highest_dark', - DarkTheme.colors.surfaceContainerHighest, - DarkTheme.colors.surfaceContainerHighest + MD3DarkTheme.colors.surfaceContainerHighest, + MD3DarkTheme.colors.surfaceContainerHighest ), surface: pick( 'system_surface_dark', - DarkTheme.colors.surface, - DarkTheme.colors.surface + MD3DarkTheme.colors.surface, + MD3DarkTheme.colors.surface ), surfaceDim: pick( 'system_surface_dim_dark', - DarkTheme.colors.surfaceDim, - DarkTheme.colors.surfaceDim + MD3DarkTheme.colors.surfaceDim, + MD3DarkTheme.colors.surfaceDim ), surfaceBright: pick( 'system_surface_bright_dark', - DarkTheme.colors.surfaceBright, - DarkTheme.colors.surfaceBright + MD3DarkTheme.colors.surfaceBright, + MD3DarkTheme.colors.surfaceBright ), surfaceContainer: pick( 'system_surface_container_dark', - DarkTheme.colors.surfaceContainer, - DarkTheme.colors.surfaceContainer + MD3DarkTheme.colors.surfaceContainer, + MD3DarkTheme.colors.surfaceContainer ), surfaceContainerHigh: pick( 'system_surface_container_high_dark', - DarkTheme.colors.surfaceContainerHigh, - DarkTheme.colors.surfaceContainerHigh + MD3DarkTheme.colors.surfaceContainerHigh, + MD3DarkTheme.colors.surfaceContainerHigh ), background: pick( 'system_background_dark', - DarkTheme.colors.background, - DarkTheme.colors.background + MD3DarkTheme.colors.background, + MD3DarkTheme.colors.background ), surfaceVariant: pick( 'system_surface_variant_dark', - DarkTheme.colors.surfaceVariant, - DarkTheme.colors.surfaceVariant + MD3DarkTheme.colors.surfaceVariant, + MD3DarkTheme.colors.surfaceVariant ), primaryFixed: pick( 'system_primary_fixed', 'system_accent1_100', - DarkTheme.colors.primaryFixed + MD3DarkTheme.colors.primaryFixed ), primaryFixedDim: pick( 'system_primary_fixed_dim', 'system_accent1_200', - DarkTheme.colors.primaryFixedDim + MD3DarkTheme.colors.primaryFixedDim ), onPrimaryFixed: pick( 'system_on_primary_fixed', 'system_accent1_900', - DarkTheme.colors.onPrimaryFixed + MD3DarkTheme.colors.onPrimaryFixed ), onPrimaryFixedVariant: pick( 'system_on_primary_fixed_variant', 'system_accent1_700', - DarkTheme.colors.onPrimaryFixedVariant + MD3DarkTheme.colors.onPrimaryFixedVariant ), secondaryFixed: pick( 'system_secondary_fixed', 'system_accent2_100', - DarkTheme.colors.secondaryFixed + MD3DarkTheme.colors.secondaryFixed ), secondaryFixedDim: pick( 'system_secondary_fixed_dim', 'system_accent2_200', - DarkTheme.colors.secondaryFixedDim + MD3DarkTheme.colors.secondaryFixedDim ), onSecondaryFixed: pick( 'system_on_secondary_fixed', 'system_accent2_900', - DarkTheme.colors.onSecondaryFixed + MD3DarkTheme.colors.onSecondaryFixed ), onSecondaryFixedVariant: pick( 'system_on_secondary_fixed_variant', 'system_accent2_700', - DarkTheme.colors.onSecondaryFixedVariant + MD3DarkTheme.colors.onSecondaryFixedVariant ), tertiaryFixed: pick( 'system_tertiary_fixed', 'system_accent3_100', - DarkTheme.colors.tertiaryFixed + MD3DarkTheme.colors.tertiaryFixed ), tertiaryFixedDim: pick( 'system_tertiary_fixed_dim', 'system_accent3_200', - DarkTheme.colors.tertiaryFixedDim + MD3DarkTheme.colors.tertiaryFixedDim ), onTertiaryFixed: pick( 'system_on_tertiary_fixed', 'system_accent3_900', - DarkTheme.colors.onTertiaryFixed + MD3DarkTheme.colors.onTertiaryFixed ), onTertiaryFixedVariant: pick( 'system_on_tertiary_fixed_variant', 'system_accent3_700', - DarkTheme.colors.onTertiaryFixedVariant + MD3DarkTheme.colors.onTertiaryFixedVariant ), }; -export const DynamicLightTheme: Theme = { - ...LightTheme, - colors: { ...LightTheme.colors, ...lightColors }, +export const DynamicLightTheme: MD3Theme = { + ...MD3LightTheme, + colors: { ...MD3LightTheme.colors, ...lightColors }, }; -export const DynamicDarkTheme: Theme = { - ...DarkTheme, - colors: { ...DarkTheme.colors, ...darkColors }, +export const DynamicDarkTheme: MD3Theme = { + ...MD3DarkTheme, + colors: { ...MD3DarkTheme.colors, ...darkColors }, }; diff --git a/src/styles/themes/DynamicTheme.tsx b/src/styles/themes/DynamicTheme.tsx index 78e3cc5c8d..6669c63a45 100644 --- a/src/styles/themes/DynamicTheme.tsx +++ b/src/styles/themes/DynamicTheme.tsx @@ -1,2 +1,2 @@ -export { DarkTheme as MD3DynamicDarkTheme } from './DarkTheme'; -export { LightTheme as MD3DynamicLightTheme } from './LightTheme'; +export { MD3DarkTheme as MD3DynamicDarkTheme } from './v3/DarkTheme'; +export { MD3LightTheme as MD3DynamicLightTheme } from './v3/LightTheme'; diff --git a/src/styles/themes/index.ts b/src/styles/themes/index.ts index 39bcb6648c..f992ef7e73 100644 --- a/src/styles/themes/index.ts +++ b/src/styles/themes/index.ts @@ -1,2 +1,3 @@ export { MD3LightTheme } from './v3/LightTheme'; export { MD3DarkTheme } from './v3/DarkTheme'; +export { DynamicLightTheme, DynamicDarkTheme } from './DynamicTheme'; diff --git a/yarn.lock b/yarn.lock index 3920e64583..9696c756fb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3887,13 +3887,6 @@ __metadata: languageName: node linkType: hard -"@material/material-color-utilities@npm:^0.2.7": - version: 0.2.7 - resolution: "@material/material-color-utilities@npm:0.2.7" - checksum: 10c0/7734f8d7cffe6a92d47fcca82b4846e39ffd79be9c057f3299466696dcdee5379b8a8a3aa6a9692d40bd6900905f689105d9a8ce47882ab22348df10621f70cd - languageName: node - linkType: hard - "@mdx-js/mdx@npm:^0.20.3": version: 0.20.3 resolution: "@mdx-js/mdx@npm:0.20.3" @@ -4317,20 +4310,6 @@ __metadata: languageName: node linkType: hard -"@pchmn/expo-material3-theme@npm:^1.3.2": - version: 1.3.2 - resolution: "@pchmn/expo-material3-theme@npm:1.3.2" - dependencies: - "@material/material-color-utilities": "npm:^0.2.7" - color: "npm:^4.2.3" - peerDependencies: - expo: "*" - react: "*" - react-native: "*" - checksum: 10c0/89aa0a65b04f4a7f709c35bbdc2f7830dff73e0335877d36a091c55fb174ce82e4b2c67690657978b03fc563ab4c20565ded0ed7faec94d0a384a9c5085dfe19 - languageName: node - linkType: hard - "@polka/url@npm:^1.0.0-next.24": version: 1.0.0-next.29 resolution: "@polka/url@npm:1.0.0-next.29" @@ -20063,7 +20042,6 @@ __metadata: "@babel/core": "npm:^7.25.2" "@expo/vector-icons": "npm:^15.0.2" "@expo/webpack-config": "npm:~19.0.1" - "@pchmn/expo-material3-theme": "npm:^1.3.2" "@react-native-async-storage/async-storage": "npm:2.2.0" "@react-native-masked-view/masked-view": "npm:0.3.2" "@react-navigation/bottom-tabs": "npm:^7.3.10" From 329d923afb2f3f8d2abc3f97973b42ebae23c210 Mon Sep 17 00:00:00 2001 From: Adrian Cotfas Date: Wed, 8 Apr 2026 09:15:20 +0300 Subject: [PATCH 11/13] refactor: rename "device colors" to "Dynamic Theme" --- example/src/DrawerItems.tsx | 16 ++++++++-------- example/src/PreferencesContext.tsx | 4 ++-- example/src/index.native.tsx | 16 ++++++++-------- example/src/index.tsx | 4 ++-- example/utils/index.ts | 2 +- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/example/src/DrawerItems.tsx b/example/src/DrawerItems.tsx index 2a31565f67..8bcee32967 100644 --- a/example/src/DrawerItems.tsx +++ b/example/src/DrawerItems.tsx @@ -16,7 +16,7 @@ import { Portal, } from 'react-native-paper'; -import { deviceColorsSupported, isWeb } from '../utils'; +import { dynamicThemeSupported, isWeb } from '../utils'; import { useExampleTheme } from './hooks/useExampleTheme'; import { PreferencesContext } from './PreferencesContext'; @@ -103,7 +103,7 @@ function DrawerItems() { if (!preferences) throw new Error('PreferencesContext not provided'); const { - toggleShouldUseDeviceColors, + toggleShouldUseDynamicTheme, toggleTheme, toggleRtl: toggleRTL, toggleCollapsed, @@ -114,7 +114,7 @@ function DrawerItems() { collapsed, rtl: isRTL, theme: { dark: isDarkTheme }, - shouldUseDeviceColors, + shouldUseDynamicTheme, } = preferences; const _handleToggleRTL = () => { @@ -181,12 +181,12 @@ function DrawerItems() { - {deviceColorsSupported && isV3 ? ( - - - Use device colors * + {dynamicThemeSupported ? ( + + + Use Dynamic Theme - + diff --git a/example/src/PreferencesContext.tsx b/example/src/PreferencesContext.tsx index fcf3642d57..ffe0e1cb8a 100644 --- a/example/src/PreferencesContext.tsx +++ b/example/src/PreferencesContext.tsx @@ -8,11 +8,11 @@ export const PreferencesContext = React.createContext<{ toggleCollapsed: () => void; toggleCustomFont: () => void; toggleRippleEffect: () => void; - toggleShouldUseDeviceColors?: () => void; + toggleShouldUseDynamicTheme?: () => void; theme: MD3Theme; rtl: boolean; collapsed: boolean; customFontLoaded: boolean; rippleEffectEnabled: boolean; - shouldUseDeviceColors?: boolean; + shouldUseDynamicTheme?: boolean; } | null>(null); diff --git a/example/src/index.native.tsx b/example/src/index.native.tsx index 402232ccc6..821386cc83 100644 --- a/example/src/index.native.tsx +++ b/example/src/index.native.tsx @@ -20,7 +20,7 @@ import { SafeAreaInsetsContext } from 'react-native-safe-area-context'; import DrawerItems from './DrawerItems'; import { PreferencesContext } from './PreferencesContext'; import App from './RootNavigator'; -import { deviceColorsSupported } from '../utils'; +import { dynamicThemeSupported } from '../utils'; import { CombinedDefaultTheme, CombinedDarkTheme, @@ -45,7 +45,7 @@ export default function PaperExample() { InitialState | undefined >(); - const [shouldUseDeviceColors, setShouldUseDeviceColors] = + const [shouldUseDynamicTheme, setShouldUseDynamicTheme] = React.useState(true); const [isDarkMode, setIsDarkMode] = React.useState(false); const [rtl, setRtl] = React.useState( @@ -56,12 +56,12 @@ export default function PaperExample() { const [rippleEffectEnabled, setRippleEffectEnabled] = React.useState(true); const theme = React.useMemo(() => { - if (deviceColorsSupported && shouldUseDeviceColors) { + if (dynamicThemeSupported && shouldUseDynamicTheme) { return isDarkMode ? DynamicDarkTheme : DynamicLightTheme; } return isDarkMode ? MD3DarkTheme : MD3LightTheme; - }, [isDarkMode, shouldUseDeviceColors]); + }, [isDarkMode, shouldUseDynamicTheme]); React.useEffect(() => { const restoreState = async () => { @@ -128,8 +128,8 @@ export default function PaperExample() { const preferences = React.useMemo( () => ({ - toggleShouldUseDeviceColors: () => - setShouldUseDeviceColors((oldValue) => !oldValue), + toggleShouldUseDynamicTheme: () => + setShouldUseDynamicTheme((oldValue) => !oldValue), toggleTheme: () => setIsDarkMode((oldValue) => !oldValue), toggleRtl: () => setRtl((rtl) => !rtl), toggleCollapsed: () => setCollapsed(!collapsed), @@ -140,14 +140,14 @@ export default function PaperExample() { collapsed, rtl, theme, - shouldUseDeviceColors, + shouldUseDynamicTheme: shouldUseDynamicTheme, }), [ rtl, theme, collapsed, customFontLoaded, - shouldUseDeviceColors, + shouldUseDynamicTheme, rippleEffectEnabled, ] ); diff --git a/example/src/index.tsx b/example/src/index.tsx index 4395d2d55e..a6ee5ccc08 100644 --- a/example/src/index.tsx +++ b/example/src/index.tsx @@ -111,9 +111,9 @@ export default function PaperExample() { rippleEffectEnabled, // noop for web, specified to avoid type errors toggleRtl: noop, - toggleShouldUseDeviceColors: noop, + toggleShouldUseDynamicTheme: noop, rtl: false, - shouldUseDeviceColors: false, + shouldUseDynamicTheme: false, }), [theme, collapsed, customFontLoaded, rippleEffectEnabled] ); diff --git a/example/utils/index.ts b/example/utils/index.ts index 4718acb993..d0856f19a5 100644 --- a/example/utils/index.ts +++ b/example/utils/index.ts @@ -1419,5 +1419,5 @@ export const restaurantsData = [ }, ]; -export const deviceColorsSupported = +export const dynamicThemeSupported = Platform.OS === 'android' && (Platform.Version as number) >= 31; From 7e6e009728e177e9a6c6f7e0a8885bebd3838a01 Mon Sep 17 00:00:00 2001 From: Adrian Cotfas Date: Tue, 14 Apr 2026 14:57:38 +0300 Subject: [PATCH 12/13] feat: update Colors and stateOpacity tokens for PlatformColor compatibility * surfaceDisabled, onSurfaceDisabled and backdrop which were not part of the MD standard were removed * the reference theme elevation colors now use the correct neutral tones; see https://m3.material.io/blog/tone-based-surface-color-m3 * replace usage of "alpha" with opacity or surface colors * remove disabled FAB prop --- example/src/Examples/AppbarExample.tsx | 2 +- example/src/Examples/FABExample.tsx | 8 - src/components/Appbar/Appbar.tsx | 2 +- src/components/Appbar/utils.ts | 2 +- .../BottomNavigation/BottomNavigationBar.tsx | 2 +- src/components/Button/Button.tsx | 41 +- src/components/Button/utils.tsx | 36 +- src/components/Checkbox/CheckboxAndroid.tsx | 10 +- src/components/Checkbox/CheckboxIOS.tsx | 3 +- src/components/Checkbox/CheckboxItem.tsx | 7 +- src/components/Checkbox/utils.ts | 56 +- src/components/Chip/Chip.tsx | 12 +- src/components/Chip/helpers.tsx | 52 +- .../DataTable/DataTablePagination.tsx | 3 +- src/components/DataTable/DataTableTitle.tsx | 4 +- src/components/Dialog/Dialog.tsx | 4 +- src/components/FAB/AnimatedFAB.tsx | 19 +- src/components/FAB/FAB.tsx | 13 +- src/components/FAB/FABGroup.tsx | 12 +- src/components/FAB/utils.ts | 41 +- src/components/HelperText/HelperText.tsx | 63 +- src/components/HelperText/utils.ts | 18 +- src/components/IconButton/IconButton.tsx | 32 +- src/components/IconButton/utils.ts | 42 +- src/components/Menu/MenuItem.tsx | 4 +- src/components/Menu/utils.ts | 32 +- src/components/Modal.tsx | 10 +- .../RadioButton/RadioButtonAndroid.tsx | 16 +- src/components/RadioButton/RadioButtonIOS.tsx | 3 +- .../RadioButton/RadioButtonItem.tsx | 7 +- src/components/Searchbar.tsx | 2 +- .../SegmentedButtons/SegmentedButtonItem.tsx | 6 +- src/components/SegmentedButtons/utils.ts | 11 +- src/components/Switch/utils.ts | 2 +- src/components/TextInput/Addons/Underline.tsx | 3 + .../TextInput/Adornment/TextInputAffix.tsx | 11 +- .../TextInput/Adornment/TextInputIcon.tsx | 4 +- src/components/TextInput/Adornment/utils.ts | 29 +- src/components/TextInput/Label/InputLabel.tsx | 10 +- src/components/TextInput/TextInputFlat.tsx | 4 + .../TextInput/TextInputOutlined.tsx | 3 + src/components/TextInput/helpers.tsx | 47 +- src/components/TextInput/types.tsx | 1 + src/components/ToggleButton/utils.ts | 10 +- src/components/TouchableRipple/utils.ts | 2 +- .../__tests__/Appbar/Appbar.test.tsx | 15 - .../Appbar/__snapshots__/Appbar.test.tsx.snap | 344 ++++---- src/components/__tests__/Button.test.tsx | 27 +- .../__snapshots__/CheckboxItem.test.tsx.snap | 5 + .../__tests__/Checkbox/utils.test.tsx | 85 +- src/components/__tests__/Chip.test.tsx | 124 +-- src/components/__tests__/FAB.test.tsx | 36 +- src/components/__tests__/FABGroup.test.tsx | 31 +- src/components/__tests__/IconButton.test.tsx | 15 +- src/components/__tests__/MenuItem.test.tsx | 13 +- src/components/__tests__/Modal.test.tsx | 33 +- .../RadioButtonItem.test.tsx.snap | 4 + .../__tests__/SegmentedButton.test.tsx | 12 +- src/components/__tests__/Surface.test.tsx | 4 +- src/components/__tests__/Switch.test.tsx | 2 +- src/components/__tests__/TextInput.test.tsx | 40 +- .../__tests__/ToggleButton.test.tsx | 16 +- .../__snapshots__/Banner.test.tsx.snap | 36 +- .../BottomNavigation.test.tsx.snap | 22 +- .../__snapshots__/Button.test.tsx.snap | 43 +- .../__snapshots__/Chip.test.tsx.snap | 26 +- .../__snapshots__/DataTable.test.tsx.snap | 741 ++++++++++-------- .../__tests__/__snapshots__/FAB.test.tsx.snap | 174 ---- .../__snapshots__/IconButton.test.tsx.snap | 346 ++++---- .../__snapshots__/ListItem.test.tsx.snap | 3 + .../__snapshots__/ListSection.test.tsx.snap | 30 +- .../__snapshots__/Menu.test.tsx.snap | 35 +- .../__snapshots__/MenuItem.test.tsx.snap | 23 +- .../__snapshots__/Searchbar.test.tsx.snap | 312 ++++---- .../SegmentedButton.test.tsx.snap | 2 + .../__snapshots__/Snackbar.test.tsx.snap | 3 + .../__snapshots__/TextInput.test.tsx.snap | 173 ++-- .../__snapshots__/ToggleButton.test.tsx.snap | 186 +++-- src/core/__tests__/theming.test.tsx | 16 +- src/core/theming.tsx | 26 +- src/styles/themes/v3/DarkTheme.tsx | 23 +- src/styles/themes/v3/LightTheme.tsx | 23 +- src/styles/themes/v3/tokens.tsx | 17 +- src/types.tsx | 43 +- 84 files changed, 1965 insertions(+), 1845 deletions(-) diff --git a/example/src/Examples/AppbarExample.tsx b/example/src/Examples/AppbarExample.tsx index a5b1042ea5..f70294e67e 100644 --- a/example/src/Examples/AppbarExample.tsx +++ b/example/src/Examples/AppbarExample.tsx @@ -186,7 +186,7 @@ const AppbarExample = ({ navigation }: Props) => { height: height + bottom, }, { - backgroundColor: theme.colors.elevation.level2, + backgroundColor: theme.colors.surfaceContainerHigh, }, ]} safeAreaInsets={{ bottom, left, right }} diff --git a/example/src/Examples/FABExample.tsx b/example/src/Examples/FABExample.tsx index 0cff916980..8052c90647 100644 --- a/example/src/Examples/FABExample.tsx +++ b/example/src/Examples/FABExample.tsx @@ -117,14 +117,6 @@ const FABExample = () => { onPress={() => {}} visible={visible} /> - {}} - visible={visible} - disabled - /> ({ backgroundColor?: ColorValue; }; - const backgroundColor = customBackground || colors.elevation.level2; + const backgroundColor = customBackground || colors.surfaceContainer; const activeTintColor = getActiveTintColor({ activeColor, diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx index 516ff915f7..9f0b3a98dc 100644 --- a/src/components/Button/Button.tsx +++ b/src/components/Button/Button.tsx @@ -274,15 +274,21 @@ const Button = ( const borderRadius = 5 * roundness; const iconSize = 18; - const { backgroundColor, borderColor, textColor, borderWidth } = - getButtonColors({ - customButtonColor, - customTextColor, - theme, - mode, - disabled, - dark, - }); + const { + backgroundColor, + borderColor, + textColor, + textOpacity, + borderWidth, + backgroundOpacity, + } = getButtonColors({ + customButtonColor, + customTextColor, + theme, + mode, + disabled, + dark, + }); const touchableStyle = { ...borderRadiusStyles, @@ -290,7 +296,7 @@ const Button = ( }; const buttonStyle = { - backgroundColor, + backgroundColor: backgroundOpacity < 1 ? 'transparent' : backgroundColor, borderColor, borderWidth, ...touchableStyle, @@ -337,6 +343,19 @@ const Button = ( elevation={elevation} container > + {backgroundOpacity < 1 && ( + + )} - + {icon && loading !== true ? ( { - const { colors } = theme as MD3Theme; - if (disabled && isMode('outlined')) { - return colors.surfaceDisabled; - } - +const getButtonBorderColor = ({ isMode, theme }: BaseProps) => { if (isMode('outlined')) { - return colors.outline; + return theme.colors.outlineVariant; } return 'transparent'; @@ -179,15 +170,24 @@ export const getButtonColors = ({ dark, }); - const borderColor = getButtonBorderColor({ isMode, theme, disabled }); + const borderColor = getButtonBorderColor({ isMode, theme }); const borderWidth = getButtonBorderWidth({ isMode, theme }); + const textOpacity = disabled ? stateOpacity.disabled : stateOpacity.enabled; + + const backgroundOpacity = + disabled && !isMode('outlined') && !isMode('text') + ? stateOpacity.pressed + : stateOpacity.enabled; + return { backgroundColor, borderColor, textColor, + textOpacity, borderWidth, + backgroundOpacity, }; }; diff --git a/src/components/Checkbox/CheckboxAndroid.tsx b/src/components/Checkbox/CheckboxAndroid.tsx index 642602b0fa..a4e6fb0c23 100644 --- a/src/components/Checkbox/CheckboxAndroid.tsx +++ b/src/components/Checkbox/CheckboxAndroid.tsx @@ -99,7 +99,7 @@ const CheckboxAndroid = ({ const checked = status === 'checked'; const indeterminate = status === 'indeterminate'; - const { rippleColor, selectionControlColor } = + const { selectionControlColor, selectionControlOpacity } = getAndroidSelectionControlColor({ theme, disabled, @@ -123,7 +123,6 @@ const CheckboxAndroid = ({ - + { - if (disabled) { - return color(theme.colors.onSurface).alpha(0.16).rgb().string(); - } - - return color(checkedColor).fade(0.32).rgb().string(); -}; - const getAndroidControlColor = ({ theme, checked, @@ -60,7 +45,7 @@ const getAndroidControlColor = ({ disabled?: boolean; }) => { if (disabled) { - return theme.colors.onSurfaceDisabled; + return theme.colors.onSurface; } if (checked) { @@ -87,8 +72,11 @@ export const getAndroidSelectionControlColor = ({ theme, customUncheckedColor, }); + const selectionControlOpacity = disabled + ? stateOpacity.disabled + : stateOpacity.enabled; + return { - rippleColor: getAndroidRippleColor({ theme, checkedColor, disabled }), selectionControlColor: getAndroidControlColor({ theme, disabled, @@ -96,6 +84,7 @@ export const getAndroidSelectionControlColor = ({ checkedColor, uncheckedColor, }), + selectionControlOpacity, }; }; @@ -109,7 +98,7 @@ const getIOSCheckedColor = ({ disabled?: boolean; }) => { if (disabled) { - return theme.colors.onSurfaceDisabled; + return theme.colors.primary; } if (customColor) { @@ -119,21 +108,6 @@ const getIOSCheckedColor = ({ return theme.colors.primary; }; -const getIOSRippleColor = ({ - theme, - checkedColor, - disabled, -}: { - theme: InternalTheme; - checkedColor: string; - disabled?: boolean; -}) => { - if (disabled) { - return color(theme.colors.onSurface).alpha(0.16).rgb().string(); - } - return color(checkedColor).fade(0.32).rgb().string(); -}; - export const getSelectionControlIOSColor = ({ theme, disabled, @@ -144,12 +118,12 @@ export const getSelectionControlIOSColor = ({ customColor?: string; }) => { const checkedColor = getIOSCheckedColor({ theme, disabled, customColor }); + const checkedColorOpacity = disabled + ? stateOpacity.disabled + : stateOpacity.enabled; + return { checkedColor, - rippleColor: getIOSRippleColor({ - theme, - checkedColor, - disabled, - }), + checkedColorOpacity, }; }; diff --git a/src/components/Chip/Chip.tsx b/src/components/Chip/Chip.tsx index 012cac4fc1..2c79e8201d 100644 --- a/src/components/Chip/Chip.tsx +++ b/src/components/Chip/Chip.tsx @@ -196,7 +196,6 @@ const Chip = ({ theme: themeOverrides, testID = 'chip', selectedColor, - showSelectedOverlay = false, showSelectedCheck = true, ellipsizeMode, compact, @@ -257,13 +256,13 @@ const Chip = ({ borderColor, textColor, iconColor, + contentOpacity, selectedBackgroundColor, backgroundColor, } = getChipColors({ isOutlined, theme, selectedColor, - showSelectedOverlay, customBackgroundColor, disabled, }); @@ -324,7 +323,14 @@ const Chip = ({ theme={theme} hitSlop={hitSlop} > - + {avatar && !icon ? ( theme as MD3Theme; +const { stateOpacity } = tokens.md.ref; + export type ChipAvatarProps = { style?: StyleProp; }; @@ -21,7 +24,6 @@ const getBorderColor = ({ isOutlined, disabled, selectedColor, - backgroundColor: _backgroundColor, }: BaseProps & { backgroundColor: string; selectedColor?: string }) => { const isSelectedColor = selectedColor !== undefined; const { colors } = md3(theme); @@ -32,14 +34,14 @@ const getBorderColor = ({ } if (disabled) { - return color(colors.onSurfaceVariant).alpha(0.12).rgb().string(); + return colors.surfaceContainer; } if (isSelectedColor) { return color(selectedColor).alpha(0.29).rgb().string(); } - return colors.outline; + return colors.outlineVariant; }; const getTextColor = ({ @@ -53,7 +55,7 @@ const getTextColor = ({ const isSelectedColor = selectedColor !== undefined; const { colors } = md3(theme); if (disabled) { - return colors.onSurfaceDisabled; + return colors.onSurface; } if (isSelectedColor) { @@ -96,7 +98,7 @@ const getBackgroundColor = ({ if (isOutlined) { return 'transparent'; } - return color(colors.onSurfaceVariant).alpha(0.12).rgb().string(); + return colors.surfaceContainerLow; } return getDefaultBackgroundColor({ theme, isOutlined }); @@ -107,43 +109,15 @@ const getSelectedBackgroundColor = ({ isOutlined, disabled, customBackgroundColor, - showSelectedOverlay, }: BaseProps & { customBackgroundColor?: ColorValue; - showSelectedOverlay?: boolean; }) => { - const { colors } = md3(theme); - const backgroundColor = getBackgroundColor({ + return getBackgroundColor({ theme, disabled, isOutlined, customBackgroundColor, }); - - if (isOutlined) { - if (showSelectedOverlay) { - return color(backgroundColor) - .mix(color(colors.onSurfaceVariant), 0.12) - .rgb() - .string(); - } - return color(backgroundColor) - .mix(color(colors.onSurfaceVariant), 0) - .rgb() - .string(); - } - - if (showSelectedOverlay) { - return color(backgroundColor) - .mix(color(colors.onSecondaryContainer), 0.12) - .rgb() - .string(); - } - - return color(backgroundColor) - .mix(color(colors.onSecondaryContainer), 0) - .rgb() - .string(); }; const getIconColor = ({ @@ -157,7 +131,7 @@ const getIconColor = ({ const isSelectedColor = selectedColor !== undefined; const { colors } = md3(theme); if (disabled) { - return colors.onSurfaceDisabled; + return colors.onSurface; } if (isSelectedColor) { @@ -175,13 +149,11 @@ export const getChipColors = ({ isOutlined, theme, selectedColor, - showSelectedOverlay, customBackgroundColor, disabled, }: BaseProps & { customBackgroundColor?: ColorValue; disabled?: boolean; - showSelectedOverlay?: boolean; selectedColor?: string; }) => { const baseChipColorProps = { theme, isOutlined, disabled }; @@ -194,9 +166,12 @@ export const getChipColors = ({ const selectedBackgroundColor = getSelectedBackgroundColor({ ...baseChipColorProps, customBackgroundColor, - showSelectedOverlay, }); + const contentOpacity = disabled + ? stateOpacity.disabled + : stateOpacity.enabled; + return { borderColor: getBorderColor({ ...baseChipColorProps, @@ -211,6 +186,7 @@ export const getChipColors = ({ ...baseChipColorProps, selectedColor, }), + contentOpacity, backgroundColor, selectedBackgroundColor, }; diff --git a/src/components/DataTable/DataTablePagination.tsx b/src/components/DataTable/DataTablePagination.tsx index 6e2612973e..6a3fc52b3d 100644 --- a/src/components/DataTable/DataTablePagination.tsx +++ b/src/components/DataTable/DataTablePagination.tsx @@ -7,7 +7,6 @@ import { ViewStyle, } from 'react-native'; -import color from 'color'; import type { ThemeProp } from 'src/types'; import { useInternalTheme } from '../../core/theming'; @@ -286,7 +285,7 @@ const DataTablePagination = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); - const labelColor = color(theme.colors.onSurface).alpha(0.6).rgb().string(); + const labelColor = theme.colors.onSurfaceVariant; return ( { const { right, left } = useSafeAreaInsets(); const theme = useInternalTheme(themeOverrides); - const { roundness, colors } = theme as MD3Theme; + const { roundness } = theme as MD3Theme; const borderRadius = 7 * roundness; - const backgroundColor = colors.elevation.level3; + const backgroundColor = theme.colors.surfaceContainerHigh; return ( , 'mode'> & { * Custom color for the icon and label of the `FAB`. */ color?: string; - /** - * Whether `FAB` is disabled. A disabled button is greyed out and `onPress` is not called on touch. - */ - disabled?: boolean; /** * Whether `FAB` is currently visible. */ @@ -206,7 +202,6 @@ const AnimatedFAB = ({ accessibilityLabel = label, accessibilityState, color: customColor, - disabled, onPress, onLongPress, delayLongPress, @@ -300,7 +295,6 @@ const AnimatedFAB = ({ const { backgroundColor, foregroundColor } = getFABColors({ theme, variant, - disabled, customColor, customBackgroundColor, }); @@ -359,15 +353,12 @@ const AnimatedFAB = ({ ...font, }; - const md3Elevation = disabled || !isIOS ? 0 : 3; + const md3Elevation = !isIOS ? 0 : 3; const shadowStyle = styles.v3Shadow; - const baseStyle = [ - StyleSheet.absoluteFill, - disabled ? styles.disabled : shadowStyle, - ]; + const baseStyle = [StyleSheet.absoluteFill, shadowStyle]; - const newAccessibilityState = { ...accessibilityState, disabled }; + const newAccessibilityState = { ...accessibilityState }; return ( , 'mode'> & { * Custom color for the icon and label of the `FAB`. */ color?: string; - /** - * Whether `FAB` is disabled. A disabled button is greyed out and `onPress` is not called on touch. - */ - disabled?: boolean; /** * Whether `FAB` is currently visible. */ @@ -184,7 +180,6 @@ const FAB = forwardRef( accessibilityState, animated = true, color: customColor, - disabled, onPress, onLongPress, delayLongPress, @@ -239,7 +234,6 @@ const FAB = forwardRef( const { backgroundColor, foregroundColor } = getFABColors({ theme, variant, - disabled, customColor, customBackgroundColor, }); @@ -256,9 +250,7 @@ const FAB = forwardRef( ...font, }; - const md3Elevation = isFlatMode || disabled ? 0 : 3; - - const newAccessibilityState = { ...accessibilityState, disabled }; + const md3Elevation = isFlatMode ? 0 : 3; return ( ( onPress={onPress} onLongPress={onLongPress} delayLongPress={delayLongPress} - disabled={disabled} accessibilityLabel={accessibilityLabel} accessibilityRole="button" - accessibilityState={newAccessibilityState} + accessibilityState={accessibilityState} testID={testID} style={{ borderRadius }} {...rest} diff --git a/src/components/FAB/FABGroup.tsx b/src/components/FAB/FABGroup.tsx index 5579728d98..595739b57c 100644 --- a/src/components/FAB/FABGroup.tsx +++ b/src/components/FAB/FABGroup.tsx @@ -306,15 +306,19 @@ const FABGroup = ({ } }; - const { labelColor, backdropColor, stackedFABBackgroundColor } = - getFABGroupColors({ theme, customBackdropColor }); + const { + labelColor, + backdropColor, + backdropOpacity: backdropMaxOpacity, + stackedFABBackgroundColor, + } = getFABGroupColors({ theme, customBackdropColor }); const backdropOpacity = open ? backdrop.interpolate({ inputRange: [0, 0.5, 1], - outputRange: [0, 1, 1], + outputRange: [0, backdropMaxOpacity, backdropMaxOpacity], }) - : backdrop; + : Animated.multiply(backdrop, backdropMaxOpacity); const opacities = animations.current; diff --git a/src/components/FAB/utils.ts b/src/components/FAB/utils.ts index 384fcc6c45..ad49fa13be 100644 --- a/src/components/FAB/utils.ts +++ b/src/components/FAB/utils.ts @@ -7,8 +7,6 @@ import { ViewStyle, } from 'react-native'; -import color from 'color'; - import type { InternalTheme } from '../../types'; type GetCombinedStylesProps = { @@ -29,7 +27,6 @@ type Variant = 'primary' | 'secondary' | 'tertiary' | 'surface'; type BaseProps = { isVariant: (variant: Variant) => boolean; theme: InternalTheme; - disabled?: boolean; }; export const getCombinedStyles = ({ @@ -165,17 +162,12 @@ export const getCombinedStyles = ({ const getBackgroundColor = ({ theme, isVariant, - disabled, customBackgroundColor, }: BaseProps & { customBackgroundColor?: ColorValue }) => { - if (customBackgroundColor && !disabled) { + if (customBackgroundColor) { return customBackgroundColor; } - if (disabled) { - return theme.colors.surfaceDisabled; - } - if (isVariant('primary')) { return theme.colors.primaryContainer; } @@ -189,7 +181,7 @@ const getBackgroundColor = ({ } if (isVariant('surface')) { - return theme.colors.elevation.level3; + return theme.colors.surfaceContainerHigh; } return theme.colors.primaryContainer; @@ -198,17 +190,12 @@ const getBackgroundColor = ({ const getForegroundColor = ({ theme, isVariant, - disabled, customColor, }: BaseProps & { customColor?: string }) => { - if (typeof customColor !== 'undefined' && !disabled) { + if (typeof customColor !== 'undefined') { return customColor; } - if (disabled) { - return theme.colors.onSurfaceDisabled; - } - if (isVariant('primary')) { return theme.colors.onPrimaryContainer; } @@ -231,13 +218,11 @@ const getForegroundColor = ({ export const getFABColors = ({ theme, variant, - disabled, customColor, customBackgroundColor, }: { theme: InternalTheme; variant: string; - disabled?: boolean; customColor?: string; customBackgroundColor?: ColorValue; }) => { @@ -245,7 +230,7 @@ export const getFABColors = ({ return variant === variantToCompare; }; - const baseFABColorProps = { theme, isVariant, disabled }; + const baseFABColorProps = { theme, isVariant }; const backgroundColor = getBackgroundColor({ ...baseFABColorProps, @@ -267,21 +252,8 @@ const getLabelColor = ({ theme }: { theme: InternalTheme }) => { return theme.colors.onSurface; }; -const getBackdropColor = ({ - theme, - customBackdropColor, -}: { - theme: InternalTheme; - customBackdropColor?: string; -}) => { - if (customBackdropColor) { - return customBackdropColor; - } - return color(theme.colors.background).alpha(0.95).rgb().string(); -}; - const getStackedFABBackgroundColor = ({ theme }: { theme: InternalTheme }) => { - return theme.colors.elevation.level3; + return theme.colors.surfaceContainerHigh; }; export const getFABGroupColors = ({ @@ -293,7 +265,8 @@ export const getFABGroupColors = ({ }) => { return { labelColor: getLabelColor({ theme }), - backdropColor: getBackdropColor({ theme, customBackdropColor }), + backdropColor: customBackdropColor ?? theme.colors.background, + backdropOpacity: customBackdropColor ? 1 : 0.95, stackedFABBackgroundColor: getStackedFABBackgroundColor({ theme }), }; }; diff --git a/src/components/HelperText/HelperText.tsx b/src/components/HelperText/HelperText.tsx index 8043968cff..6fc44d58a5 100644 --- a/src/components/HelperText/HelperText.tsx +++ b/src/components/HelperText/HelperText.tsx @@ -5,6 +5,7 @@ import { StyleProp, StyleSheet, TextStyle, + View, } from 'react-native'; import { getTextColor } from './utils'; @@ -122,36 +123,42 @@ const HelperText = ({ textHeight = e.nativeEvent.layout.height; }; - const textColor = getTextColor({ theme, disabled, type }); + const { color: textColor, opacity: textOpacity } = getTextColor({ + theme, + disabled, + type, + }); return ( - - {rest.children} - + + + {rest.children} + + ); }; diff --git a/src/components/HelperText/utils.ts b/src/components/HelperText/utils.ts index ab9d2dde8e..767cb74ef0 100644 --- a/src/components/HelperText/utils.ts +++ b/src/components/HelperText/utils.ts @@ -1,5 +1,8 @@ +import { tokens } from '../../styles/themes/v3/tokens'; import type { InternalTheme } from '../../types'; +const { stateOpacity } = tokens.md.ref; + type BaseProps = { theme: InternalTheme; disabled?: boolean; @@ -7,14 +10,19 @@ type BaseProps = { }; export function getTextColor({ theme, disabled, type }: BaseProps) { - const { colors } = theme; - if (type === 'error') { - return colors?.error; + return { color: theme.colors.error, opacity: stateOpacity.enabled }; } if (disabled) { - return theme.colors.onSurfaceDisabled; + return { + color: theme.colors.onSurfaceVariant, + opacity: stateOpacity.disabled, + }; } - return theme.colors.onSurfaceVariant; + + return { + color: theme.colors.onSurfaceVariant, + opacity: stateOpacity.enabled, + }; } diff --git a/src/components/IconButton/IconButton.tsx b/src/components/IconButton/IconButton.tsx index dbe7de4841..8cf5bff8d5 100644 --- a/src/components/IconButton/IconButton.tsx +++ b/src/components/IconButton/IconButton.tsx @@ -134,7 +134,13 @@ const IconButton = forwardRef( const IconComponent = animated ? CrossFadeIcon : Icon; - const { iconColor, backgroundColor, borderColor } = getIconButtonColor({ + const { + iconColor, + iconOpacity, + backgroundColor, + borderColor, + backgroundOpacity, + } = getIconButtonColor({ theme, disabled, selected, @@ -162,7 +168,8 @@ const IconButton = forwardRef( testID={`${testID}-container`} style={[ { - backgroundColor, + backgroundColor: + backgroundOpacity < 1 ? undefined : backgroundColor, width: buttonSize, height: buttonSize, }, @@ -173,6 +180,15 @@ const IconButton = forwardRef( container elevation={0} > + {backgroundOpacity < 1 && ( + + )} ( testID={testID} {...rest} > - {loading ? ( - - ) : ( - - )} + + {loading ? ( + + ) : ( + + )} + ); diff --git a/src/components/IconButton/utils.ts b/src/components/IconButton/utils.ts index fd985b04aa..653a272750 100644 --- a/src/components/IconButton/utils.ts +++ b/src/components/IconButton/utils.ts @@ -1,5 +1,8 @@ +import { tokens } from '../../styles/themes/v3/tokens'; import type { InternalTheme } from '../../types'; +const { stateOpacity } = tokens.md.ref; + type IconButtonMode = 'outlined' | 'contained' | 'contained-tonal'; type BaseProps = { @@ -9,20 +12,6 @@ type BaseProps = { selected?: boolean; }; -const getBorderColor = ({ - theme, - disabled, -}: { - theme: InternalTheme; - disabled?: boolean; -}) => { - if (disabled) { - return theme.colors.surfaceDisabled; - } - - return theme.colors.outline; -}; - const getBackgroundColor = ({ theme, isMode, @@ -32,7 +21,7 @@ const getBackgroundColor = ({ }: BaseProps & { customContainerColor?: string }) => { if (disabled) { if (isMode('contained') || isMode('contained-tonal')) { - return theme.colors.surfaceDisabled; + return theme.colors.onSurface; } } @@ -71,7 +60,7 @@ const getIconColor = ({ customIconColor, }: BaseProps & { customIconColor?: string }) => { if (disabled) { - return theme.colors.onSurfaceDisabled; + return theme.colors.onSurface; } if (typeof customIconColor !== 'undefined') { @@ -136,12 +125,23 @@ export const getIconButtonColor = ({ customIconColor, }); + const iconOpacity = disabled ? stateOpacity.disabled : stateOpacity.enabled; + + const backgroundColor = getBackgroundColor({ + ...baseIconColorProps, + customContainerColor, + }); + + const backgroundOpacity = + disabled && (isMode('contained') || isMode('contained-tonal')) + ? stateOpacity.disabled + : stateOpacity.enabled; + return { iconColor, - backgroundColor: getBackgroundColor({ - ...baseIconColorProps, - customContainerColor, - }), - borderColor: getBorderColor({ theme, disabled }), + iconOpacity, + backgroundColor, + borderColor: theme.colors.outlineVariant, + backgroundOpacity, }; }; diff --git a/src/components/Menu/MenuItem.tsx b/src/components/Menu/MenuItem.tsx index 725e38cd5b..ac77147031 100644 --- a/src/components/Menu/MenuItem.tsx +++ b/src/components/Menu/MenuItem.tsx @@ -145,7 +145,7 @@ const MenuItem = ({ hitSlop, }: Props) => { const theme = useInternalTheme(themeOverrides); - const { titleColor, iconColor } = getMenuItemColor({ + const { titleColor, iconColor, contentOpacity } = getMenuItemColor({ theme, disabled, }); @@ -185,7 +185,7 @@ const MenuItem = ({ accessibilityState={newAccessibilityState} hitSlop={hitSlop} > - + {leadingIcon ? ( diff --git a/src/components/Menu/utils.ts b/src/components/Menu/utils.ts index 8fc73ca082..f9e3d5d9a1 100644 --- a/src/components/Menu/utils.ts +++ b/src/components/Menu/utils.ts @@ -1,6 +1,9 @@ -import type { InternalTheme, MD3Theme } from '../../types'; +import { tokens } from '../../styles/themes/v3/tokens'; +import type { InternalTheme } from '../../types'; import type { IconSource } from '../Icon'; +const { stateOpacity } = tokens.md.ref; + export const MIN_WIDTH = 112; export const MAX_WIDTH = 280; @@ -15,32 +18,23 @@ type ColorProps = { disabled?: boolean; }; -const getDisabledColor = (theme: InternalTheme) => { - return (theme as MD3Theme).colors.onSurfaceDisabled; -}; - -const getTitleColor = ({ theme, disabled }: ColorProps) => { - const { colors } = theme as MD3Theme; - if (disabled) { - return getDisabledColor(theme); - } - - return colors.onSurface; +const getTitleColor = ({ theme }: ColorProps) => { + return theme.colors.onSurface; }; -const getIconColor = ({ theme, disabled }: ColorProps) => { - const { colors } = theme as MD3Theme; - if (disabled) { - return getDisabledColor(theme); - } - - return colors.onSurfaceVariant; +const getIconColor = ({ theme }: ColorProps) => { + return theme.colors.onSurfaceVariant; }; export const getMenuItemColor = ({ theme, disabled }: ColorProps) => { + const contentOpacity = disabled + ? stateOpacity.disabled + : stateOpacity.enabled; + return { titleColor: getTitleColor({ theme, disabled }), iconColor: getIconColor({ theme, disabled }), + contentOpacity, }; }; diff --git a/src/components/Modal.tsx b/src/components/Modal.tsx index dc55c3cf7a..21b1ffd39d 100644 --- a/src/components/Modal.tsx +++ b/src/components/Modal.tsx @@ -14,11 +14,14 @@ import useLatestCallback from 'use-latest-callback'; import Surface from './Surface'; import { useInternalTheme } from '../core/theming'; +import { tokens } from '../styles/themes/v3/tokens'; import type { ThemeProp } from '../types'; import { addEventListener } from '../utils/addEventListener'; import { BackHandler } from '../utils/BackHandler/BackHandler'; import useAnimatedValue from '../utils/useAnimatedValue'; +const { scrimAlpha } = tokens.md.ref; + export type Props = { /** * Determines whether clicking outside the modal dismisses it. @@ -201,8 +204,11 @@ function Modal({ style={[ styles.backdrop, { - backgroundColor: theme.colors?.backdrop, - opacity, + backgroundColor: theme.colors.scrim, + opacity: opacity.interpolate({ + inputRange: [0, 1], + outputRange: [0, scrimAlpha], + }), }, ]} testID={`${testID}-backdrop`} diff --git a/src/components/RadioButton/RadioButtonAndroid.tsx b/src/components/RadioButton/RadioButtonAndroid.tsx index 515efe5eff..4b68455101 100644 --- a/src/components/RadioButton/RadioButtonAndroid.tsx +++ b/src/components/RadioButton/RadioButtonAndroid.tsx @@ -110,20 +110,18 @@ const RadioButtonAndroid = ({ value, }) === 'checked'; - const { rippleColor, selectionControlColor } = - getAndroidSelectionControlColor({ - theme, - disabled, - checked, - customColor: rest.color, - customUncheckedColor: rest.uncheckedColor, - }); + const { selectionControlColor } = getAndroidSelectionControlColor({ + theme, + disabled, + checked, + customColor: rest.color, + customUncheckedColor: rest.uncheckedColor, + }); return ( ( style={[ { borderRadius: roundness }, { - backgroundColor: colors.elevation.level3, + backgroundColor: theme.colors.surfaceContainerHigh, borderRadius: roundness * (isBarMode ? 7 : 0), }, styles.container, diff --git a/src/components/SegmentedButtons/SegmentedButtonItem.tsx b/src/components/SegmentedButtons/SegmentedButtonItem.tsx index 6f04b6aeb7..c70ff68ae2 100644 --- a/src/components/SegmentedButtons/SegmentedButtonItem.tsx +++ b/src/components/SegmentedButtons/SegmentedButtonItem.tsx @@ -146,7 +146,7 @@ const SegmentedButtonItem = ({ }, [checked, checkScale, showSelectedCheck]); const { roundness } = theme; - const { borderColor, textColor, borderWidth, backgroundColor } = + const { borderColor, textColor, textOpacity, borderWidth, backgroundColor } = getSegmentedButtonColors({ checked, theme, @@ -210,7 +210,9 @@ const SegmentedButtonItem = ({ theme={theme} hitSlop={hitSlop} > - + {showCheckedIcon ? ( { const getSegmentedButtonBorderColor = ({ theme, disabled }: BaseProps) => { if (disabled) { - return theme.colors.surfaceDisabled; + return theme.colors.outlineVariant; } return theme.colors.outline; }; @@ -108,7 +111,7 @@ const getSegmentedButtonTextColor = ({ uncheckedColor, }: SegmentedButtonProps) => { if (disabled) { - return theme.colors.onSurfaceDisabled; + return theme.colors.onSurface; } if (checked) { return checkedColor ?? theme.colors.onSecondaryContainer; @@ -141,5 +144,7 @@ export const getSegmentedButtonColors = ({ }); const borderWidth = getSegmentedButtonBorderWidth({ theme }); - return { backgroundColor, borderColor, textColor, borderWidth }; + const textOpacity = disabled ? stateOpacity.disabled : stateOpacity.enabled; + + return { backgroundColor, borderColor, textColor, textOpacity, borderWidth }; }; diff --git a/src/components/Switch/utils.ts b/src/components/Switch/utils.ts index 34ffc26eb5..c0afc7c142 100644 --- a/src/components/Switch/utils.ts +++ b/src/components/Switch/utils.ts @@ -81,7 +81,7 @@ const getOnTintColor = ({ } if (value) { - return setColor(checkedColor).alpha(0.5).rgb().string(); + return theme.colors.surfaceContainerHighest; } if (theme.dark) { diff --git a/src/components/TextInput/Addons/Underline.tsx b/src/components/TextInput/Addons/Underline.tsx index 20b49233dc..22a8e419cc 100644 --- a/src/components/TextInput/Addons/Underline.tsx +++ b/src/components/TextInput/Addons/Underline.tsx @@ -14,6 +14,7 @@ type UnderlineProps = { activeColor: string; underlineColorCustom?: string; hasActiveOutline?: boolean; + disabledOpacity?: number; style?: StyleProp; theme?: ThemeProp; }; @@ -25,6 +26,7 @@ export const Underline = ({ activeColor, underlineColorCustom, hasActiveOutline, + disabledOpacity, style, theme: _themeOverrides, }: UnderlineProps) => { @@ -44,6 +46,7 @@ export const Underline = ({ styles.md3Underline, { backgroundColor, + opacity: disabledOpacity, // Underlines is thinner when input is not focused transform: [ { diff --git a/src/components/TextInput/Adornment/TextInputAffix.tsx b/src/components/TextInput/Adornment/TextInputAffix.tsx index 71a2b78475..94a0c08662 100644 --- a/src/components/TextInput/Adornment/TextInputAffix.tsx +++ b/src/components/TextInput/Adornment/TextInputAffix.tsx @@ -152,12 +152,19 @@ const TextInputAffix = ({ [side]: offset, } as ViewStyle; - const textColor = getTextColor({ theme, disabled }); + const { color: textColor, opacity: textOpacity } = getTextColor({ + theme, + disabled, + }); const content = ( diff --git a/src/components/TextInput/Adornment/TextInputIcon.tsx b/src/components/TextInput/Adornment/TextInputIcon.tsx index 0005071fe3..0fc2c7c906 100644 --- a/src/components/TextInput/Adornment/TextInputIcon.tsx +++ b/src/components/TextInput/Adornment/TextInputIcon.tsx @@ -142,7 +142,7 @@ const TextInputIcon = ({ const theme = useInternalTheme(themeOverrides); - const iconColor = getIconColor({ + const { color: iconColor, opacity: iconOpacity } = getIconColor({ theme, disabled, isTextInputFocused, @@ -150,7 +150,7 @@ const TextInputIcon = ({ }); return ( - + string | undefined) | string; }) { - if (typeof customColor === 'function') { - return customColor(isTextInputFocused); - } - if (customColor) { - return customColor; - } + const color = + typeof customColor === 'function' + ? customColor(isTextInputFocused) + : customColor ?? theme.colors.onSurfaceVariant; - if (disabled) { - return theme.colors.onSurfaceDisabled; - } + const opacity = + disabled && !customColor ? stateOpacity.disabled : stateOpacity.enabled; - return theme.colors.onSurfaceVariant; + return { color, opacity }; } diff --git a/src/components/TextInput/Label/InputLabel.tsx b/src/components/TextInput/Label/InputLabel.tsx index 4877bc236e..6fd869a1c3 100644 --- a/src/components/TextInput/Label/InputLabel.tsx +++ b/src/components/TextInput/Label/InputLabel.tsx @@ -18,7 +18,6 @@ const InputLabel = (props: InputLabelProps) => { wiggle, error, focused, - opacity, labelLayoutWidth, labelLayoutHeight, labelBackground, @@ -44,6 +43,8 @@ const InputLabel = (props: InputLabelProps) => { backgroundColor, roundness, placeholderColor, + disabledOpacity, + opacity, errorColor, labelTranslationXOffset, maxFontSizeMultiplier, @@ -139,7 +140,12 @@ const InputLabel = (props: InputLabelProps) => { // This gives the effect of animating the color, but allows us to use native driver { if (textColor) { return textColor; } - if (disabled) { - return theme.colors.onSurfaceDisabled; - } - return theme.colors.onSurface; }; const getActiveColor = ({ theme, - disabled, error, activeUnderlineColor, activeOutlineColor, @@ -340,18 +333,10 @@ const getActiveColor = ({ return modeColor; } - if (disabled) { - return theme.colors.onSurfaceDisabled; - } - return theme.colors.primary; }; -const getPlaceholderColor = ({ theme, disabled }: BaseProps) => { - if (disabled) { - return theme.colors.onSurfaceDisabled; - } - +const getPlaceholderColor = ({ theme }: BaseProps) => { return theme.colors.onSurfaceVariant; }; @@ -365,17 +350,12 @@ const getSelectionColor = ({ if (typeof customSelectionColor !== 'undefined') { return customSelectionColor; } - - if (Platform.OS === 'android') { - return color(activeColor).alpha(0.54).rgb().string(); - } - return activeColor; }; const getFlatBackgroundColor = ({ theme, disabled }: BaseProps) => { if (disabled) { - return color(theme.colors.onSurface).alpha(0.04).rgb().string(); + return theme.colors.surfaceContainerHighest; } return theme.colors.surfaceVariant; @@ -390,10 +370,6 @@ const getFlatUnderlineColor = ({ return underlineColor; } - if (disabled) { - return theme.colors.onSurfaceDisabled; - } - return theme.colors.onSurfaceVariant; }; @@ -410,8 +386,7 @@ const getOutlinedOutlineInputColor = ({ if (theme.dark) { return 'transparent'; } - - return theme.colors.surfaceDisabled; + return theme.colors.outlineVariant; } return theme.colors.outline; @@ -442,12 +417,17 @@ export const getFlatInputColors = ({ mode: 'flat', }); + const disabledOpacity = disabled + ? stateOpacity.disabled + : stateOpacity.enabled; + return { inputTextColor: getInputTextColor({ ...baseFlatColorProps, textColor, }), activeColor, + disabledOpacity, underlineColorCustom: getFlatUnderlineColor({ ...baseFlatColorProps, underlineColor, @@ -484,12 +464,17 @@ export const getOutlinedInputColors = ({ mode: 'outlined', }); + const disabledOpacity = disabled + ? stateOpacity.disabled + : stateOpacity.enabled; + return { inputTextColor: getInputTextColor({ ...baseOutlinedColorProps, textColor, }), activeColor, + disabledOpacity, outlineColor: getOutlinedOutlineInputColor({ ...baseOutlinedColorProps, customOutlineColor, diff --git a/src/components/TextInput/types.tsx b/src/components/TextInput/types.tsx index 1f710e4089..49bc46e121 100644 --- a/src/components/TextInput/types.tsx +++ b/src/components/TextInput/types.tsx @@ -115,6 +115,7 @@ export type LabelProps = { paddingRight?: number; labelTranslationXOffset?: number; placeholderColor: string | null; + disabledOpacity?: number; backgroundColor?: ColorValue; label?: TextInputLabelProp | null; hasActiveOutline?: boolean | null; diff --git a/src/components/ToggleButton/utils.ts b/src/components/ToggleButton/utils.ts index efb2857bed..e471a5b4b6 100644 --- a/src/components/ToggleButton/utils.ts +++ b/src/components/ToggleButton/utils.ts @@ -1,6 +1,3 @@ -import color from 'color'; - -import { tokens } from '../../styles/themes/v3/tokens'; import type { InternalTheme } from '../../types'; export const getToggleButtonColor = ({ @@ -11,10 +8,7 @@ export const getToggleButtonColor = ({ checked: boolean | null; }) => { if (checked) { - return color(theme.colors.onSecondaryContainer) - .alpha(tokens.md.ref.opacity.level2) - .rgb() - .string(); + return theme.colors.surfaceContainerHighest; } - return 'transparent'; + return theme.colors.surfaceContainer; }; diff --git a/src/components/TouchableRipple/utils.ts b/src/components/TouchableRipple/utils.ts index 83308eb228..10dcef6703 100644 --- a/src/components/TouchableRipple/utils.ts +++ b/src/components/TouchableRipple/utils.ts @@ -29,7 +29,7 @@ const getRippleColor = ({ return rippleColor; } - return color(theme.colors.onSurface).alpha(0.1).rgb().string(); + return theme.colors.stateLayerPressed; }; export const getTouchableRippleColors = ({ diff --git a/src/components/__tests__/Appbar/Appbar.test.tsx b/src/components/__tests__/Appbar/Appbar.test.tsx index 6c80269a0f..e1c55fa8c8 100644 --- a/src/components/__tests__/Appbar/Appbar.test.tsx +++ b/src/components/__tests__/Appbar/Appbar.test.tsx @@ -232,21 +232,6 @@ describe('AppbarAction', () => { expect(appbarActionIcon.props.color).toBe('purple'); }); - it('should be rendered with custom ripple color', () => { - const { getByTestId } = render( - - - - ); - const appbarActionContainer = getByTestId('appbar-action-container').props - .children; - expect(appbarActionContainer.props.rippleColor).toBe('purple'); - }); - it('should render AppbarBackAction with custom color', () => { const { getByTestId } = render( diff --git a/src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap b/src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap index 50ab8e3cd6..82c623d863 100644 --- a/src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap +++ b/src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap @@ -46,7 +46,7 @@ exports[`Appbar does not pass any additional props to Searchbar 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(243, 237, 247, 1)", + "backgroundColor": "rgba(236, 230, 240, 1)", "borderRadius": 28, "shadowColor": "#000", "shadowOffset": { @@ -64,7 +64,7 @@ exports[`Appbar does not pass any additional props to Searchbar 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgba(243, 237, 247, 1)", + "backgroundColor": "rgba(236, 230, 240, 1)", "borderRadius": 28, "flex": undefined, "flexDirection": "row", @@ -104,7 +104,7 @@ exports[`Appbar does not pass any additional props to Searchbar 1`] = ` style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -181,35 +181,43 @@ exports[`Appbar does not pass any additional props to Searchbar 1`] = ` } testID="search-bar-icon" > - + - magnify - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + magnify + + @@ -288,7 +296,7 @@ exports[`Appbar does not pass any additional props to Searchbar 1`] = ` style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -365,35 +373,43 @@ exports[`Appbar does not pass any additional props to Searchbar 1`] = ` } testID="search-bar-clear-icon" > - + - close - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + close + + @@ -471,7 +487,7 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -550,76 +566,84 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A > - + > + + @@ -714,7 +738,7 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -792,66 +816,74 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A > - - menu - + + menu + + diff --git a/src/components/__tests__/Button.test.tsx b/src/components/__tests__/Button.test.tsx index 3d16801c15..b47be8c53e 100644 --- a/src/components/__tests__/Button.test.tsx +++ b/src/components/__tests__/Button.test.tsx @@ -5,9 +5,12 @@ import { act, fireEvent, render } from '@testing-library/react-native'; import { getTheme } from '../../core/theming'; import { pink500, white } from '../../styles/themes/v2/colors'; +import { tokens } from '../../styles/themes/v3/tokens'; import Button from '../Button/Button'; import { getButtonColors } from '../Button/utils'; +const { stateOpacity } = tokens.md.ref; + const styles = StyleSheet.create({ flexing: { flexDirection: 'row-reverse', @@ -349,7 +352,8 @@ describe('getButtonColors - background color', () => { disabled: true, }) ).toMatchObject({ - backgroundColor: getTheme().colors.surfaceDisabled, + backgroundColor: getTheme().colors.onSurface, + backgroundOpacity: stateOpacity.pressed, }); }) ); @@ -364,7 +368,8 @@ describe('getButtonColors - background color', () => { disabled: true, }) ).toMatchObject({ - backgroundColor: getTheme(true).colors.surfaceDisabled, + backgroundColor: getTheme(true).colors.onSurface, + backgroundOpacity: stateOpacity.pressed, }); }) ); @@ -376,7 +381,7 @@ describe('getButtonColors - background color', () => { mode: 'elevated', }) ).toMatchObject({ - backgroundColor: getTheme().colors.elevation.level1, + backgroundColor: getTheme().colors.surfaceContainerLow, }); }); @@ -387,7 +392,7 @@ describe('getButtonColors - background color', () => { mode: 'elevated', }) ).toMatchObject({ - backgroundColor: getTheme(true).colors.elevation.level1, + backgroundColor: getTheme(true).colors.surfaceContainerLow, }); }); @@ -485,7 +490,8 @@ describe('getButtonColors - text color', () => { mode: 'text', }) ).toMatchObject({ - textColor: getTheme().colors.onSurfaceDisabled, + textColor: getTheme().colors.onSurface, + textOpacity: stateOpacity.disabled, }); }); @@ -498,7 +504,8 @@ describe('getButtonColors - text color', () => { mode: 'text', }) ).toMatchObject({ - textColor: getTheme(true).colors.onSurfaceDisabled, + textColor: getTheme(true).colors.onSurface, + textOpacity: stateOpacity.disabled, }); }); @@ -596,7 +603,7 @@ describe('getButtonColors - border color', () => { mode: 'outlined', }) ).toMatchObject({ - borderColor: getTheme().colors.surfaceDisabled, + borderColor: getTheme().colors.outlineVariant, }); }); @@ -608,7 +615,7 @@ describe('getButtonColors - border color', () => { mode: 'outlined', }) ).toMatchObject({ - borderColor: getTheme(true).colors.surfaceDisabled, + borderColor: getTheme(true).colors.outlineVariant, }); }); @@ -619,7 +626,7 @@ describe('getButtonColors - border color', () => { mode: 'outlined', }) ).toMatchObject({ - borderColor: getTheme().colors.outline, + borderColor: getTheme().colors.outlineVariant, }); }); @@ -630,7 +637,7 @@ describe('getButtonColors - border color', () => { mode: 'outlined', }) ).toMatchObject({ - borderColor: getTheme(true).colors.outline, + borderColor: getTheme(true).colors.outlineVariant, }); }); diff --git a/src/components/__tests__/Checkbox/__snapshots__/CheckboxItem.test.tsx.snap b/src/components/__tests__/Checkbox/__snapshots__/CheckboxItem.test.tsx.snap index 3325829520..5c416c9720 100644 --- a/src/components/__tests__/Checkbox/__snapshots__/CheckboxItem.test.tsx.snap +++ b/src/components/__tests__/Checkbox/__snapshots__/CheckboxItem.test.tsx.snap @@ -165,6 +165,7 @@ exports[`can render leading checkbox control 1`] = ` }, { "color": "rgba(29, 27, 32, 1)", + "opacity": 1, "textAlign": "right", }, undefined, @@ -262,6 +263,7 @@ exports[`can render the Android checkbox on different platforms 1`] = ` }, { "color": "rgba(29, 27, 32, 1)", + "opacity": 1, "textAlign": "left", }, undefined, @@ -323,6 +325,7 @@ exports[`can render the Android checkbox on different platforms 1`] = ` collapsable={false} style={ { + "opacity": 1, "transform": [ { "scale": 1, @@ -478,6 +481,7 @@ exports[`can render the iOS checkbox on different platforms 1`] = ` }, { "color": "rgba(29, 27, 32, 1)", + "opacity": 1, "textAlign": "left", }, undefined, @@ -658,6 +662,7 @@ exports[`renders unchecked 1`] = ` }, { "color": "rgba(29, 27, 32, 1)", + "opacity": 1, "textAlign": "left", }, undefined, diff --git a/src/components/__tests__/Checkbox/utils.test.tsx b/src/components/__tests__/Checkbox/utils.test.tsx index 3e551140c5..799a343768 100644 --- a/src/components/__tests__/Checkbox/utils.test.tsx +++ b/src/components/__tests__/Checkbox/utils.test.tsx @@ -1,50 +1,10 @@ -import color from 'color'; - import { getTheme } from '../../../core/theming'; +import { tokens } from '../../../styles/themes/v3/tokens'; import { getAndroidSelectionControlColor, getSelectionControlIOSColor, } from '../../Checkbox/utils'; - -describe('getAndroidSelectionControlColor - ripple color', () => { - it('should return correct disabled color, for theme version 3', () => { - expect( - getAndroidSelectionControlColor({ - theme: getTheme(), - disabled: true, - checked: false, - }) - ).toMatchObject({ - rippleColor: color(getTheme().colors.onSurface) - .alpha(0.16) - .rgb() - .string(), - }); - }); - - it('should return custom color', () => { - expect( - getAndroidSelectionControlColor({ - theme: getTheme(), - customColor: 'purple', - checked: false, - }) - ).toMatchObject({ - rippleColor: color('purple').fade(0.32).rgb().string(), - }); - }); - - it('should return theme color, for theme version 3', () => { - expect( - getAndroidSelectionControlColor({ - theme: getTheme(), - checked: false, - }) - ).toMatchObject({ - rippleColor: color(getTheme().colors.primary).fade(0.32).rgb().string(), - }); - }); -}); +const { stateOpacity } = tokens.md.ref; describe('getAndroidSelectionControlColor - checkbox color', () => { it('should return correct disabled color, for theme version 3', () => { @@ -55,7 +15,8 @@ describe('getAndroidSelectionControlColor - checkbox color', () => { checked: false, }) ).toMatchObject({ - selectionControlColor: getTheme().colors.onSurfaceDisabled, + selectionControlColor: getTheme().colors.onSurface, + selectionControlOpacity: stateOpacity.disabled, }); }); @@ -104,41 +65,26 @@ describe('getAndroidSelectionControlColor - checkbox color', () => { selectionControlColor: getTheme().colors.onSurfaceVariant, }); }); -}); - -describe('getSelectionControlIOSColor - ripple color', () => { - it('should return correct disabled color, for theme version 3', () => { - expect( - getSelectionControlIOSColor({ - theme: getTheme(), - disabled: true, - }) - ).toMatchObject({ - rippleColor: color(getTheme().colors.onSurface) - .alpha(0.16) - .rgb() - .string(), - }); - }); - it('should return custom color', () => { + it('should return theme color, unchecked, dark mode', () => { expect( - getSelectionControlIOSColor({ - theme: getTheme(), - customColor: 'purple', + getAndroidSelectionControlColor({ + theme: getTheme(true), + checked: false, }) ).toMatchObject({ - rippleColor: color('purple').fade(0.32).rgb().string(), + selectionControlColor: getTheme(true).colors.onSurfaceVariant, }); }); - it('should return theme color, for theme version 3', () => { + it('should return theme color, unchecked, light mode', () => { expect( - getSelectionControlIOSColor({ - theme: getTheme(), + getAndroidSelectionControlColor({ + theme: getTheme(false), + checked: false, }) ).toMatchObject({ - rippleColor: color(getTheme().colors.primary).fade(0.32).rgb().string(), + selectionControlColor: getTheme(false).colors.onSurfaceVariant, }); }); }); @@ -151,7 +97,8 @@ describe('getSelectionControlIOSColor - checked color', () => { disabled: true, }) ).toMatchObject({ - checkedColor: getTheme().colors.onSurfaceDisabled, + checkedColor: getTheme().colors.primary, + checkedColorOpacity: stateOpacity.disabled, }); }); diff --git a/src/components/__tests__/Chip.test.tsx b/src/components/__tests__/Chip.test.tsx index 5505a3726e..76044715b2 100644 --- a/src/components/__tests__/Chip.test.tsx +++ b/src/components/__tests__/Chip.test.tsx @@ -5,9 +5,12 @@ import { act, render } from '@testing-library/react-native'; import color from 'color'; import { getTheme } from '../../core/theming'; +import { tokens } from '../../styles/themes/v3/tokens'; import Chip from '../Chip/Chip'; import { getChipColors } from '../Chip/helpers'; +const { stateOpacity } = tokens.md.ref; + it('renders chip with onPress', () => { const tree = render( {}}>Example Chip).toJSON(); @@ -99,7 +102,8 @@ describe('getChipColors - text color', () => { isOutlined: false, }) ).toMatchObject({ - textColor: getTheme().colors.onSurfaceDisabled, + textColor: getTheme().colors.onSurface, + contentOpacity: stateOpacity.disabled, }); }); @@ -147,7 +151,8 @@ describe('getChipColors - icon color', () => { isOutlined: false, }) ).toMatchObject({ - iconColor: getTheme().colors.onSurfaceDisabled, + iconColor: getTheme().colors.onSurface, + contentOpacity: stateOpacity.disabled, }); }); @@ -187,7 +192,7 @@ describe('getChipColors - icon color', () => { }); describe('getChipColor - selected background color', () => { - it('should return custom color, for theme version 3, outlined mode', () => { + it('should return custom color, outlined mode', () => { expect( getChipColors({ theme: getTheme(), @@ -195,14 +200,11 @@ describe('getChipColor - selected background color', () => { isOutlined: true, }) ).toMatchObject({ - selectedBackgroundColor: color('purple') - .mix(color(getTheme().colors.onSurfaceVariant), 0) - .rgb() - .string(), + selectedBackgroundColor: 'purple', }); }); - it('should return custom color, for theme version 3, flat mode', () => { + it('should return custom color, flat mode', () => { expect( getChipColors({ theme: getTheme(), @@ -210,42 +212,32 @@ describe('getChipColor - selected background color', () => { isOutlined: false, }) ).toMatchObject({ - selectedBackgroundColor: color('purple') - .mix(color(getTheme().colors.onSecondaryContainer), 0) - .rgb() - .string(), + selectedBackgroundColor: 'purple', }); }); - it('should return custom color, for theme version 3, outlined mode, show selected overlay', () => { + it('should return theme color, for theme version 3, flat mode', () => { expect( getChipColors({ theme: getTheme(), - customBackgroundColor: 'purple', - showSelectedOverlay: true, - isOutlined: true, + isOutlined: false, }) ).toMatchObject({ - selectedBackgroundColor: color('purple') - .mix(color(getTheme().colors.onSurfaceVariant), 0.12) - .rgb() - .string(), + selectedBackgroundColor: getTheme().colors.secondaryContainer, }); }); +}); - it('should return custom color, for theme version 3, flat mode, show selected overlay', () => { +describe('getChipColor - background color', () => { + it('should return custom color', () => { expect( getChipColors({ theme: getTheme(), customBackgroundColor: 'purple', - showSelectedOverlay: true, isOutlined: false, }) ).toMatchObject({ - selectedBackgroundColor: color('purple') - .mix(color(getTheme().colors.onSecondaryContainer), 0.12) - .rgb() - .string(), + backgroundColor: 'purple', }); }); @@ -256,10 +248,7 @@ describe('getChipColor - selected background color', () => { isOutlined: true, }) ).toMatchObject({ - selectedBackgroundColor: color(getTheme().colors.surface) - .mix(color(getTheme().colors.onSurfaceVariant), 0) - .rgb() - .string(), + backgroundColor: getTheme().colors.surface, }); }); @@ -270,56 +259,64 @@ describe('getChipColor - selected background color', () => { isOutlined: false, }) ).toMatchObject({ - selectedBackgroundColor: color(getTheme().colors.secondaryContainer) - .mix(color(getTheme().colors.onSecondaryContainer), 0) - .rgb() - .string(), + backgroundColor: getTheme().colors.secondaryContainer, }); }); }); -describe('getChipColor - background color', () => { - it('should return custom color', () => { +describe('getChipColor - border color', () => { + it('should return correct disabled color, for theme version 3', () => { expect( getChipColors({ theme: getTheme(), - customBackgroundColor: 'purple', + disabled: true, isOutlined: false, }) ).toMatchObject({ - backgroundColor: 'purple', + borderColor: 'transparent', }); }); - it('should return theme color, for theme version 3, outlined mode', () => { + it('should return custom color, for theme version 3', () => { expect( getChipColors({ theme: getTheme(), - isOutlined: true, + selectedColor: 'purple', + isOutlined: false, }) ).toMatchObject({ - backgroundColor: getTheme().colors.surface, + borderColor: 'transparent', }); }); - it('should return theme color, for theme version 3, flat mode', () => { + it('should return theme color, for theme version 3', () => { expect( getChipColors({ theme: getTheme(), isOutlined: false, }) ).toMatchObject({ - backgroundColor: getTheme().colors.secondaryContainer, + borderColor: 'transparent', }); }); -}); -describe('getChipColor - border color', () => { - it('should return correct disabled color, for theme version 3', () => { + it('should return custom color, outlined mode', () => { expect( getChipColors({ - theme: getTheme(), - disabled: true, + theme: getTheme(false), + selectedColor: 'purple', + isOutlined: true, + }) + ).toMatchObject({ + borderColor: color('purple').alpha(0.29).rgb().string(), + }); + }); + + it('should return custom color, flat mode', () => { + expect( + getChipColors({ + theme: getTheme(true), + customBackgroundColor: 'purple', isOutlined: false, }) ).toMatchObject({ @@ -327,11 +324,32 @@ describe('getChipColor - border color', () => { }); }); - it('should return custom color, for theme version 3', () => { + it('should return theme color, light mode, outlined mode', () => { expect( getChipColors({ - theme: getTheme(), - selectedColor: 'purple', + theme: getTheme(false), + isOutlined: true, + }) + ).toMatchObject({ + borderColor: getTheme(false).colors.outlineVariant, + }); + }); + + it('should return theme color, dark mode, outlined mode', () => { + expect( + getChipColors({ + theme: getTheme(true), + isOutlined: true, + }) + ).toMatchObject({ + borderColor: getTheme(true).colors.outlineVariant, + }); + }); + + it('should return theme background color, light mode, flat mode', () => { + expect( + getChipColors({ + theme: getTheme(false), isOutlined: false, }) ).toMatchObject({ @@ -339,10 +357,10 @@ describe('getChipColor - border color', () => { }); }); - it('should return theme color, for theme version 3', () => { + it('should return theme background color, dark mode, flat mode', () => { expect( getChipColors({ - theme: getTheme(), + theme: getTheme(true), isOutlined: false, }) ).toMatchObject({ diff --git a/src/components/__tests__/FAB.test.tsx b/src/components/__tests__/FAB.test.tsx index 74f636cf5c..9fc9c12e98 100644 --- a/src/components/__tests__/FAB.test.tsx +++ b/src/components/__tests__/FAB.test.tsx @@ -91,12 +91,6 @@ it('renders loading FAB with custom size prop', () => { expect(tree).toMatchSnapshot(); }); -it('renders disabled FAB', () => { - const tree = render( {}} icon="plus" disabled />).toJSON(); - - expect(tree).toMatchSnapshot(); -}); - it('renders custom color for the icon and label of the FAB', () => { const tree = render( {}} icon="plus" color="#AA0114" /> @@ -196,19 +190,7 @@ describe('getFABColors - background color', () => { }); }); - it('should return correct disabled color, for theme version 3', () => { - expect( - getFABColors({ - theme: getTheme(), - disabled: true, - variant: 'primary', - }) - ).toMatchObject({ - backgroundColor: getTheme().colors.surfaceDisabled, - }); - }); - - it('should return correct theme color, for theme version 3, primary variant', () => { + it('should return correct theme color, primary variant', () => { expect( getFABColors({ theme: getTheme(), @@ -248,7 +230,7 @@ describe('getFABColors - background color', () => { variant: 'surface', }) ).toMatchObject({ - backgroundColor: getTheme().colors.elevation.level3, + backgroundColor: getTheme().colors.surfaceContainerHigh, }); }); }); @@ -266,19 +248,7 @@ describe('getFABColors - foreground color', () => { }); }); - it('should return correct disabled color, for theme version 3', () => { - expect( - getFABColors({ - theme: getTheme(), - variant: 'primary', - disabled: true, - }) - ).toMatchObject({ - foregroundColor: getTheme().colors.onSurfaceDisabled, - }); - }); - - it('should return correct theme color, for theme version 3, primary variant', () => { + it('should return correct theme color, primary variant', () => { expect( getFABColors({ theme: getTheme(), diff --git a/src/components/__tests__/FABGroup.test.tsx b/src/components/__tests__/FABGroup.test.tsx index 7009526e42..5f25e46c6f 100644 --- a/src/components/__tests__/FABGroup.test.tsx +++ b/src/components/__tests__/FABGroup.test.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import { Animated } from 'react-native'; import { act, fireEvent, render } from '@testing-library/react-native'; -import color from 'color'; import { getTheme } from '../../core/theming'; import FAB from '../FAB'; @@ -26,10 +25,30 @@ describe('getFABGroupColors - backdrop color', () => { theme: getTheme(), }) ).toMatchObject({ - backdropColor: color(getTheme().colors.background) - .alpha(0.95) - .rgb() - .string(), + backdropColor: getTheme().colors.background, + }); + }); +}); + +describe('getFABGroupColors - backdrop opacity', () => { + it('should return scrimAlpha when no custom backdrop color', () => { + expect( + getFABGroupColors({ + theme: getTheme(), + }) + ).toMatchObject({ + backdropOpacity: 0.95, + }); + }); + + it('should return 1 when custom backdrop color is provided', () => { + expect( + getFABGroupColors({ + theme: getTheme(), + customBackdropColor: 'transparent', + }) + ).toMatchObject({ + backdropOpacity: 1, }); }); }); @@ -53,7 +72,7 @@ describe('getFABGroupColors - stacked FAB background color', () => { theme: getTheme(), }) ).toMatchObject({ - stackedFABBackgroundColor: getTheme().colors.elevation.level3, + stackedFABBackgroundColor: getTheme().colors.surfaceContainerHigh, }); }); }); diff --git a/src/components/__tests__/IconButton.test.tsx b/src/components/__tests__/IconButton.test.tsx index 39d1eb8663..fdd3316850 100644 --- a/src/components/__tests__/IconButton.test.tsx +++ b/src/components/__tests__/IconButton.test.tsx @@ -5,9 +5,12 @@ import { act, render } from '@testing-library/react-native'; import { getTheme } from '../../core/theming'; import { pink500 } from '../../styles/themes/v2/colors'; +import { tokens } from '../../styles/themes/v3/tokens'; import IconButton from '../IconButton/IconButton'; import { getIconButtonColor } from '../IconButton/utils'; +const { stateOpacity } = tokens.md.ref; + const styles = StyleSheet.create({ square: { borderRadius: 0, @@ -96,7 +99,8 @@ describe('getIconButtonColor - icon color', () => { disabled: true, }) ).toMatchObject({ - iconColor: getTheme().colors.onSurfaceDisabled, + iconColor: getTheme().colors.onSurface, + iconOpacity: stateOpacity.disabled, }); }); @@ -211,7 +215,10 @@ describe('getIconButtonColor - background color', () => { mode, disabled: true, }) - ).toMatchObject({ backgroundColor: getTheme().colors.surfaceDisabled }); + ).toMatchObject({ + backgroundColor: getTheme().colors.onSurface, + backgroundOpacity: stateOpacity.disabled, + }); }) ); @@ -292,7 +299,7 @@ describe('getIconButtonColor - border color', () => { disabled: true, }) ).toMatchObject({ - borderColor: getTheme().colors.surfaceDisabled, + borderColor: getTheme().colors.outlineVariant, }); }); @@ -302,7 +309,7 @@ describe('getIconButtonColor - border color', () => { theme: getTheme(), }) ).toMatchObject({ - borderColor: getTheme().colors.outline, + borderColor: getTheme().colors.outlineVariant, }); }); }); diff --git a/src/components/__tests__/MenuItem.test.tsx b/src/components/__tests__/MenuItem.test.tsx index 10fb008b5e..dead127da1 100644 --- a/src/components/__tests__/MenuItem.test.tsx +++ b/src/components/__tests__/MenuItem.test.tsx @@ -3,9 +3,12 @@ import * as React from 'react'; import { render } from '@testing-library/react-native'; import { getTheme } from '../../core/theming'; +import { tokens } from '../../styles/themes/v3/tokens'; import Menu from '../Menu/Menu'; import { getMenuItemColor } from '../Menu/utils'; +const { stateOpacity } = tokens.md.ref; + describe('Menu Item', () => { it('renders menu item', () => { const tree = render( @@ -70,7 +73,10 @@ describe('getMenuItemColor - title color', () => { theme: getTheme(), disabled: true, }) - ).toMatchObject({ titleColor: getTheme().colors.onSurfaceDisabled }); + ).toMatchObject({ + titleColor: getTheme().colors.onSurface, + contentOpacity: stateOpacity.disabled, + }); }); it('should return correct theme color, for theme version 3', () => { @@ -91,7 +97,10 @@ describe('getMenuItemColor - icon color', () => { theme: getTheme(), disabled: true, }) - ).toMatchObject({ iconColor: getTheme().colors.onSurfaceDisabled }); + ).toMatchObject({ + iconColor: getTheme().colors.onSurfaceVariant, + contentOpacity: stateOpacity.disabled, + }); }); it('should return correct theme color, for theme version 3', () => { diff --git a/src/components/__tests__/Modal.test.tsx b/src/components/__tests__/Modal.test.tsx index 32161d5b84..d040cc62de 100644 --- a/src/components/__tests__/Modal.test.tsx +++ b/src/components/__tests__/Modal.test.tsx @@ -9,8 +9,11 @@ import { import { act, fireEvent, render } from '@testing-library/react-native'; import { MD3LightTheme } from '../../styles/themes'; +import { tokens } from '../../styles/themes/v3/tokens'; import Modal from '../Modal'; +const { scrimAlpha } = tokens.md.ref; + jest.mock('react-native-safe-area-context', () => ({ useSafeAreaInsets: () => ({ bottom: 44, left: 0, right: 0, top: 37 }), })); @@ -55,7 +58,7 @@ describe('Modal', () => { ); expect(getByTestId('modal-backdrop')).toHaveStyle({ - backgroundColor: MD3LightTheme.colors.backdrop, + backgroundColor: MD3LightTheme.colors.scrim, }); }); @@ -66,7 +69,7 @@ describe('Modal', () => { testID="modal" theme={{ colors: { - backdrop: 'transparent', + scrim: 'transparent', }, }} > @@ -119,7 +122,7 @@ describe('Modal', () => { }); expect(getByTestId('modal-backdrop')).toHaveStyle({ - opacity: 1, + opacity: scrimAlpha, }); expect(getByTestId('modal-surface-outer-layer')).toHaveStyle({ @@ -156,7 +159,7 @@ describe('Modal', () => { }); expect(getByTestId('modal-backdrop')).toHaveStyle({ - opacity: 1, + opacity: scrimAlpha, }); expect(getByTestId('modal-surface-outer-layer')).toHaveStyle({ @@ -198,7 +201,7 @@ describe('Modal', () => { }); expect(getByTestId('modal-backdrop')).toHaveStyle({ - opacity: 1, + opacity: scrimAlpha, }); expect(getByTestId('modal-surface-outer-layer')).toHaveStyle({ @@ -241,7 +244,7 @@ describe('Modal', () => { }); expect(getByTestId('modal-backdrop')).toHaveStyle({ - opacity: 1, + opacity: scrimAlpha, }); expect(getByTestId('modal-surface-outer-layer')).toHaveStyle({ @@ -308,7 +311,7 @@ describe('Modal', () => { }); expect(getByTestId('modal-backdrop')).toHaveStyle({ - opacity: 1, + opacity: scrimAlpha, }); expect(getByTestId('modal-surface-outer-layer')).toHaveStyle({ @@ -376,7 +379,7 @@ describe('Modal', () => { }); expect(getByTestId('modal-backdrop')).toHaveStyle({ - opacity: 1, + opacity: scrimAlpha, }); expect(getByTestId('modal-surface-outer-layer')).toHaveStyle({ opacity: 1, @@ -393,7 +396,7 @@ describe('Modal', () => { ); expect(getByTestId('modal-backdrop')).toHaveStyle({ - opacity: 1, + opacity: scrimAlpha, }); expect(getByTestId('modal-surface-outer-layer')).toHaveStyle({ opacity: 1, @@ -406,7 +409,7 @@ describe('Modal', () => { ); expect(getByTestId('modal-backdrop')).toHaveStyle({ - opacity: 1, + opacity: scrimAlpha, }); expect(getByTestId('modal-surface-outer-layer')).toHaveStyle({ opacity: 1, @@ -453,7 +456,7 @@ describe('Modal', () => { ); expect(getByTestId('modal-backdrop')).toHaveStyle({ - opacity: 1, + opacity: scrimAlpha, }); expect(getByTestId('modal-surface-outer-layer')).toHaveStyle({ opacity: 1, @@ -466,7 +469,7 @@ describe('Modal', () => { ); expect(getByTestId('modal-backdrop')).toHaveStyle({ - opacity: 1, + opacity: scrimAlpha, }); expect(getByTestId('modal-surface-outer-layer')).toHaveStyle({ opacity: 1, @@ -491,7 +494,7 @@ describe('Modal', () => { ); expect(getByTestId('modal-backdrop')).toHaveStyle({ - opacity: 1, + opacity: scrimAlpha, }); expect(getByTestId('modal-surface-outer-layer')).toHaveStyle({ opacity: 1, @@ -504,7 +507,7 @@ describe('Modal', () => { ); expect(getByTestId('modal-backdrop')).toHaveStyle({ - opacity: 1, + opacity: scrimAlpha, }); expect(getByTestId('modal-surface-outer-layer')).toHaveStyle({ opacity: 1, @@ -527,7 +530,7 @@ describe('Modal', () => { }); expect(getByTestId('modal-backdrop')).toHaveStyle({ - opacity: 1, + opacity: scrimAlpha, }); expect(getByTestId('modal-surface-outer-layer')).toHaveStyle({ opacity: 1, diff --git a/src/components/__tests__/RadioButton/__snapshots__/RadioButtonItem.test.tsx.snap b/src/components/__tests__/RadioButton/__snapshots__/RadioButtonItem.test.tsx.snap index de667249ae..f44e395c55 100644 --- a/src/components/__tests__/RadioButton/__snapshots__/RadioButtonItem.test.tsx.snap +++ b/src/components/__tests__/RadioButton/__snapshots__/RadioButtonItem.test.tsx.snap @@ -163,6 +163,7 @@ exports[`can render leading radio button control 1`] = ` }, { "color": "rgba(29, 27, 32, 1)", + "opacity": 1, "textAlign": "right", }, undefined, @@ -257,6 +258,7 @@ exports[`can render the Android radio button on different platforms 1`] = ` }, { "color": "rgba(29, 27, 32, 1)", + "opacity": 1, "textAlign": "left", }, undefined, @@ -408,6 +410,7 @@ exports[`can render the iOS radio button on different platforms 1`] = ` }, { "color": "rgba(29, 27, 32, 1)", + "opacity": 1, "textAlign": "left", }, undefined, @@ -585,6 +588,7 @@ exports[`renders unchecked 1`] = ` }, { "color": "rgba(29, 27, 32, 1)", + "opacity": 1, "textAlign": "left", }, undefined, diff --git a/src/components/__tests__/SegmentedButton.test.tsx b/src/components/__tests__/SegmentedButton.test.tsx index e65f9015f7..e04f4791c8 100644 --- a/src/components/__tests__/SegmentedButton.test.tsx +++ b/src/components/__tests__/SegmentedButton.test.tsx @@ -3,12 +3,15 @@ import * as React from 'react'; import { render } from '@testing-library/react-native'; import { getTheme } from '../../core/theming'; +import { tokens } from '../../styles/themes/v3/tokens'; import SegmentedButtons from '../SegmentedButtons/SegmentedButtons'; import { getDisabledSegmentedButtonStyle, getSegmentedButtonColors, } from '../SegmentedButtons/utils'; +const { stateOpacity } = tokens.md.ref; + it('renders segmented button', () => { const tree = render( { theme | disabled | checked | checkedColor | uncheckedColor | expected ${getTheme()} | ${false} | ${true} | ${undefined} | ${undefined} | ${getTheme().colors.onSecondaryContainer} ${getTheme()} | ${false} | ${false} | ${undefined} | ${undefined} | ${getTheme().colors.onSurface} - ${getTheme()} | ${true} | ${true} | ${undefined} | ${undefined} | ${getTheme().colors.onSurfaceDisabled} - ${getTheme()} | ${true} | ${false} | ${undefined} | ${undefined} | ${getTheme().colors.onSurfaceDisabled} + ${getTheme()} | ${true} | ${true} | ${undefined} | ${undefined} | ${getTheme().colors.onSurface} + ${getTheme()} | ${true} | ${false} | ${undefined} | ${undefined} | ${getTheme().colors.onSurface} ${getTheme()} | ${false} | ${true} | ${'a125f5'} | ${undefined} | ${'a125f5'} ${getTheme()} | ${false} | ${false} | ${undefined} | ${'000'} | ${'000'} ${getTheme()} | ${false} | ${false} | ${'a125f5'} | ${'000'} | ${'000'} @@ -121,7 +124,7 @@ describe('getSegmentedButtonColors', () => { checked: false, }) ).toMatchObject({ - borderColor: getTheme().colors.surfaceDisabled, + borderColor: getTheme().colors.outlineVariant, }); }); @@ -145,7 +148,8 @@ describe('getSegmentedButtonColors', () => { checked: false, }) ).toMatchObject({ - textColor: getTheme().colors.onSurfaceDisabled, + textColor: getTheme().colors.onSurface, + textOpacity: stateOpacity.disabled, }); }); }); diff --git a/src/components/__tests__/Surface.test.tsx b/src/components/__tests__/Surface.test.tsx index 8d8e639779..045a63a3e6 100644 --- a/src/components/__tests__/Surface.test.tsx +++ b/src/components/__tests__/Surface.test.tsx @@ -65,7 +65,7 @@ describe('Surface', () => { shadowRadius: 12, }); expect(getByTestId('surface-test')).toHaveStyle({ - backgroundColor: getTheme().colors.elevation.level5, + backgroundColor: getTheme().colors.surfaceContainerHighest, }); }); @@ -256,7 +256,7 @@ describe('Surface', () => { expect(getByTestId(testID)).not.toHaveStyle({ elevation: 5 }); expect(getByTestId(testID)).toHaveStyle({ - backgroundColor: getTheme().colors.elevation.level5, + backgroundColor: getTheme().colors.surfaceContainerHighest, }); }); }); diff --git a/src/components/__tests__/Switch.test.tsx b/src/components/__tests__/Switch.test.tsx index dfaa028b43..ee7a82a15d 100644 --- a/src/components/__tests__/Switch.test.tsx +++ b/src/components/__tests__/Switch.test.tsx @@ -198,7 +198,7 @@ describe('getSwitchColor - on tint color', () => { color: 'purple', }) ).toMatchObject({ - onTintColor: color('purple').alpha(0.5).rgb().string(), + checkedColor: 'purple', }); }); diff --git a/src/components/__tests__/TextInput.test.tsx b/src/components/__tests__/TextInput.test.tsx index c92ed138c4..2fbebb326f 100644 --- a/src/components/__tests__/TextInput.test.tsx +++ b/src/components/__tests__/TextInput.test.tsx @@ -3,16 +3,18 @@ import * as React from 'react'; import { I18nManager, Platform, StyleSheet, Text, View } from 'react-native'; import { fireEvent, render } from '@testing-library/react-native'; -import color from 'color'; import { DefaultTheme, getTheme, ThemeProvider } from '../../core/theming'; import { red500 } from '../../styles/themes/v2/colors'; +import { tokens } from '../../styles/themes/v3/tokens'; import { getFlatInputColors, getOutlinedInputColors, } from '../TextInput/helpers'; import TextInput, { Props } from '../TextInput/TextInput'; +const { stateOpacity } = tokens.md.ref; + const style = StyleSheet.create({ inputStyle: { color: red500, @@ -547,7 +549,7 @@ describe('getFlatInputColor - underline color', () => { theme: getTheme(), }) ).toMatchObject({ - underlineColorCustom: getTheme().colors.onSurfaceDisabled, + underlineColorCustom: getTheme().colors.onSurfaceVariant, }); }); @@ -610,7 +612,8 @@ describe('getFlatInputColor - input text color', () => { theme: getTheme(), }) ).toMatchObject({ - inputTextColor: getTheme().colors.onSurfaceDisabled, + inputTextColor: getTheme().colors.onSurface, + disabledOpacity: stateOpacity.disabled, }); }); @@ -626,18 +629,19 @@ describe('getFlatInputColor - input text color', () => { }); describe('getFlatInputColor - placeholder color', () => { - it('should return correct disabled color, for theme version 3', () => { + it('should return correct disabled color', () => { expect( getFlatInputColors({ disabled: true, theme: getTheme(), }) ).toMatchObject({ - placeholderColor: getTheme().colors.onSurfaceDisabled, + placeholderColor: getTheme().colors.onSurfaceVariant, + disabledOpacity: stateOpacity.disabled, }); }); - it('should return correct theme color, for theme version 3', () => { + it('should return correct theme color', () => { expect( getFlatInputColors({ theme: getTheme(), @@ -656,10 +660,7 @@ describe('getFlatInputColor - background color', () => { theme: getTheme(), }) ).toMatchObject({ - backgroundColor: color(getTheme().colors.onSurface) - .alpha(0.04) - .rgb() - .string(), + backgroundColor: getTheme().colors.surfaceContainerHighest, }); expect( getFlatInputColors({ @@ -667,10 +668,7 @@ describe('getFlatInputColor - background color', () => { theme: getTheme(true), }) ).toMatchObject({ - backgroundColor: color(getTheme(true).colors.onSurface) - .alpha(0.04) - .rgb() - .string(), + backgroundColor: getTheme(true).colors.surfaceContainerHighest, }); }); @@ -715,7 +713,8 @@ describe('getFlatInputColor - active color', () => { theme: getTheme(), }) ).toMatchObject({ - activeColor: getTheme().colors.onSurfaceDisabled, + activeColor: getTheme().colors.primary, + disabledOpacity: stateOpacity.disabled, }); }); @@ -778,7 +777,7 @@ describe('getOutlinedInputColors - outline color', () => { theme: getTheme(), }) ).toMatchObject({ - outlineColor: getTheme().colors.surfaceDisabled, + outlineColor: getTheme().colors.outlineVariant, }); }); @@ -832,7 +831,8 @@ describe('getOutlinedInputColors - input text color', () => { theme: getTheme(), }) ).toMatchObject({ - inputTextColor: getTheme().colors.onSurfaceDisabled, + inputTextColor: getTheme().colors.onSurface, + disabledOpacity: stateOpacity.disabled, }); }); @@ -855,7 +855,8 @@ describe('getOutlinedInputColors - placeholder color', () => { theme: getTheme(), }) ).toMatchObject({ - placeholderColor: getTheme().colors.onSurfaceDisabled, + placeholderColor: getTheme().colors.onSurfaceVariant, + disabledOpacity: stateOpacity.disabled, }); }); @@ -900,7 +901,8 @@ describe('getOutlinedInputColors - active color', () => { theme: getTheme(), }) ).toMatchObject({ - activeColor: getTheme().colors.onSurfaceDisabled, + activeColor: getTheme().colors.primary, + disabledOpacity: stateOpacity.disabled, }); }); diff --git a/src/components/__tests__/ToggleButton.test.tsx b/src/components/__tests__/ToggleButton.test.tsx index 61936f4909..a830558681 100644 --- a/src/components/__tests__/ToggleButton.test.tsx +++ b/src/components/__tests__/ToggleButton.test.tsx @@ -2,10 +2,8 @@ import * as React from 'react'; import { Animated } from 'react-native'; import { act, render } from '@testing-library/react-native'; -import color from 'color'; import { getTheme } from '../../core/theming'; -import { tokens } from '../../styles/themes/v3/tokens'; import ToggleButton from '../ToggleButton'; import { getToggleButtonColor } from '../ToggleButton/utils'; @@ -36,25 +34,19 @@ it('renders unchecked toggle button', () => { describe('getToggleButtonColor', () => { it('should return correct color when checked and theme version 3', () => { expect(getToggleButtonColor({ theme: getTheme(), checked: true })).toBe( - color(getTheme().colors.onSecondaryContainer) - .alpha(tokens.md.ref.opacity.level2) - .rgb() - .string() + getTheme().colors.surfaceContainerHighest ); }); it('should return correct color when checked and theme version 3, dark theme', () => { expect(getToggleButtonColor({ theme: getTheme(true), checked: true })).toBe( - color(getTheme(true).colors.onSecondaryContainer) - .alpha(tokens.md.ref.opacity.level2) - .rgb() - .string() + getTheme(true).colors.surfaceContainerHighest ); }); - it('should return transparent color when not checked', () => { + it('should return correct color when not checked', () => { expect(getToggleButtonColor({ theme: getTheme(), checked: false })).toBe( - 'transparent' + getTheme().colors.surfaceContainer ); }); }); diff --git a/src/components/__tests__/__snapshots__/Banner.test.tsx.snap b/src/components/__tests__/__snapshots__/Banner.test.tsx.snap index 0a61a1a3de..6be6a1afa3 100644 --- a/src/components/__tests__/__snapshots__/Banner.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Banner.test.tsx.snap @@ -5,7 +5,7 @@ exports[`render visible banner, with custom theme 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(255, 255, 255, 1)", + "backgroundColor": "rgba(247, 242, 250, 1)", "opacity": 1, "shadowColor": "#000", "shadowOffset": { @@ -22,7 +22,7 @@ exports[`render visible banner, with custom theme 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(255, 255, 255, 1)", + "backgroundColor": "rgba(247, 242, 250, 1)", "flex": undefined, "shadowColor": "#000", "shadowOffset": { @@ -208,6 +208,9 @@ exports[`render visible banner, with custom theme 1`] = ` "flexDirection": "row", "justifyContent": "center", }, + { + "opacity": 1, + }, undefined, ] } @@ -278,7 +281,7 @@ exports[`renders hidden banner, without action buttons and without image 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(255, 255, 255, 1)", + "backgroundColor": "rgba(247, 242, 250, 1)", "opacity": 0, "shadowColor": "#000", "shadowOffset": { @@ -295,7 +298,7 @@ exports[`renders hidden banner, without action buttons and without image 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(255, 255, 255, 1)", + "backgroundColor": "rgba(247, 242, 250, 1)", "flex": undefined, "shadowColor": "#000", "shadowOffset": { @@ -413,7 +416,7 @@ exports[`renders visible banner, with action buttons and with image 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(255, 255, 255, 1)", + "backgroundColor": "rgba(247, 242, 250, 1)", "opacity": 1, "shadowColor": "#000", "shadowOffset": { @@ -430,7 +433,7 @@ exports[`renders visible banner, with action buttons and with image 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(255, 255, 255, 1)", + "backgroundColor": "rgba(247, 242, 250, 1)", "flex": undefined, "shadowColor": "#000", "shadowOffset": { @@ -638,6 +641,9 @@ exports[`renders visible banner, with action buttons and with image 1`] = ` "flexDirection": "row", "justifyContent": "center", }, + { + "opacity": 1, + }, undefined, ] } @@ -708,7 +714,7 @@ exports[`renders visible banner, with action buttons and without image 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(255, 255, 255, 1)", + "backgroundColor": "rgba(247, 242, 250, 1)", "opacity": 1, "shadowColor": "#000", "shadowOffset": { @@ -725,7 +731,7 @@ exports[`renders visible banner, with action buttons and without image 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(255, 255, 255, 1)", + "backgroundColor": "rgba(247, 242, 250, 1)", "flex": undefined, "shadowColor": "#000", "shadowOffset": { @@ -911,6 +917,9 @@ exports[`renders visible banner, with action buttons and without image 1`] = ` "flexDirection": "row", "justifyContent": "center", }, + { + "opacity": 1, + }, undefined, ] } @@ -1060,6 +1069,9 @@ exports[`renders visible banner, with action buttons and without image 1`] = ` "flexDirection": "row", "justifyContent": "center", }, + { + "opacity": 1, + }, undefined, ] } @@ -1130,7 +1142,7 @@ exports[`renders visible banner, without action buttons and with image 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(255, 255, 255, 1)", + "backgroundColor": "rgba(247, 242, 250, 1)", "opacity": 1, "shadowColor": "#000", "shadowOffset": { @@ -1147,7 +1159,7 @@ exports[`renders visible banner, without action buttons and with image 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(255, 255, 255, 1)", + "backgroundColor": "rgba(247, 242, 250, 1)", "flex": undefined, "shadowColor": "#000", "shadowOffset": { @@ -1275,7 +1287,7 @@ exports[`renders visible banner, without action buttons and without image 1`] = collapsable={false} style={ { - "backgroundColor": "rgba(255, 255, 255, 1)", + "backgroundColor": "rgba(247, 242, 250, 1)", "opacity": 1, "shadowColor": "#000", "shadowOffset": { @@ -1292,7 +1304,7 @@ exports[`renders visible banner, without action buttons and without image 1`] = collapsable={false} style={ { - "backgroundColor": "rgba(255, 255, 255, 1)", + "backgroundColor": "rgba(247, 242, 250, 1)", "flex": undefined, "shadowColor": "#000", "shadowOffset": { diff --git a/src/components/__tests__/__snapshots__/BottomNavigation.test.tsx.snap b/src/components/__tests__/__snapshots__/BottomNavigation.test.tsx.snap index 6bc02934ba..587006fa3d 100644 --- a/src/components/__tests__/__snapshots__/BottomNavigation.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/BottomNavigation.test.tsx.snap @@ -113,7 +113,7 @@ exports[`allows customizing Route's type via generics 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgba(247, 242, 250, 1)", + "backgroundColor": "rgba(243, 237, 247, 1)", "overflow": "hidden", } } @@ -780,7 +780,7 @@ exports[`hides labels in non-shifting bottom navigation 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgba(247, 242, 250, 1)", + "backgroundColor": "rgba(243, 237, 247, 1)", "overflow": "hidden", } } @@ -1521,7 +1521,7 @@ exports[`hides labels in shifting bottom navigation 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgba(247, 242, 250, 1)", + "backgroundColor": "rgba(243, 237, 247, 1)", "overflow": "hidden", } } @@ -2394,7 +2394,7 @@ exports[`renders bottom navigation with getLazy 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgba(247, 242, 250, 1)", + "backgroundColor": "rgba(243, 237, 247, 1)", "overflow": "hidden", } } @@ -4123,7 +4123,7 @@ exports[`renders bottom navigation with scene animation 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgba(247, 242, 250, 1)", + "backgroundColor": "rgba(243, 237, 247, 1)", "overflow": "hidden", } } @@ -5597,7 +5597,7 @@ exports[`renders custom icon and label in non-shifting bottom navigation 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgba(247, 242, 250, 1)", + "backgroundColor": "rgba(243, 237, 247, 1)", "overflow": "hidden", } } @@ -6299,7 +6299,7 @@ exports[`renders custom icon and label in shifting bottom navigation 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgba(247, 242, 250, 1)", + "backgroundColor": "rgba(243, 237, 247, 1)", "overflow": "hidden", } } @@ -7293,7 +7293,7 @@ exports[`renders custom icon and label with custom colors in non-shifting bottom style={ { "alignItems": "center", - "backgroundColor": "rgba(247, 242, 250, 1)", + "backgroundColor": "rgba(243, 237, 247, 1)", "overflow": "hidden", } } @@ -8394,7 +8394,7 @@ exports[`renders custom icon and label with custom colors in shifting bottom nav style={ { "alignItems": "center", - "backgroundColor": "rgba(247, 242, 250, 1)", + "backgroundColor": "rgba(243, 237, 247, 1)", "overflow": "hidden", } } @@ -9342,7 +9342,7 @@ exports[`renders non-shifting bottom navigation 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgba(247, 242, 250, 1)", + "backgroundColor": "rgba(243, 237, 247, 1)", "overflow": "hidden", } } @@ -10443,7 +10443,7 @@ exports[`renders shifting bottom navigation 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgba(247, 242, 250, 1)", + "backgroundColor": "rgba(243, 237, 247, 1)", "overflow": "hidden", } } diff --git a/src/components/__tests__/__snapshots__/Button.test.tsx.snap b/src/components/__tests__/__snapshots__/Button.test.tsx.snap index fddcd2bc10..6c34864a74 100644 --- a/src/components/__tests__/__snapshots__/Button.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Button.test.tsx.snap @@ -92,6 +92,9 @@ exports[`renders button with an accessibility hint 1`] = ` "flexDirection": "row", "justifyContent": "center", }, + { + "opacity": 1, + }, undefined, ] } @@ -242,6 +245,9 @@ exports[`renders button with an accessibility label 1`] = ` "flexDirection": "row", "justifyContent": "center", }, + { + "opacity": 1, + }, undefined, ] } @@ -391,6 +397,9 @@ exports[`renders button with button color 1`] = ` "flexDirection": "row", "justifyContent": "center", }, + { + "opacity": 1, + }, undefined, ] } @@ -540,6 +549,9 @@ exports[`renders button with color 1`] = ` "flexDirection": "row", "justifyContent": "center", }, + { + "opacity": 1, + }, undefined, ] } @@ -689,6 +701,9 @@ exports[`renders button with custom testID 1`] = ` "flexDirection": "row", "justifyContent": "center", }, + { + "opacity": 1, + }, undefined, ] } @@ -838,6 +853,9 @@ exports[`renders button with icon 1`] = ` "flexDirection": "row", "justifyContent": "center", }, + { + "opacity": 1, + }, undefined, ] } @@ -1036,6 +1054,9 @@ exports[`renders button with icon in reverse order 1`] = ` "flexDirection": "row", "justifyContent": "center", }, + { + "opacity": 1, + }, { "flexDirection": "row-reverse", }, @@ -1236,6 +1257,9 @@ exports[`renders contained contained with mode 1`] = ` "flexDirection": "row", "justifyContent": "center", }, + { + "opacity": 1, + }, undefined, ] } @@ -1386,6 +1410,9 @@ exports[`renders disabled button 1`] = ` "flexDirection": "row", "justifyContent": "center", }, + { + "opacity": 0.38, + }, undefined, ] } @@ -1422,7 +1449,7 @@ exports[`renders disabled button 1`] = ` undefined, false, { - "color": "rgba(29, 27, 32, 0.38)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 14, "fontWeight": "500", @@ -1535,6 +1562,9 @@ exports[`renders loading button 1`] = ` "flexDirection": "row", "justifyContent": "center", }, + { + "opacity": 1, + }, undefined, ] } @@ -1824,7 +1854,7 @@ exports[`renders outlined button with mode 1`] = ` style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderStyle": "solid", "borderWidth": 1, @@ -1892,6 +1922,9 @@ exports[`renders outlined button with mode 1`] = ` "flexDirection": "row", "justifyContent": "center", }, + { + "opacity": 1, + }, undefined, ] } @@ -2042,6 +2075,9 @@ exports[`renders text button by default 1`] = ` "flexDirection": "row", "justifyContent": "center", }, + { + "opacity": 1, + }, undefined, ] } @@ -2191,6 +2227,9 @@ exports[`renders text button with mode 1`] = ` "flexDirection": "row", "justifyContent": "center", }, + { + "opacity": 1, + }, undefined, ] } diff --git a/src/components/__tests__/__snapshots__/Chip.test.tsx.snap b/src/components/__tests__/__snapshots__/Chip.test.tsx.snap index f6d6b1379f..4c6358aa1d 100644 --- a/src/components/__tests__/__snapshots__/Chip.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Chip.test.tsx.snap @@ -100,6 +100,9 @@ exports[`renders chip with close button 1`] = ` { "paddingLeft": 0, }, + { + "opacity": 1, + }, { "paddingRight": 34, }, @@ -395,6 +398,9 @@ exports[`renders chip with custom close button 1`] = ` { "paddingLeft": 0, }, + { + "opacity": 1, + }, { "paddingRight": 34, }, @@ -690,6 +696,9 @@ exports[`renders chip with icon 1`] = ` { "paddingLeft": 0, }, + { + "opacity": 1, + }, { "paddingRight": 0, }, @@ -892,6 +901,9 @@ exports[`renders chip with onPress 1`] = ` { "paddingLeft": 0, }, + { + "opacity": 1, + }, { "paddingRight": 0, }, @@ -972,7 +984,7 @@ exports[`renders outlined disabled chip 1`] = ` style={ { "backgroundColor": "transparent", - "borderColor": "rgba(73, 69, 79, 0.12)", + "borderColor": "rgba(243, 237, 247, 1)", "borderRadius": 8, "borderStyle": "solid", "borderWidth": 1, @@ -1049,6 +1061,9 @@ exports[`renders outlined disabled chip 1`] = ` { "paddingLeft": 0, }, + { + "opacity": 0.38, + }, { "paddingRight": 0, }, @@ -1081,7 +1096,7 @@ exports[`renders outlined disabled chip 1`] = ` "textAlignVertical": "center", }, { - "color": "rgba(29, 27, 32, 0.38)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 14, "fontWeight": "500", @@ -1111,7 +1126,7 @@ exports[`renders selected chip 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgb(232, 222, 248)", + "backgroundColor": "rgba(232, 222, 248, 1)", "borderRadius": 8, "shadowColor": "#000", "shadowOffset": { @@ -1128,7 +1143,7 @@ exports[`renders selected chip 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgb(232, 222, 248)", + "backgroundColor": "rgba(232, 222, 248, 1)", "borderColor": "transparent", "borderRadius": 8, "borderStyle": "solid", @@ -1206,6 +1221,9 @@ exports[`renders selected chip 1`] = ` { "paddingLeft": 0, }, + { + "opacity": 1, + }, { "paddingRight": 0, }, diff --git a/src/components/__tests__/__snapshots__/DataTable.test.tsx.snap b/src/components/__tests__/__snapshots__/DataTable.test.tsx.snap index 7fde640799..f6071c245c 100644 --- a/src/components/__tests__/__snapshots__/DataTable.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/DataTable.test.tsx.snap @@ -233,7 +233,7 @@ exports[`DataTable.Header renders data table header 1`] = ` }, {}, { - "color": "rgba(29, 27, 32, 0.6)", + "color": "rgba(73, 69, 79, 1)", }, undefined, ], @@ -314,7 +314,7 @@ exports[`DataTable.Header renders data table header 1`] = ` }, {}, { - "color": "rgba(29, 27, 32, 0.6)", + "color": "rgba(73, 69, 79, 1)", }, undefined, ], @@ -366,7 +366,7 @@ exports[`DataTable.Pagination renders data table pagination 1`] = ` "marginRight": 16, }, { - "color": "rgba(29, 27, 32, 0.6)", + "color": "rgba(73, 69, 79, 1)", }, ], ] @@ -404,7 +404,7 @@ exports[`DataTable.Pagination renders data table pagination 1`] = ` style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -481,35 +481,43 @@ exports[`DataTable.Pagination renders data table pagination 1`] = ` } testID="icon-button" > - + - chevron-left - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + chevron-left + + @@ -538,7 +546,7 @@ exports[`DataTable.Pagination renders data table pagination 1`] = ` style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -615,35 +623,43 @@ exports[`DataTable.Pagination renders data table pagination 1`] = ` } testID="icon-button" > - + - chevron-right - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + chevron-right + + @@ -690,7 +706,7 @@ exports[`DataTable.Pagination renders data table pagination with fast-forward bu "marginRight": 16, }, { - "color": "rgba(29, 27, 32, 0.6)", + "color": "rgba(73, 69, 79, 1)", }, ], ] @@ -730,7 +746,7 @@ exports[`DataTable.Pagination renders data table pagination with fast-forward bu style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -807,35 +823,43 @@ exports[`DataTable.Pagination renders data table pagination with fast-forward bu } testID="icon-button" > - + - page-first - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + page-first + + @@ -864,7 +888,7 @@ exports[`DataTable.Pagination renders data table pagination with fast-forward bu style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -941,35 +965,43 @@ exports[`DataTable.Pagination renders data table pagination with fast-forward bu } testID="icon-button" > - + - chevron-left - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + chevron-left + + @@ -998,7 +1030,7 @@ exports[`DataTable.Pagination renders data table pagination with fast-forward bu style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -1075,35 +1107,43 @@ exports[`DataTable.Pagination renders data table pagination with fast-forward bu } testID="icon-button" > - + - chevron-right - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + chevron-right + + @@ -1132,7 +1172,7 @@ exports[`DataTable.Pagination renders data table pagination with fast-forward bu style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -1209,35 +1249,43 @@ exports[`DataTable.Pagination renders data table pagination with fast-forward bu } testID="icon-button" > - + - page-last - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + page-last + + @@ -1284,7 +1332,7 @@ exports[`DataTable.Pagination renders data table pagination with label 1`] = ` "marginRight": 16, }, { - "color": "rgba(29, 27, 32, 0.6)", + "color": "rgba(73, 69, 79, 1)", }, ], ] @@ -1324,7 +1372,7 @@ exports[`DataTable.Pagination renders data table pagination with label 1`] = ` style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -1401,35 +1449,43 @@ exports[`DataTable.Pagination renders data table pagination with label 1`] = ` } testID="icon-button" > - + - chevron-left - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + chevron-left + + @@ -1458,7 +1514,7 @@ exports[`DataTable.Pagination renders data table pagination with label 1`] = ` style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -1535,35 +1591,43 @@ exports[`DataTable.Pagination renders data table pagination with label 1`] = ` } testID="icon-button" > - + - chevron-right - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + chevron-right + + @@ -1620,7 +1684,7 @@ exports[`DataTable.Pagination renders data table pagination with options select "marginRight": 16, }, { - "color": "rgba(29, 27, 32, 0.6)", + "color": "rgba(73, 69, 79, 1)", }, ], ] @@ -1654,7 +1718,7 @@ exports[`DataTable.Pagination renders data table pagination with options select style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderStyle": "solid", "borderWidth": 1, @@ -1723,6 +1787,9 @@ exports[`DataTable.Pagination renders data table pagination with options select "flexDirection": "row", "justifyContent": "center", }, + { + "opacity": 1, + }, { "flexDirection": "row-reverse", }, @@ -1853,7 +1920,7 @@ exports[`DataTable.Pagination renders data table pagination with options select "marginRight": 16, }, { - "color": "rgba(29, 27, 32, 0.6)", + "color": "rgba(73, 69, 79, 1)", }, ], ] @@ -1893,7 +1960,7 @@ exports[`DataTable.Pagination renders data table pagination with options select style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -1970,35 +2037,43 @@ exports[`DataTable.Pagination renders data table pagination with options select } testID="icon-button" > - + - page-first - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + page-first + + @@ -2027,7 +2102,7 @@ exports[`DataTable.Pagination renders data table pagination with options select style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -2104,35 +2179,43 @@ exports[`DataTable.Pagination renders data table pagination with options select } testID="icon-button" > - + - chevron-left - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + chevron-left + + @@ -2161,7 +2244,7 @@ exports[`DataTable.Pagination renders data table pagination with options select style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -2238,35 +2321,43 @@ exports[`DataTable.Pagination renders data table pagination with options select } testID="icon-button" > - + - chevron-right - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + chevron-right + + @@ -2295,7 +2386,7 @@ exports[`DataTable.Pagination renders data table pagination with options select style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -2372,35 +2463,43 @@ exports[`DataTable.Pagination renders data table pagination with options select } testID="icon-button" > - + - page-last - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + page-last + + @@ -2738,7 +2837,7 @@ exports[`DataTable.Title renders right aligned data table title 1`] = ` }, {}, { - "color": "rgba(29, 27, 32, 0.6)", + "color": "rgba(73, 69, 79, 1)", }, undefined, ], diff --git a/src/components/__tests__/__snapshots__/FAB.test.tsx.snap b/src/components/__tests__/__snapshots__/FAB.test.tsx.snap index 3eb29a581a..7dbef02469 100644 --- a/src/components/__tests__/__snapshots__/FAB.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/FAB.test.tsx.snap @@ -522,180 +522,6 @@ exports[`renders default FAB 1`] = ` `; -exports[`renders disabled FAB 1`] = ` - - - - - - - - plus - - - - - - - -`; - exports[`renders extended FAB 1`] = ` - + - camera - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + camera + + @@ -167,7 +175,7 @@ exports[`renders icon button by default 1`] = ` style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -243,35 +251,43 @@ exports[`renders icon button by default 1`] = ` } testID="icon-button" > - + - camera - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + camera + + @@ -303,7 +319,7 @@ exports[`renders icon button with color 1`] = ` style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -379,35 +395,43 @@ exports[`renders icon button with color 1`] = ` } testID="icon-button" > - + - camera - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + camera + + @@ -439,7 +463,7 @@ exports[`renders icon button with size 1`] = ` style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 23, "borderWidth": 0, "elevation": 0, @@ -515,35 +539,43 @@ exports[`renders icon button with size 1`] = ` } testID="icon-button" > - + - camera - + [ + { + "lineHeight": 30, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + camera + + @@ -575,7 +607,7 @@ exports[`renders icon change animated 1`] = ` style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -653,66 +685,74 @@ exports[`renders icon change animated 1`] = ` > - - camera - + + camera + + diff --git a/src/components/__tests__/__snapshots__/ListItem.test.tsx.snap b/src/components/__tests__/__snapshots__/ListItem.test.tsx.snap index 2ae673d6d3..d194b59877 100644 --- a/src/components/__tests__/__snapshots__/ListItem.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/ListItem.test.tsx.snap @@ -216,6 +216,9 @@ exports[`renders list item with custom description 1`] = ` { "paddingLeft": 0, }, + { + "opacity": 1, + }, { "paddingRight": 0, }, diff --git a/src/components/__tests__/__snapshots__/ListSection.test.tsx.snap b/src/components/__tests__/__snapshots__/ListSection.test.tsx.snap index fa4dd4024d..bb71edde3b 100644 --- a/src/components/__tests__/__snapshots__/ListSection.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/ListSection.test.tsx.snap @@ -16,13 +16,12 @@ exports[`renders list section with custom title style 1`] = ` "scale": 1, }, "colors": { - "backdrop": "rgba(50, 47, 55, 0.4)", "background": "rgba(254, 247, 255, 1)", "elevation": { "level0": "transparent", - "level1": "rgba(255, 255, 255, 1)", - "level2": "rgba(247, 242, 250, 1)", - "level3": "rgba(243, 237, 247, 1)", + "level1": "rgba(247, 242, 250, 1)", + "level2": "rgba(243, 237, 247, 1)", + "level3": "rgba(236, 230, 240, 1)", "level4": "rgba(236, 230, 240, 1)", "level5": "rgba(230, 224, 233, 1)", }, @@ -43,7 +42,6 @@ exports[`renders list section with custom title style 1`] = ` "onSecondaryFixed": "rgba(29, 25, 43, 1)", "onSecondaryFixedVariant": "rgba(74, 68, 88, 1)", "onSurface": "rgba(29, 27, 32, 1)", - "onSurfaceDisabled": "rgba(29, 27, 32, 0.38)", "onSurfaceVariant": "rgba(73, 69, 79, 1)", "onTertiary": "rgba(255, 255, 255, 1)", "onTertiaryContainer": "rgba(49, 17, 29, 1)", @@ -61,6 +59,7 @@ exports[`renders list section with custom title style 1`] = ` "secondaryFixed": "rgba(232, 222, 248, 1)", "secondaryFixedDim": "rgba(204, 194, 220, 1)", "shadow": "rgba(0, 0, 0, 1)", + "stateLayerPressed": "rgba(29, 27, 32, 0.1)", "surface": "rgba(254, 247, 255, 1)", "surfaceBright": "rgba(254, 247, 255, 1)", "surfaceContainer": "rgba(243, 237, 247, 1)", @@ -69,7 +68,6 @@ exports[`renders list section with custom title style 1`] = ` "surfaceContainerLow": "rgba(247, 242, 250, 1)", "surfaceContainerLowest": "rgba(255, 255, 255, 1)", "surfaceDim": "rgba(222, 216, 225, 1)", - "surfaceDisabled": "rgba(29, 27, 32, 0.12)", "surfaceVariant": "rgba(231, 224, 236, 1)", "tertiary": "rgba(125, 82, 96, 1)", "tertiaryContainer": "rgba(255, 216, 228, 1)", @@ -562,13 +560,12 @@ exports[`renders list section with subheader 1`] = ` "scale": 1, }, "colors": { - "backdrop": "rgba(50, 47, 55, 0.4)", "background": "rgba(254, 247, 255, 1)", "elevation": { "level0": "transparent", - "level1": "rgba(255, 255, 255, 1)", - "level2": "rgba(247, 242, 250, 1)", - "level3": "rgba(243, 237, 247, 1)", + "level1": "rgba(247, 242, 250, 1)", + "level2": "rgba(243, 237, 247, 1)", + "level3": "rgba(236, 230, 240, 1)", "level4": "rgba(236, 230, 240, 1)", "level5": "rgba(230, 224, 233, 1)", }, @@ -589,7 +586,6 @@ exports[`renders list section with subheader 1`] = ` "onSecondaryFixed": "rgba(29, 25, 43, 1)", "onSecondaryFixedVariant": "rgba(74, 68, 88, 1)", "onSurface": "rgba(29, 27, 32, 1)", - "onSurfaceDisabled": "rgba(29, 27, 32, 0.38)", "onSurfaceVariant": "rgba(73, 69, 79, 1)", "onTertiary": "rgba(255, 255, 255, 1)", "onTertiaryContainer": "rgba(49, 17, 29, 1)", @@ -607,6 +603,7 @@ exports[`renders list section with subheader 1`] = ` "secondaryFixed": "rgba(232, 222, 248, 1)", "secondaryFixedDim": "rgba(204, 194, 220, 1)", "shadow": "rgba(0, 0, 0, 1)", + "stateLayerPressed": "rgba(29, 27, 32, 0.1)", "surface": "rgba(254, 247, 255, 1)", "surfaceBright": "rgba(254, 247, 255, 1)", "surfaceContainer": "rgba(243, 237, 247, 1)", @@ -615,7 +612,6 @@ exports[`renders list section with subheader 1`] = ` "surfaceContainerLow": "rgba(247, 242, 250, 1)", "surfaceContainerLowest": "rgba(255, 255, 255, 1)", "surfaceDim": "rgba(222, 216, 225, 1)", - "surfaceDisabled": "rgba(29, 27, 32, 0.12)", "surfaceVariant": "rgba(231, 224, 236, 1)", "tertiary": "rgba(125, 82, 96, 1)", "tertiaryContainer": "rgba(255, 216, 228, 1)", @@ -1106,13 +1102,12 @@ exports[`renders list section without subheader 1`] = ` "scale": 1, }, "colors": { - "backdrop": "rgba(50, 47, 55, 0.4)", "background": "rgba(254, 247, 255, 1)", "elevation": { "level0": "transparent", - "level1": "rgba(255, 255, 255, 1)", - "level2": "rgba(247, 242, 250, 1)", - "level3": "rgba(243, 237, 247, 1)", + "level1": "rgba(247, 242, 250, 1)", + "level2": "rgba(243, 237, 247, 1)", + "level3": "rgba(236, 230, 240, 1)", "level4": "rgba(236, 230, 240, 1)", "level5": "rgba(230, 224, 233, 1)", }, @@ -1133,7 +1128,6 @@ exports[`renders list section without subheader 1`] = ` "onSecondaryFixed": "rgba(29, 25, 43, 1)", "onSecondaryFixedVariant": "rgba(74, 68, 88, 1)", "onSurface": "rgba(29, 27, 32, 1)", - "onSurfaceDisabled": "rgba(29, 27, 32, 0.38)", "onSurfaceVariant": "rgba(73, 69, 79, 1)", "onTertiary": "rgba(255, 255, 255, 1)", "onTertiaryContainer": "rgba(49, 17, 29, 1)", @@ -1151,6 +1145,7 @@ exports[`renders list section without subheader 1`] = ` "secondaryFixed": "rgba(232, 222, 248, 1)", "secondaryFixedDim": "rgba(204, 194, 220, 1)", "shadow": "rgba(0, 0, 0, 1)", + "stateLayerPressed": "rgba(29, 27, 32, 0.1)", "surface": "rgba(254, 247, 255, 1)", "surfaceBright": "rgba(254, 247, 255, 1)", "surfaceContainer": "rgba(243, 237, 247, 1)", @@ -1159,7 +1154,6 @@ exports[`renders list section without subheader 1`] = ` "surfaceContainerLow": "rgba(247, 242, 250, 1)", "surfaceContainerLowest": "rgba(255, 255, 255, 1)", "surfaceDim": "rgba(222, 216, 225, 1)", - "surfaceDisabled": "rgba(29, 27, 32, 0.12)", "surfaceVariant": "rgba(231, 224, 236, 1)", "tertiary": "rgba(125, 82, 96, 1)", "tertiaryContainer": "rgba(255, 216, 228, 1)", diff --git a/src/components/__tests__/__snapshots__/Menu.test.tsx.snap b/src/components/__tests__/__snapshots__/Menu.test.tsx.snap index d3a7c1b1a1..2a09d12a10 100644 --- a/src/components/__tests__/__snapshots__/Menu.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Menu.test.tsx.snap @@ -36,7 +36,7 @@ exports[`renders menu with content styles 1`] = ` style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderStyle": "solid", "borderWidth": 1, @@ -104,6 +104,9 @@ exports[`renders menu with content styles 1`] = ` "flexDirection": "row", "justifyContent": "center", }, + { + "opacity": 1, + }, undefined, ] } @@ -259,7 +262,7 @@ exports[`renders menu with content styles 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(247, 242, 250, 1)", + "backgroundColor": "rgba(243, 237, 247, 1)", "borderRadius": 4, "borderTopLeftRadius": 0, "borderTopRightRadius": 0, @@ -288,7 +291,7 @@ exports[`renders menu with content styles 1`] = ` pointerEvents="box-none" style={ { - "backgroundColor": "rgba(247, 242, 250, 1)", + "backgroundColor": "rgba(243, 237, 247, 1)", "borderRadius": 4, "borderTopLeftRadius": 0, "borderTopRightRadius": 0, @@ -362,6 +365,9 @@ exports[`renders menu with content styles 1`] = ` { "flexDirection": "row", }, + { + "opacity": 1, + }, undefined, ] } @@ -483,6 +489,9 @@ exports[`renders menu with content styles 1`] = ` { "flexDirection": "row", }, + { + "opacity": 1, + }, undefined, ] } @@ -590,7 +599,7 @@ exports[`renders not visible menu 1`] = ` style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderStyle": "solid", "borderWidth": 1, @@ -658,6 +667,9 @@ exports[`renders not visible menu 1`] = ` "flexDirection": "row", "justifyContent": "center", }, + { + "opacity": 1, + }, undefined, ] } @@ -755,7 +767,7 @@ exports[`renders visible menu 1`] = ` style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderStyle": "solid", "borderWidth": 1, @@ -823,6 +835,9 @@ exports[`renders visible menu 1`] = ` "flexDirection": "row", "justifyContent": "center", }, + { + "opacity": 1, + }, undefined, ] } @@ -978,7 +993,7 @@ exports[`renders visible menu 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(247, 242, 250, 1)", + "backgroundColor": "rgba(243, 237, 247, 1)", "borderRadius": 4, "opacity": 0, "shadowColor": "#000", @@ -1005,7 +1020,7 @@ exports[`renders visible menu 1`] = ` pointerEvents="box-none" style={ { - "backgroundColor": "rgba(247, 242, 250, 1)", + "backgroundColor": "rgba(243, 237, 247, 1)", "borderRadius": 4, "flex": undefined, "paddingVertical": 8, @@ -1077,6 +1092,9 @@ exports[`renders visible menu 1`] = ` { "flexDirection": "row", }, + { + "opacity": 1, + }, undefined, ] } @@ -1198,6 +1216,9 @@ exports[`renders visible menu 1`] = ` { "flexDirection": "row", }, + { + "opacity": 1, + }, undefined, ] } diff --git a/src/components/__tests__/__snapshots__/MenuItem.test.tsx.snap b/src/components/__tests__/__snapshots__/MenuItem.test.tsx.snap index 069b8c854d..e879443bf9 100644 --- a/src/components/__tests__/__snapshots__/MenuItem.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/MenuItem.test.tsx.snap @@ -59,6 +59,9 @@ exports[`Menu Item renders menu item 1`] = ` { "flexDirection": "row", }, + { + "opacity": 1, + }, undefined, ] } @@ -220,6 +223,9 @@ exports[`Menu Item renders menu item 1`] = ` { "flexDirection": "row", }, + { + "opacity": 1, + }, undefined, ] } @@ -381,6 +387,9 @@ exports[`Menu Item renders menu item 1`] = ` { "flexDirection": "row", }, + { + "opacity": 0.38, + }, undefined, ] } @@ -403,7 +412,7 @@ exports[`Menu Item renders menu item 1`] = ` style={ [ { - "color": "rgba(29, 27, 32, 0.38)", + "color": "rgba(73, 69, 79, 1)", "fontSize": 24, }, [ @@ -466,7 +475,7 @@ exports[`Menu Item renders menu item 1`] = ` }, [ { - "color": "rgba(29, 27, 32, 0.38)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 16, "fontWeight": "400", @@ -542,6 +551,9 @@ exports[`Menu Item renders menu item 1`] = ` { "flexDirection": "row", }, + { + "opacity": 0.38, + }, undefined, ] } @@ -564,7 +576,7 @@ exports[`Menu Item renders menu item 1`] = ` style={ [ { - "color": "rgba(29, 27, 32, 0.38)", + "color": "rgba(73, 69, 79, 1)", "fontSize": 24, }, [ @@ -627,7 +639,7 @@ exports[`Menu Item renders menu item 1`] = ` }, [ { - "color": "rgba(29, 27, 32, 0.38)", + "color": "rgba(29, 27, 32, 1)", "fontFamily": "System", "fontSize": 16, "fontWeight": "400", @@ -703,6 +715,9 @@ exports[`Menu Item renders menu item 1`] = ` { "flexDirection": "row", }, + { + "opacity": 1, + }, undefined, ] } diff --git a/src/components/__tests__/__snapshots__/Searchbar.test.tsx.snap b/src/components/__tests__/__snapshots__/Searchbar.test.tsx.snap index bbf1c420f7..1954a404ef 100644 --- a/src/components/__tests__/__snapshots__/Searchbar.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Searchbar.test.tsx.snap @@ -5,7 +5,7 @@ exports[`activity indicator snapshot test 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(243, 237, 247, 1)", + "backgroundColor": "rgba(236, 230, 240, 1)", "borderRadius": 28, "shadowColor": "#000", "shadowOffset": { @@ -23,7 +23,7 @@ exports[`activity indicator snapshot test 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgba(243, 237, 247, 1)", + "backgroundColor": "rgba(236, 230, 240, 1)", "borderRadius": 28, "flex": undefined, "flexDirection": "row", @@ -63,7 +63,7 @@ exports[`activity indicator snapshot test 1`] = ` style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -140,35 +140,43 @@ exports[`activity indicator snapshot test 1`] = ` } testID="search-bar-icon" > - + - magnify - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + magnify + + @@ -415,7 +423,7 @@ exports[`renders with placeholder 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(243, 237, 247, 1)", + "backgroundColor": "rgba(236, 230, 240, 1)", "borderRadius": 28, "shadowColor": "#000", "shadowOffset": { @@ -433,7 +441,7 @@ exports[`renders with placeholder 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgba(243, 237, 247, 1)", + "backgroundColor": "rgba(236, 230, 240, 1)", "borderRadius": 28, "flex": undefined, "flexDirection": "row", @@ -473,7 +481,7 @@ exports[`renders with placeholder 1`] = ` style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -550,35 +558,43 @@ exports[`renders with placeholder 1`] = ` } testID="search-bar-icon" > - + - magnify - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + magnify + + @@ -657,7 +673,7 @@ exports[`renders with placeholder 1`] = ` style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -734,35 +750,43 @@ exports[`renders with placeholder 1`] = ` } testID="search-bar-clear-icon" > - + - close - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + close + + @@ -776,7 +800,7 @@ exports[`renders with text 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(243, 237, 247, 1)", + "backgroundColor": "rgba(236, 230, 240, 1)", "borderRadius": 28, "shadowColor": "#000", "shadowOffset": { @@ -794,7 +818,7 @@ exports[`renders with text 1`] = ` style={ { "alignItems": "center", - "backgroundColor": "rgba(243, 237, 247, 1)", + "backgroundColor": "rgba(236, 230, 240, 1)", "borderRadius": 28, "flex": undefined, "flexDirection": "row", @@ -834,7 +858,7 @@ exports[`renders with text 1`] = ` style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -911,35 +935,43 @@ exports[`renders with text 1`] = ` } testID="search-bar-icon" > - + - magnify - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + magnify + + @@ -1014,7 +1046,7 @@ exports[`renders with text 1`] = ` style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -1091,35 +1123,43 @@ exports[`renders with text 1`] = ` } testID="search-bar-clear-icon" > - + - close - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + close + + diff --git a/src/components/__tests__/__snapshots__/SegmentedButton.test.tsx.snap b/src/components/__tests__/__snapshots__/SegmentedButton.test.tsx.snap index 914c9d8c8a..895061bb52 100644 --- a/src/components/__tests__/__snapshots__/SegmentedButton.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/SegmentedButton.test.tsx.snap @@ -91,6 +91,7 @@ exports[`renders segmented button 1`] = ` "paddingVertical": 9, }, { + "opacity": 1, "paddingVertical": 9, }, ] @@ -216,6 +217,7 @@ exports[`renders segmented button 1`] = ` "paddingVertical": 9, }, { + "opacity": 1, "paddingVertical": 9, }, ] diff --git a/src/components/__tests__/__snapshots__/Snackbar.test.tsx.snap b/src/components/__tests__/__snapshots__/Snackbar.test.tsx.snap index 401868fabf..ce2a9c8637 100644 --- a/src/components/__tests__/__snapshots__/Snackbar.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Snackbar.test.tsx.snap @@ -410,6 +410,9 @@ exports[`renders snackbar with action button 1`] = ` "flexDirection": "row", "justifyContent": "center", }, + { + "opacity": 1, + }, undefined, ] } diff --git a/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap b/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap index 090fdaec66..0a7334fa12 100644 --- a/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap @@ -21,6 +21,7 @@ exports[`call onPress when affix adornment pressed 1`] = ` "bottom": 0, "height": 1, "left": 0, + "opacity": 1, "position": "absolute", "right": 0, "transform": [ @@ -65,6 +66,9 @@ exports[`call onPress when affix adornment pressed 1`] = ` { "zIndex": 3, }, + { + "opacity": 1, + }, ] } > @@ -206,6 +210,7 @@ exports[`call onPress when affix adornment pressed 1`] = ` "letterSpacing": 0.15, "lineHeight": undefined, "minWidth": 65, + "opacity": 1, "paddingLeft": 16, "paddingRight": 16, "textAlign": "left", @@ -278,6 +283,7 @@ exports[`call onPress when affix adornment pressed 1`] = ` [ { "color": "rgba(73, 69, 79, 1)", + "opacity": 1, }, { "fontFamily": "System", @@ -319,6 +325,7 @@ exports[`correctly applies a component as the text label 1`] = ` "bottom": 0, "height": 1, "left": 0, + "opacity": 1, "position": "absolute", "right": 0, "transform": [ @@ -363,6 +370,9 @@ exports[`correctly applies a component as the text label 1`] = ` { "zIndex": 3, }, + { + "opacity": 1, + }, ] } > @@ -520,6 +530,7 @@ exports[`correctly applies a component as the text label 1`] = ` "letterSpacing": 0.15, "lineHeight": undefined, "minWidth": 65, + "opacity": 1, "paddingLeft": 16, "paddingRight": 16, "textAlign": "left", @@ -561,6 +572,7 @@ exports[`correctly applies cursorColor prop 1`] = ` "bottom": 0, "height": 1, "left": 0, + "opacity": 1, "position": "absolute", "right": 0, "transform": [ @@ -605,6 +617,9 @@ exports[`correctly applies cursorColor prop 1`] = ` { "zIndex": 3, }, + { + "opacity": 1, + }, ] } > @@ -746,6 +761,7 @@ exports[`correctly applies cursorColor prop 1`] = ` "letterSpacing": 0.15, "lineHeight": undefined, "minWidth": 65, + "opacity": 1, "paddingLeft": 16, "paddingRight": 16, "textAlign": "left", @@ -787,6 +803,7 @@ exports[`correctly applies default textAlign based on default RTL 1`] = ` "bottom": 0, "height": 1, "left": 0, + "opacity": 1, "position": "absolute", "right": 0, "transform": [ @@ -831,6 +848,9 @@ exports[`correctly applies default textAlign based on default RTL 1`] = ` { "zIndex": 3, }, + { + "opacity": 1, + }, ] } > @@ -972,6 +992,7 @@ exports[`correctly applies default textAlign based on default RTL 1`] = ` "letterSpacing": 0.15, "lineHeight": undefined, "minWidth": 65, + "opacity": 1, "paddingLeft": 16, "paddingRight": 16, "textAlign": "left", @@ -1050,6 +1071,9 @@ exports[`correctly applies height to multiline Outline TextInput 1`] = ` { "zIndex": 3, }, + { + "opacity": 1, + }, ] } > @@ -1232,6 +1256,7 @@ exports[`correctly applies height to multiline Outline TextInput 1`] = ` "letterSpacing": 0.15, "lineHeight": undefined, "minWidth": 65, + "opacity": 1, "paddingHorizontal": 16, "textAlign": "left", "textAlignVertical": "top", @@ -1272,6 +1297,7 @@ exports[`correctly applies paddingLeft from contentStyleProp 1`] = ` "bottom": 0, "height": 1, "left": 0, + "opacity": 1, "position": "absolute", "right": 0, "transform": [ @@ -1316,6 +1342,9 @@ exports[`correctly applies paddingLeft from contentStyleProp 1`] = ` { "zIndex": 3, }, + { + "opacity": 1, + }, ] } > @@ -1457,6 +1486,7 @@ exports[`correctly applies paddingLeft from contentStyleProp 1`] = ` "letterSpacing": 0.15, "lineHeight": undefined, "minWidth": 65, + "opacity": 1, "paddingLeft": 16, "paddingRight": 16, "textAlign": "left", @@ -1500,6 +1530,7 @@ exports[`correctly applies textAlign center 1`] = ` "bottom": 0, "height": 1, "left": 0, + "opacity": 1, "position": "absolute", "right": 0, "transform": [ @@ -1544,6 +1575,9 @@ exports[`correctly applies textAlign center 1`] = ` { "zIndex": 3, }, + { + "opacity": 1, + }, ] } > @@ -1685,6 +1719,7 @@ exports[`correctly applies textAlign center 1`] = ` "letterSpacing": 0.15, "lineHeight": undefined, "minWidth": 65, + "opacity": 1, "paddingLeft": 16, "paddingRight": 16, "textAlign": "center", @@ -1726,6 +1761,7 @@ exports[`correctly renders left-side affix adornment, and right-side icon adornm "bottom": 0, "height": 1, "left": 0, + "opacity": 1, "position": "absolute", "right": 0, "transform": [ @@ -1770,6 +1806,9 @@ exports[`correctly renders left-side affix adornment, and right-side icon adornm { "zIndex": 3, }, + { + "opacity": 1, + }, ] } > @@ -1911,6 +1950,7 @@ exports[`correctly renders left-side affix adornment, and right-side icon adornm "letterSpacing": 0.15, "lineHeight": undefined, "minWidth": 65, + "opacity": 1, "paddingLeft": 16, "paddingRight": 56, "textAlign": "left", @@ -1952,6 +1992,7 @@ exports[`correctly renders left-side affix adornment, and right-side icon adornm [ { "color": "rgba(73, 69, 79, 1)", + "opacity": 1, }, { "fontFamily": "System", @@ -1980,6 +2021,9 @@ exports[`correctly renders left-side affix adornment, and right-side icon adornm "position": "absolute", "width": 24, }, + { + "opacity": 1, + }, { "right": 16, "top": 16, @@ -2012,7 +2056,7 @@ exports[`correctly renders left-side affix adornment, and right-side icon adornm style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -2088,35 +2132,43 @@ exports[`correctly renders left-side affix adornment, and right-side icon adornm } testID="right-icon-adornment" > - + - heart - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + heart + + @@ -2145,6 +2197,7 @@ exports[`correctly renders left-side icon adornment, and right-side affix adornm "bottom": 0, "height": 1, "left": 0, + "opacity": 1, "position": "absolute", "right": 0, "transform": [ @@ -2189,6 +2242,9 @@ exports[`correctly renders left-side icon adornment, and right-side affix adornm { "zIndex": 3, }, + { + "opacity": 1, + }, ] } > @@ -2330,6 +2386,7 @@ exports[`correctly renders left-side icon adornment, and right-side affix adornm "letterSpacing": 0.15, "lineHeight": undefined, "minWidth": 65, + "opacity": 1, "paddingLeft": 56, "paddingRight": 56, "textAlign": "left", @@ -2360,6 +2417,9 @@ exports[`correctly renders left-side icon adornment, and right-side affix adornm "position": "absolute", "width": 24, }, + { + "opacity": 1, + }, { "left": 16, "top": 16, @@ -2392,7 +2452,7 @@ exports[`correctly renders left-side icon adornment, and right-side affix adornm style={ { "backgroundColor": "transparent", - "borderColor": "rgba(121, 116, 126, 1)", + "borderColor": "rgba(202, 196, 208, 1)", "borderRadius": 20, "borderWidth": 0, "elevation": 0, @@ -2468,35 +2528,43 @@ exports[`correctly renders left-side icon adornment, and right-side affix adornm } testID="left-icon-adornment" > - + - heart - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + heart + + @@ -2522,6 +2590,7 @@ exports[`correctly renders left-side icon adornment, and right-side affix adornm [ { "color": "rgba(73, 69, 79, 1)", + "opacity": 1, }, { "fontFamily": "System", diff --git a/src/components/__tests__/__snapshots__/ToggleButton.test.tsx.snap b/src/components/__tests__/__snapshots__/ToggleButton.test.tsx.snap index 0e475cd073..a8feb453e3 100644 --- a/src/components/__tests__/__snapshots__/ToggleButton.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/ToggleButton.test.tsx.snap @@ -5,7 +5,7 @@ exports[`renders disabled toggle button 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(29, 25, 43, 0.12)", + "backgroundColor": "rgba(230, 224, 233, 1)", "borderRadius": 4, "height": 42, "margin": 0, @@ -25,7 +25,7 @@ exports[`renders disabled toggle button 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(29, 25, 43, 0.12)", + "backgroundColor": "rgba(230, 224, 233, 1)", "borderColor": "rgba(121, 116, 126, 1)", "borderRadius": 4, "borderWidth": 0, @@ -105,35 +105,43 @@ exports[`renders disabled toggle button 1`] = ` } testID="icon-button" > - + - heart - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + heart + + @@ -144,7 +152,7 @@ exports[`renders toggle button 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(29, 25, 43, 0.12)", + "backgroundColor": "rgba(230, 224, 233, 1)", "borderRadius": 4, "height": 42, "margin": 0, @@ -164,7 +172,7 @@ exports[`renders toggle button 1`] = ` collapsable={false} style={ { - "backgroundColor": "rgba(29, 25, 43, 0.12)", + "backgroundColor": "rgba(230, 224, 233, 1)", "borderColor": "rgba(121, 116, 126, 1)", "borderRadius": 4, "borderWidth": 0, @@ -239,35 +247,43 @@ exports[`renders toggle button 1`] = ` } testID="icon-button" > - + - heart - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + heart + + @@ -278,7 +294,7 @@ exports[`renders unchecked toggle button 1`] = ` collapsable={false} style={ { - "backgroundColor": "transparent", + "backgroundColor": "rgba(243, 237, 247, 1)", "borderRadius": 4, "height": 42, "margin": 0, @@ -298,7 +314,7 @@ exports[`renders unchecked toggle button 1`] = ` collapsable={false} style={ { - "backgroundColor": "transparent", + "backgroundColor": "rgba(243, 237, 247, 1)", "borderColor": "rgba(121, 116, 126, 1)", "borderRadius": 4, "borderWidth": 0, @@ -378,35 +394,43 @@ exports[`renders unchecked toggle button 1`] = ` } testID="icon-button" > - + - heart - + [ + { + "lineHeight": 24, + "transform": [ + { + "scaleX": 1, + }, + ], + }, + { + "backgroundColor": "transparent", + }, + ], + ] + } + > + heart + + diff --git a/src/core/__tests__/theming.test.tsx b/src/core/__tests__/theming.test.tsx index 7b069cd482..f9efe7752e 100644 --- a/src/core/__tests__/theming.test.tsx +++ b/src/core/__tests__/theming.test.tsx @@ -91,7 +91,7 @@ describe('adaptNavigationTheme', () => { ...NavigationLightTheme.colors, primary: MD3LightTheme.colors.primary, background: MD3LightTheme.colors.background, - card: MD3LightTheme.colors.elevation.level2, + card: MD3LightTheme.colors.surfaceContainer, text: MD3LightTheme.colors.onSurface, border: MD3LightTheme.colors.outline, notification: MD3LightTheme.colors.error, @@ -103,7 +103,7 @@ describe('adaptNavigationTheme', () => { ...NavigationDarkTheme.colors, primary: MD3DarkTheme.colors.primary, background: MD3DarkTheme.colors.background, - card: MD3DarkTheme.colors.elevation.level2, + card: MD3DarkTheme.colors.surfaceContainer, text: MD3DarkTheme.colors.onSurface, border: MD3DarkTheme.colors.outline, notification: MD3DarkTheme.colors.error, @@ -125,7 +125,7 @@ describe('adaptNavigationTheme', () => { ...NavigationLightTheme.colors, primary: colors.primary, background: colors.background, - card: colors.elevation.level2, + card: colors.surfaceContainer, text: colors.onSurface, border: colors.outline, notification: colors.error, @@ -146,7 +146,7 @@ describe('adaptNavigationTheme', () => { ...NavigationDarkTheme.colors, primary: colors.primary, background: colors.background, - card: colors.elevation.level2, + card: colors.surfaceContainer, text: colors.onSurface, border: colors.outline, notification: colors.error, @@ -167,7 +167,7 @@ describe('adaptNavigationTheme', () => { ...NavigationCustomLightTheme.colors, primary: colors.primary, background: colors.background, - card: colors.elevation.level2, + card: colors.surfaceContainer, text: colors.onSurface, border: colors.outline, notification: colors.error, @@ -191,7 +191,7 @@ describe('adaptNavigationTheme', () => { ...NavigationLightTheme.colors, primary: colors.primary, background: colors.background, - card: colors.elevation.level2, + card: colors.surfaceContainer, text: colors.onSurface, border: colors.outline, notification: colors.error, @@ -213,7 +213,7 @@ describe('adaptNavigationTheme', () => { ...NavigationDarkTheme.colors, primary: colors.primary, background: colors.background, - card: colors.elevation.level2, + card: colors.surfaceContainer, text: colors.onSurface, border: colors.outline, notification: colors.error, @@ -232,7 +232,7 @@ describe('adaptNavigationTheme', () => { ...NavigationThemeWithFonts.colors, primary: MD3LightTheme.colors.primary, background: MD3LightTheme.colors.background, - card: MD3LightTheme.colors.elevation.level2, + card: MD3LightTheme.colors.surfaceContainer, text: MD3LightTheme.colors.onSurface, border: MD3LightTheme.colors.outline, notification: MD3LightTheme.colors.error, diff --git a/src/core/theming.tsx b/src/core/theming.tsx index 042a83d960..04649515c6 100644 --- a/src/core/theming.tsx +++ b/src/core/theming.tsx @@ -1,15 +1,9 @@ import type { ComponentType } from 'react'; import { $DeepPartial, createTheming } from '@callstack/react-theme-provider'; -import color from 'color'; import { MD3DarkTheme, MD3LightTheme } from '../styles/themes'; -import type { - InternalTheme, - MD3Theme, - MD3AndroidColors, - NavigationTheme, -} from '../types'; +import type { InternalTheme, MD3Theme, NavigationTheme } from '../types'; export const DefaultTheme = MD3LightTheme; @@ -105,7 +99,7 @@ const getAdaptedTheme = ( ...theme.colors, primary: materialTheme.colors.primary, background: materialTheme.colors.background, - card: materialTheme.colors.elevation.level2, + card: materialTheme.colors.surfaceContainer, text: materialTheme.colors.onSurface, border: materialTheme.colors.outline, notification: materialTheme.colors.error, @@ -142,19 +136,3 @@ const getAdaptedTheme = ( return base; }; - -export const getDynamicThemeElevations = (scheme: MD3AndroidColors) => { - const elevationValues = ['transparent', 0.05, 0.08, 0.11, 0.12, 0.14]; - return elevationValues.reduce((elevations, elevationValue, index) => { - return { - ...elevations, - [`level${index}`]: - index === 0 - ? elevationValue - : color(scheme.surface) - .mix(color(scheme.primary), elevationValue as number) - .rgb() - .string(), - }; - }, {}); -}; diff --git a/src/styles/themes/v3/DarkTheme.tsx b/src/styles/themes/v3/DarkTheme.tsx index a8dd709faf..c8e21e8d46 100644 --- a/src/styles/themes/v3/DarkTheme.tsx +++ b/src/styles/themes/v3/DarkTheme.tsx @@ -1,10 +1,10 @@ import color from 'color'; import { MD3LightTheme } from './LightTheme'; -import { MD3Colors, tokens } from './tokens'; +import { tokens } from './tokens'; import type { MD3Theme } from '../../../types'; -const { palette, opacity } = tokens.md.ref; +const { palette, stateOpacity } = tokens.md.ref; export const MD3DarkTheme: MD3Theme = { ...MD3LightTheme, @@ -28,10 +28,6 @@ export const MD3DarkTheme: MD3Theme = { surfaceContainerHigh: palette.neutral17, surfaceContainerHighest: palette.neutral22, surfaceVariant: palette.neutralVariant30, - surfaceDisabled: color(palette.neutral90) - .alpha(opacity.level2) - .rgb() - .string(), background: palette.neutral6, error: palette.error80, errorContainer: palette.error30, @@ -43,10 +39,6 @@ export const MD3DarkTheme: MD3Theme = { onTertiaryContainer: palette.tertiary90, onSurface: palette.neutral90, onSurfaceVariant: palette.neutralVariant80, - onSurfaceDisabled: color(palette.neutral90) - .alpha(opacity.level4) - .rgb() - .string(), onError: palette.error20, onErrorContainer: palette.error80, onBackground: palette.neutral90, @@ -69,12 +61,15 @@ export const MD3DarkTheme: MD3Theme = { onTertiaryFixedVariant: palette.tertiary30, shadow: palette.neutral0, scrim: palette.neutral0, - backdrop: color(MD3Colors.neutralVariant20).alpha(0.4).rgb().string(), + stateLayerPressed: color(palette.neutral90) + .alpha(stateOpacity.pressed) + .rgb() + .string(), elevation: { level0: 'transparent', - level1: palette.neutral4, - level2: palette.neutral10, - level3: palette.neutral12, + level1: palette.neutral10, + level2: palette.neutral12, + level3: palette.neutral17, level4: palette.neutral17, level5: palette.neutral22, }, diff --git a/src/styles/themes/v3/LightTheme.tsx b/src/styles/themes/v3/LightTheme.tsx index c7b32d6013..da0ece6476 100644 --- a/src/styles/themes/v3/LightTheme.tsx +++ b/src/styles/themes/v3/LightTheme.tsx @@ -1,10 +1,10 @@ import color from 'color'; -import { MD3Colors, tokens } from './tokens'; +import { tokens } from './tokens'; import type { MD3Theme } from '../../../types'; import configureFonts from '../../fonts'; -const { palette, opacity } = tokens.md.ref; +const { palette, stateOpacity } = tokens.md.ref; export const MD3LightTheme: MD3Theme = { dark: false, @@ -27,10 +27,6 @@ export const MD3LightTheme: MD3Theme = { surfaceContainerHigh: palette.neutral92, surfaceContainerHighest: palette.neutral90, surfaceVariant: palette.neutralVariant90, - surfaceDisabled: color(palette.neutral10) - .alpha(opacity.level2) - .rgb() - .string(), background: palette.neutral98, error: palette.error40, errorContainer: palette.error90, @@ -42,10 +38,6 @@ export const MD3LightTheme: MD3Theme = { onTertiaryContainer: palette.tertiary10, onSurface: palette.neutral10, onSurfaceVariant: palette.neutralVariant30, - onSurfaceDisabled: color(palette.neutral10) - .alpha(opacity.level4) - .rgb() - .string(), onError: palette.error100, onErrorContainer: palette.error10, onBackground: palette.neutral10, @@ -68,12 +60,15 @@ export const MD3LightTheme: MD3Theme = { onTertiaryFixedVariant: palette.tertiary30, shadow: palette.neutral0, scrim: palette.neutral0, - backdrop: color(MD3Colors.neutralVariant20).alpha(0.4).rgb().string(), + stateLayerPressed: color(palette.neutral10) + .alpha(stateOpacity.pressed) + .rgb() + .string(), elevation: { level0: 'transparent', - level1: palette.neutral100, - level2: palette.neutral96, - level3: palette.neutral94, + level1: palette.neutral96, + level2: palette.neutral94, + level3: palette.neutral92, level4: palette.neutral92, level5: palette.neutral90, }, diff --git a/src/styles/themes/v3/tokens.tsx b/src/styles/themes/v3/tokens.tsx index 6eb27445fd..12486aca53 100644 --- a/src/styles/themes/v3/tokens.tsx +++ b/src/styles/themes/v3/tokens.tsx @@ -116,12 +116,19 @@ const ref = { weightMedium: '500' as Font['fontWeight'], }, - opacity: { - level1: 0.08, - level2: 0.12, - level3: 0.16, - level4: 0.38, + /** State layers opacity + * @see https://m3.material.io/foundations/interaction/states/state-layers + */ + stateOpacity: { + dragged: 0.16, + pressed: 0.1, + focus: 0.1, + hover: 0.08, + disabled: 0.38, + enabled: 1.0, }, + + scrimAlpha: 0.32, }; const regularType = { diff --git a/src/types.tsx b/src/types.tsx index d8d0e81125..fc10abf1a7 100644 --- a/src/types.tsx +++ b/src/types.tsx @@ -44,7 +44,6 @@ export type MD3Colors = { surfaceContainerHigh: string; surfaceContainerHighest: string; surfaceVariant: string; - surfaceDisabled: string; background: string; error: string; errorContainer: string; @@ -56,7 +55,6 @@ export type MD3Colors = { onTertiaryContainer: string; onSurface: string; onSurfaceVariant: string; - onSurfaceDisabled: string; onError: string; onErrorContainer: string; onBackground: string; @@ -79,44 +77,15 @@ export type MD3Colors = { onTertiaryFixedVariant: string; shadow: string; scrim: string; - backdrop: string; + /** Pre-computed state layer color at press opacity (0.10). + * Used for ripple effects. Avoids runtime alpha manipulation + * which is incompatible with PlatformColor on Android. + * TODO: revisit after https://github.com/facebook/react-native/pull/56395 + * @see https://m3.material.io/foundations/interaction/states/state-layers */ + stateLayerPressed: string; elevation: MD3ElevationColors; }; -export type MD3AndroidColors = { - primary: number; - primaryContainer: number; - secondary: number; - secondaryContainer: number; - tertiary: number; - tertiaryContainer: number; - surface: number; - surfaceVariant: number; - background: number; - error: number; - errorContainer: number; - onPrimary: number; - onPrimaryContainer: number; - onSecondary: number; - onSecondaryContainer: number; - onTertiary: number; - onTertiaryContainer: number; - onSurface: number; - onSurfaceVariant: number; - onError: number; - onErrorContainer: number; - onBackground: number; - outline: number; - outlineVariant: number; - inverseSurface: number; - inverseOnSurface: number; - inversePrimary: number; - shadow: number; - scrim: number; -}; - -export type MD3Palette = {}; - export type ThemeProp = $DeepPartial; export type ThemeBase = { From c5367b3ac26f1547b3fcebe444945ee8fc932e3d Mon Sep 17 00:00:00 2001 From: Michal Lul Date: Tue, 28 Apr 2026 10:04:39 +0200 Subject: [PATCH 13/13] feat: text field component --- docs/docusaurus.config.js | 3 + docs/src/components/PropTable.tsx | 12 +- docs/src/data/screenshots.js | 4 + docs/static/screenshots/text-field-filled.png | Bin 0 -> 40005 bytes .../screenshots/text-field-outlined.png | Bin 0 -> 25143 bytes example/src/ExampleList.tsx | 2 + example/src/Examples/TextFieldExample.tsx | 213 +++++++ src/components/TextField/TextField.tsx | 293 ++++++++++ src/components/TextField/constants.ts | 57 ++ src/components/TextField/filled/constants.ts | 33 ++ src/components/TextField/filled/logic.ts | 258 +++++++++ src/components/TextField/filled/styles.ts | 55 ++ src/components/TextField/filled/utils.ts | 34 ++ src/components/TextField/logic.ts | 261 +++++++++ .../TextField/outlined/constants.ts | 55 ++ src/components/TextField/outlined/logic.ts | 215 ++++++++ src/components/TextField/outlined/styles.ts | 43 ++ src/components/TextField/outlined/utils.ts | 39 ++ src/components/TextField/styles.ts | 45 ++ src/components/TextField/utils.ts | 88 +++ src/components/__tests__/TextField.test.tsx | 522 ++++++++++++++++++ .../__snapshots__/TextField.test.tsx.snap | 328 +++++++++++ src/index.tsx | 6 + 23 files changed, 2564 insertions(+), 2 deletions(-) create mode 100644 docs/static/screenshots/text-field-filled.png create mode 100644 docs/static/screenshots/text-field-outlined.png create mode 100644 example/src/Examples/TextFieldExample.tsx create mode 100644 src/components/TextField/TextField.tsx create mode 100644 src/components/TextField/constants.ts create mode 100644 src/components/TextField/filled/constants.ts create mode 100644 src/components/TextField/filled/logic.ts create mode 100644 src/components/TextField/filled/styles.ts create mode 100644 src/components/TextField/filled/utils.ts create mode 100644 src/components/TextField/logic.ts create mode 100644 src/components/TextField/outlined/constants.ts create mode 100644 src/components/TextField/outlined/logic.ts create mode 100644 src/components/TextField/outlined/styles.ts create mode 100644 src/components/TextField/outlined/utils.ts create mode 100644 src/components/TextField/styles.ts create mode 100644 src/components/TextField/utils.ts create mode 100644 src/components/__tests__/TextField.test.tsx create mode 100644 src/components/__tests__/__snapshots__/TextField.test.tsx.snap diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index 1dec1bb6ec..ab4a61be5e 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -170,6 +170,7 @@ const config = { TextInputAffix: 'TextInput/Adornment/TextInputAffix', TextInputIcon: 'TextInput/Adornment/TextInputIcon', }, + TextField: 'TextField/TextField', ToggleButton: { ToggleButton: 'ToggleButton/ToggleButton', ToggleButtonGroup: 'ToggleButton/ToggleButtonGroup', @@ -206,6 +207,8 @@ const config = { } const customUrls = { + TextField: 'src/components/TextField/TextField.tsx', + TextInput: 'src/components/TextInput/TextInput.tsx', TextInputAffix: 'src/components/TextInput/Adornment/TextInputAffix.tsx', TextInputIcon: diff --git a/docs/src/components/PropTable.tsx b/docs/src/components/PropTable.tsx index 35f5069433..47ffe3d4f5 100644 --- a/docs/src/components/PropTable.tsx +++ b/docs/src/components/PropTable.tsx @@ -11,17 +11,23 @@ const typeDefinitions = { 'https://github.com/callstack/react-native-paper/blob/main/src/components/Icon.tsx#L16', ThemeProp: 'https://callstack.github.io/react-native-paper/docs/guides/theming#theme-properties', + 'ComponentType': + 'https://github.com/callstack/react-native-paper/blob/main/src/components/TextField/TextField.tsx#L21', AccessibilityState: 'https://reactnative.dev/docs/accessibility#accessibilitystate', 'StyleProp': 'https://reactnative.dev/docs/view-style-props', 'StyleProp': 'https://reactnative.dev/docs/text-style-props', + TextProps: 'https://reactnative.dev/docs/text#props', }; const renderBadge = (annotation: string) => { const [annotType, ...annotLabel] = annotation.split(' '); // eslint-disable-next-line prettier/prettier - return `${annotLabel.join(' ')}`; + return `${annotLabel.join(' ')}`; }; export default function PropTable({ @@ -56,7 +62,9 @@ export default function PropTable({ if (line.includes('@')) { const annotIndex = line.indexOf('@'); // eslint-disable-next-line prettier/prettier - return `${line.substr(0, annotIndex)} ${renderBadge(line.substr(annotIndex))}`; + return `${line.substr(0, annotIndex)} ${renderBadge( + line.substr(annotIndex) + )}`; } else { return line; } diff --git a/docs/src/data/screenshots.js b/docs/src/data/screenshots.js index c1afa99a6a..185fa877a3 100644 --- a/docs/src/data/screenshots.js +++ b/docs/src/data/screenshots.js @@ -146,6 +146,10 @@ const screenshots = { 'iOS (disabled)': 'screenshots/switch-disabled.ios.png', }, Text: 'screenshots/typography.png', + TextField: { + filled: 'screenshots/text-field-filled.png', + outlined: 'screenshots/text-field-outlined.png', + }, TextInput: { 'flat (focused)': 'screenshots/textinput-flat.focused.png', 'flat (disabled)': 'screenshots/textinput-flat.disabled.png', diff --git a/docs/static/screenshots/text-field-filled.png b/docs/static/screenshots/text-field-filled.png new file mode 100644 index 0000000000000000000000000000000000000000..03ab10d37eb94c5e60b825fbdac149fcae4e7924 GIT binary patch literal 40005 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

w2 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 Swl<>x0000g#C%~n|ML|I!Pyl3MC@AOv3JR7X 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

P9hfvwG&=nSMyK9 zKVcp0F|+upifHE~QU{7$6v9c&4tL>96x{rL%`hAqbXU;$yg&JpfKGIK4H|SLqy8LH z_H#v{6;)8jJ8a*|-{(9la~2RrM;k)>gnU@flIG@ksb|MI zG+FCg!}Ee%!8mO1Q|91_yL4>qt@5!{P;+X7l)>Bp$#^moMlq^mo7wVQ`zF-farhma zz1pCcNQ5`;=UWwYvKZf&(a|-e`w`DE_8tzef-HrPO%0=X$p0J)0B76yq^`oBz7<*L z3a;|eTSx0nHLgu6J{yoxpk*L>ZJ)B@?c||YH1zzpoi&`~OTT~oT@!obD2GR@w+u(+PZoIkNx z6vdJfru2Oi{X&KovaTcvwpo*}SvB8?JHkFN-5UYv3l)UJvDH3`(!P;nR)(*3k4Nr3 z!alL2C2%63u0)hHKbEb2>}OXyS{Y%q$6_BBEJhELO|j8O>!ha9m%Pd?nlz24<5w|7 zFk|8=ER#~;L8Y6%rH7|~Cd_g6Zu!jj^n)H5RLn&9V}L5SSvLoD-FlDPZ$pw|9ze~k ze?x|R-?NzW)I-_`$lez15WmQX^sEG(plUS_<*uyDstQSAiI?u%{>?bABcAeCo7yRd z_RyhX!$}B}M?hoNa-*0WjlU;2!SyzY)=8Krjelr6Ie5O!|=o36t$3Vk+ta^qdr-4pm1s}fFp9uO{_@7 zLGq^OFXGail}sdudi6OhSV05`Rq2G7tUFM{ zTf-hnNuN;#A;{o2ruu92Lfz*t#dr<9_BUWX)k(KDOFuN?s$=SgZ+AEDt!v%k?qU2x z{KvGZnxXy44;0vQmU1Xqh8bY5_r##@F-AY&ebt0J2l7J?iLD$ML=LuH%NZJ!u$vyB zp2DbAv?Z}8xZ_rJANAY`1&Ng12A=imm7Twc^r*LlFKcV`e5gNs#G`d`6Ck=*7Ce9r ze8g3#VU1n(N6bYnCX9ud>0qZ)qXoK(7yhk_>wcqbSA=Crwq&#y?%?blv82aD`^6|= zGQrSmna)2v#x~He$Fv_hE@BayRM7Nf%j3O*1#*lr7hQZ~wtHPhcrd$TO=jCcV5yY> zDJExESHzwfW6eW!6`Sd&4q+f6xV5Qb?s`r0ERXOx1VF#E+Vnhe!@uG&#-eYquc-2v z(xI;&&-7^gw7KHd;M8%>g8XW4$cS%q&+XiUEqfm^JlC4lJoH2^!L?`M^`nE2lR^kU zkw9cg8&hRP*Lr#X1{ATODWl+VnXlx;X)w)o+*nPQoWA8A@Ul9idX`i-u%i!ZbZ*iQ zZ^ilu3E1`O>$TD?3i4lQHBxle1ZJ^i8Fr+G&O009|N0le|G*Laz|RxerbwZ5yNc-p zMXTyg&{WE#r+#-^GkrT@Hm*DXm6uSDbnkIB`^)Icus-{Y*l4;2Q0tA+*VE_OC literal 0 HcmV?d00001 diff --git a/example/src/ExampleList.tsx b/example/src/ExampleList.tsx index 016f085caa..bdaa584e12 100644 --- a/example/src/ExampleList.tsx +++ b/example/src/ExampleList.tsx @@ -43,6 +43,7 @@ import SwitchExample from './Examples/SwitchExample'; import TeamDetails from './Examples/TeamDetails'; import TeamsList from './Examples/TeamsList'; import TextExample from './Examples/TextExample'; +import TextFieldExample from './Examples/TextFieldExample'; import TextInputExample from './Examples/TextInputExample'; import ThemeExample from './Examples/ThemeExample'; import ThemingWithReactNavigation from './Examples/ThemingWithReactNavigation'; @@ -89,6 +90,7 @@ export const mainExamples: Record< surface: SurfaceExample, switch: SwitchExample, text: TextExample, + textField: TextFieldExample, textInput: TextInputExample, toggleButton: ToggleButtonExample, tooltipExample: TooltipExample, diff --git a/example/src/Examples/TextFieldExample.tsx b/example/src/Examples/TextFieldExample.tsx new file mode 100644 index 0000000000..f0c2758696 --- /dev/null +++ b/example/src/Examples/TextFieldExample.tsx @@ -0,0 +1,213 @@ +import * as React from 'react'; +import { Pressable, StyleSheet, View } from 'react-native'; + +import { + Icon, + List, + TextField, + type TextFieldAccessoryProps, +} from 'react-native-paper'; + +import { useExampleTheme } from '../hooks/useExampleTheme'; +import ScreenWrapper from '../ScreenWrapper'; + +const TextFieldExample = () => { + const { colors } = useExampleTheme(); + const iconMuted = colors.onSurfaceVariant; + const [searchQuery, setSearchQuery] = React.useState(''); + const [email, setEmail] = React.useState(''); + const [filledPassword, setFilledPassword] = React.useState(''); + const [filledNotes, setFilledNotes] = React.useState(''); + const [outlinedSearchQuery, setOutlinedSearchQuery] = React.useState(''); + const [outlinedText, setOutlinedText] = React.useState(''); + const [outlinedPassword, setOutlinedPassword] = React.useState(''); + const [outlinedNotes, setOutlinedNotes] = React.useState(''); + const [errorField, setErrorField] = React.useState('invalid@'); + + const ClearFilledSearchAccessory = ({ + style, + editable, + }: TextFieldAccessoryProps) => { + return ( + setSearchQuery('')} + accessibilityRole="button" + accessibilityLabel="Clear text" + > + + + ); + }; + + const ClearOutlinedSearchAccessory = ({ + style, + editable, + }: TextFieldAccessoryProps) => { + return ( + setOutlinedSearchQuery('')} + accessibilityRole="button" + accessibilityLabel="Clear text" + > + + + ); + }; + + const SearchLeadingAccessory = ({ style }: TextFieldAccessoryProps) => { + return ( + + + + ); + }; + + return ( + + + + + + + + + + + + + + + + + + + + ); +}; + +TextFieldExample.title = 'TextField'; + +const styles = StyleSheet.create({ + container: { + paddingHorizontal: 16, + paddingVertical: 8, + }, + field: {}, + section: { + gap: 16, + }, +}); + +export default TextFieldExample; diff --git a/src/components/TextField/TextField.tsx b/src/components/TextField/TextField.tsx new file mode 100644 index 0000000000..abab35a6f1 --- /dev/null +++ b/src/components/TextField/TextField.tsx @@ -0,0 +1,293 @@ +import React, { ComponentType } from 'react'; +import { + Animated, + Pressable, + StyleProp, + Text, + TextInput, + TextInputProps, + TextProps, + TextStyle, + View, + ViewStyle, +} from 'react-native'; + +import { useTextField } from './logic'; +import type { InternalTheme, ThemeProp } from '../../types'; + +export type TextFieldVariant = 'filled' | 'outlined'; + +export interface TextFieldAccessoryProps { + style: StyleProp; + status?: 'error' | 'disabled'; + multiline: boolean; + editable: boolean; +} + +export type TextFieldSharedApi = { + input: React.RefObject; + theme: InternalTheme; + isFocused: boolean; + disabled: boolean; + hasAccessory: boolean; + hasError: boolean; + $animatedLabelWrapperStyle: Animated.WithAnimatedObject; + $animatedLabelTextStyle: Animated.WithAnimatedObject; + $animatedPlaceholderStyle: Animated.WithAnimatedObject; + $animatedActiveOutlineStyle?: Animated.WithAnimatedObject; +}; + +export interface TextFieldProps extends TextInputProps { + /** + * Ref forwarded to the underlying TextInput. + */ + ref?: React.Ref; + /** + * - `filled` text fields are often used in dialogs and short forms where their style draws more attention. + * - `outlined` text fields are often used in long forms where their reduced emphasis helps simplify the layout. + */ + variant?: TextFieldVariant; + /** + * A style modifier for different input states. + */ + status?: 'error' | 'disabled'; + /** + * The label text to display above the input. + */ + label?: string; + /** + * Pass any additional props directly to the label Text component. + */ + labelProps?: TextProps; + /** + * Supporting text to display below the input (Material Design 3). When + * `status` is `error`, this text is styled as an error message. + */ + supportingText?: string; + /** + * Pass any additional props directly to the supporting text `Text` component. + */ + supportingTextProps?: TextProps; + /** + * Style overrides for the pressable root element. + */ + pressableStyle?: StyleProp; + /** + * Style overrides for the field container (the bordered row that includes + * LeftAccessory, input content, and RightAccessory). + */ + fieldStyle?: StyleProp; + /** + * Style overrides for the input content wrapper (the area containing + * the label and TextInput, excluding accessories). + */ + containerStyle?: StyleProp; + theme?: ThemeProp; + /** + * An optional component to render on the right side of the input. + */ + RightAccessory?: ComponentType; + /** + * An optional component to render on the left side of the input. + */ + LeftAccessory?: ComponentType; +} + +/** + * A text field lets users enter and edit text. It shows an optional floating label, + * supports `filled` and `outlined` variants, optional supporting text (including + * error state), and left/right accessories. + * + * ## Usage + * ```js + * import * as React from 'react'; + * import { Pressable, View } from 'react-native'; + * import { Icon, TextField } from 'react-native-paper'; + * + * const MyComponent = () => { + * const [text, setText] = React.useState(''); + * + * const LeadingAccessory = ({ style }) => ( + * + * + * + * ); + * + * const TrailingAccessory = ({ style, editable }) => ( + * setText('')} + * accessibilityRole="button" + * accessibilityLabel="Clear text" + * > + * + * + * ); + * + * return ( + * + * ); + * }; + * + * export default MyComponent; + * ``` + * + * @extends TextInput props https://reactnative.dev/docs/textinput#props + */ +function TextField(props: TextFieldProps) { + /* eslint-disable @typescript-eslint/no-unused-vars -- peel TextField-only props before TextInput spread */ + const { + ref, + status, + label, + supportingText, + supportingTextProps, + labelProps, + variant, + pressableStyle, + fieldStyle, + containerStyle, + theme, + LeftAccessory, + RightAccessory, + ...textInputProps + } = props; + + const { + input, + disabled, + hasError, + $pressableStyles, + $leadingAccessoryStyles, + $trailingAccessoryStyles, + $fieldStyles, + $disabledBackgroundStyles, + $outlineStyles, + $animatedActiveOutlineStyles, + $animatedLabelWrapperStyles, + $animatedLabelTextStyles, + $containerStyles, + $inputStyles, + $supportingTextStyles, + $selectionColor, + $cursorColor, + $animatedPlaceholderStyles, + LeadingAccessory, + TrailingAccessory, + focusInput, + onFocusHandler, + onBlurHandler, + } = useTextField(props); + + return ( + + + {/* Disabled tint overlay — filled variant only. A childless + absolutely-positioned View whose translucent fill is applied via the + `opacity` style, so it never affects label/input rendering and works + with PlatformColor on Android. */} + {!!$disabledBackgroundStyles && ( + + )} + + {/* Inactive indicator — always-visible 1px bottom border (filled) or + full border (outlined); height and color reflect error/disabled state + but do not change on focus */} + + + {/* Active indicator — filled variant only; 2px bar that expands from + the center outward via scaleX (0 → 1) on focus and collapses on blur */} + {!!$animatedActiveOutlineStyles && ( + + )} + + {!!label && ( + + + {label} + + + )} + + {!!LeadingAccessory && ( + + )} + + + {/* Animated placeholder — a custom Text node that fades in once the + label has floated up; rendered only when a placeholder is provided + and the field is empty so it never overlaps real input text */} + {!!textInputProps.placeholder && !textInputProps.value && ( + + {textInputProps.placeholder} + + )} + + + + + {!!TrailingAccessory && ( + + )} + + + {!!supportingText && ( + + {supportingText} + + )} + + ); +} + +export default TextField; diff --git a/src/components/TextField/constants.ts b/src/components/TextField/constants.ts new file mode 100644 index 0000000000..38f0d107cf --- /dev/null +++ b/src/components/TextField/constants.ts @@ -0,0 +1,57 @@ +import { Platform } from 'react-native'; + +// ================== +// PLATFORM +// ================== +export const isWeb = Platform.OS === 'web'; + +// ===================== +// FIELD LAYOUT +// ===================== +export const TEXT_FIELD_HEIGHT = 56; +export const TEXT_FIELD_PADDING_VERTICAL = 8; +export const TEXT_FIELD_INPUT_WRAPPER_PADDING_HORIZONTAL = 16; +export const TEXT_FIELD_ACCESSORY_MARGIN_HORIZONTAL = 12; + +// ================== +// ACCESSORY +// ================== +export const ACCESSORY_SIZE = 24; + +// =============== +// TYPOGRAPHY +// =============== +export const LINE_HEIGHT_DELTA = 2; +export const INPUT_FONT_SIZE = 16; +export const ACTIVE_LABEL_FONT_SIZE = 12; +export const INACTIVE_LABEL_FONT_SIZE = INPUT_FONT_SIZE; +export const HELPER_FONT_SIZE = 12; + +export const INACTIVE_LABEL_TOP_POSITION = + (TEXT_FIELD_HEIGHT - + 2 * TEXT_FIELD_PADDING_VERTICAL - + INACTIVE_LABEL_FONT_SIZE) / + 2 + + TEXT_FIELD_PADDING_VERTICAL - + LINE_HEIGHT_DELTA; + +// ================= +// HELPER TEXT LAYOUT +// ================= +export const HELPER_MARGIN_TOP = 4; + +// ========= +// ANIMATION +// ========= +export const ANIMATION_DURATION_MS = 150; + +// ========= +// INDICATOR +// ========= +export const ACTIVE_INDICATOR_SIZE = 2; +export const INACTIVE_INDICATOR_SIZE = 1; + +// ============ +// SHAPE +// ============ +export const TEXT_FIELD_BORDER_RADIUS = 4; diff --git a/src/components/TextField/filled/constants.ts b/src/components/TextField/filled/constants.ts new file mode 100644 index 0000000000..9b783ccd5e --- /dev/null +++ b/src/components/TextField/filled/constants.ts @@ -0,0 +1,33 @@ +import { + ACCESSORY_SIZE, + ACTIVE_LABEL_FONT_SIZE, + TEXT_FIELD_ACCESSORY_MARGIN_HORIZONTAL, + TEXT_FIELD_INPUT_WRAPPER_PADDING_HORIZONTAL, + TEXT_FIELD_PADDING_VERTICAL, +} from '../constants'; + +// ================== +// LABEL POSITIONING +// ================== + +export const LABEL_LEFT_OFFSET_WITH_ACCESSORY = + ACCESSORY_SIZE + + TEXT_FIELD_ACCESSORY_MARGIN_HORIZONTAL + + TEXT_FIELD_INPUT_WRAPPER_PADDING_HORIZONTAL; + +export const LABEL_LEFT_OFFSET_WITHOUT_ACCESSORY = + TEXT_FIELD_INPUT_WRAPPER_PADDING_HORIZONTAL; + +export const ACTIVE_LABEL_TOP_POSITION = TEXT_FIELD_PADDING_VERTICAL; + +// ================== +// PLACEHOLDER & MULTILINE POSITIONING +// ================== + +export const PADDING_TOP = ACTIVE_LABEL_FONT_SIZE + TEXT_FIELD_PADDING_VERTICAL; + +// ================== +// OPACITY +// ================== + +export const FILLED_CONTAINER_ALPHA = 0.04; diff --git a/src/components/TextField/filled/logic.ts b/src/components/TextField/filled/logic.ts new file mode 100644 index 0000000000..4db793f4c4 --- /dev/null +++ b/src/components/TextField/filled/logic.ts @@ -0,0 +1,258 @@ +import { + Animated, + I18nManager, + StyleProp, + TextStyle, + ViewStyle, +} from 'react-native'; + +import { + ACTIVE_INDICATOR_SIZE, + INACTIVE_INDICATOR_SIZE, + INPUT_FONT_SIZE, + isWeb, + TEXT_FIELD_INPUT_WRAPPER_PADDING_HORIZONTAL, +} from '../constants'; +import { + $disabledStyle, + $inputStyle, + $leadingAccessoryStyle, + $supportingTextStyle, + $trailingAccessoryStyle, +} from '../styles'; +import type { TextFieldProps, TextFieldSharedApi } from '../TextField'; +import { + getFieldBackgroundColor, + getLabelColor, + getSupportingTextColor, +} from '../utils'; +import { + LABEL_LEFT_OFFSET_WITH_ACCESSORY, + LABEL_LEFT_OFFSET_WITHOUT_ACCESSORY, + PADDING_TOP, +} from './constants'; +import { + $containerStyle, + $fieldStyle, + $labelTextStyle, + $labelWrapperStyle, + $disabledBackgroundStyle, + $outlineStyle, +} from './styles'; +import { getOutlineColor } from './utils'; + +export const getFilledTextFieldData = ( + api: TextFieldSharedApi, + props: TextFieldProps +) => { + const { + labelProps, + supportingTextProps, + style: $inputStyleOverride, + fieldStyle: $fieldStyleOverride, + containerStyle: $containerStyleOverride, + ...textInputProps + } = props; + + const { + input, + theme, + isFocused, + disabled, + hasAccessory, + hasError, + $animatedLabelWrapperStyle, + $animatedLabelTextStyle, + $animatedPlaceholderStyle, + $animatedActiveOutlineStyle, + } = api; + + // ======================= + // CONSTANTS + // ======================= + + const { isRTL } = I18nManager; + + // ======================= + // THEME TOKENS + // ======================= + + const { + colors: { onSurface }, + } = theme; + + const labelColor = getLabelColor({ + theme, + status: props.status, + isFocused, + disabled, + }); + + const outlineColor = getOutlineColor({ + theme, + status: props.status, + isFocused: false, + disabled, + }); + + const activeOutlineColor = getOutlineColor({ + theme, + status: props.status, + isFocused: true, + disabled, + }); + + const fieldBackgroundColor = getFieldBackgroundColor({ theme, disabled }); + + const supportingTextColor = getSupportingTextColor({ + theme, + status: props.status, + disabled, + }); + + // ======================= + // STYLES + // ======================= + + const $animatedLabelWrapperStyles: StyleProp< + Animated.WithAnimatedObject | ViewStyle + > = [ + $labelWrapperStyle, + { + left: hasAccessory + ? LABEL_LEFT_OFFSET_WITH_ACCESSORY + : LABEL_LEFT_OFFSET_WITHOUT_ACCESSORY, + }, + $animatedLabelWrapperStyle, + ]; + + const $animatedLabelTextStyles: StyleProp< + Animated.WithAnimatedObject | TextStyle + > = [ + $labelTextStyle, + { + color: labelColor, + }, + $animatedLabelTextStyle, + disabled && $disabledStyle, + labelProps?.style, + ]; + + const $fieldStyles = [ + $fieldStyle, + { + backgroundColor: fieldBackgroundColor, + }, + $fieldStyleOverride, + ]; + + /* Disabled tint (`onSurface @ 0.04`) is rendered as a childless overlay so its + alpha can be applied via the `opacity` style without leaking onto the label + and input. The View accepts `PlatformColor` directly. */ + const $disabledBackgroundStyles: StyleProp = disabled + ? [ + $disabledBackgroundStyle, + { + backgroundColor: onSurface, + }, + ] + : undefined; + + const $outlineStyles = [ + $outlineStyle, + { + height: INACTIVE_INDICATOR_SIZE, + backgroundColor: outlineColor, + }, + disabled && $disabledStyle, + ]; + + const $animatedActiveOutlineStyles: StyleProp< + Animated.WithAnimatedObject | ViewStyle + > = [ + $outlineStyle, + { + height: ACTIVE_INDICATOR_SIZE, + backgroundColor: activeOutlineColor, + }, + disabled && $disabledStyle, + $animatedActiveOutlineStyle, + ]; + + const $containerStyles = [$containerStyle, $containerStyleOverride]; + + const $supportingTextStyles: StyleProp = [ + $supportingTextStyle, + { + color: supportingTextColor, + writingDirection: isRTL ? 'rtl' : 'ltr', + }, + disabled && $disabledStyle, + supportingTextProps?.style, + ]; + + const $inputStyles: StyleProp = [ + $inputStyle, + { + color: onSurface, + fontSize: INPUT_FONT_SIZE, + textAlign: isRTL ? 'right' : 'left', + writingDirection: isRTL ? 'rtl' : 'ltr', + }, + textInputProps.multiline && { + height: 'auto' as TextStyle['height'], + paddingTop: PADDING_TOP, + }, + isWeb && { + outlineStyle: 'none' as TextStyle['outlineStyle'], + }, + disabled && $disabledStyle, + $inputStyleOverride, + ]; + + const $leadingAccessoryStyles = [ + $leadingAccessoryStyle, + disabled && $disabledStyle, + ]; + + const $trailingAccessoryStyles = [ + $trailingAccessoryStyle, + disabled && $disabledStyle, + ]; + + const $animatedPlaceholderStyles: StyleProp< + Animated.WithAnimatedObject | TextStyle + > = [ + $inputStyle, + { + position: 'absolute', + top: PADDING_TOP, + left: TEXT_FIELD_INPUT_WRAPPER_PADDING_HORIZONTAL, + fontSize: INPUT_FONT_SIZE, + color: + textInputProps.placeholderTextColor ?? theme.colors.onSurfaceVariant, + textAlign: isRTL ? 'right' : 'left', + writingDirection: isRTL ? 'rtl' : 'ltr', + }, + disabled && $disabledStyle, + $animatedPlaceholderStyle, + ]; + + return { + input, + disabled, + hasError, + $animatedLabelWrapperStyles, + $animatedLabelTextStyles, + $animatedPlaceholderStyles, + $fieldStyles, + $disabledBackgroundStyles, + $outlineStyles, + $animatedActiveOutlineStyles, + $containerStyles, + $supportingTextStyles, + $inputStyles, + $leadingAccessoryStyles, + $trailingAccessoryStyles, + }; +}; diff --git a/src/components/TextField/filled/styles.ts b/src/components/TextField/filled/styles.ts new file mode 100644 index 0000000000..88672cb299 --- /dev/null +++ b/src/components/TextField/filled/styles.ts @@ -0,0 +1,55 @@ +import { TextStyle, ViewStyle } from 'react-native'; + +import { + TEXT_FIELD_BORDER_RADIUS, + TEXT_FIELD_HEIGHT, + TEXT_FIELD_INPUT_WRAPPER_PADDING_HORIZONTAL, + TEXT_FIELD_PADDING_VERTICAL, +} from '../constants'; +import { FILLED_CONTAINER_ALPHA } from './constants'; + +export const $fieldStyle: ViewStyle = { + minHeight: TEXT_FIELD_HEIGHT, + flexDirection: 'row', + paddingVertical: TEXT_FIELD_PADDING_VERTICAL, + borderTopStartRadius: TEXT_FIELD_BORDER_RADIUS, + borderTopEndRadius: TEXT_FIELD_BORDER_RADIUS, +}; + +export const $outlineStyle: ViewStyle = { + position: 'absolute', + left: 0, + right: 0, + bottom: 0, +}; + +export const $containerStyle: ViewStyle = { + flex: 1, + paddingHorizontal: TEXT_FIELD_INPUT_WRAPPER_PADDING_HORIZONTAL, + justifyContent: 'flex-end', +}; + +export const $labelWrapperStyle: ViewStyle = { + position: 'absolute', +}; + +export const $labelTextStyle: TextStyle = { + fontWeight: '400', + includeFontPadding: false, + paddingVertical: 0, + paddingHorizontal: 0, +}; + +/* Disabled tint (`onSurface @ 0.04`) is rendered as a childless overlay so its + alpha can be applied via the `opacity` style without leaking onto the label + and input. The View accepts `PlatformColor` directly. */ +export const $disabledBackgroundStyle: ViewStyle = { + position: 'absolute', + top: 0, + left: 0, + right: 0, + bottom: 0, + opacity: FILLED_CONTAINER_ALPHA, + borderTopStartRadius: TEXT_FIELD_BORDER_RADIUS, + borderTopEndRadius: TEXT_FIELD_BORDER_RADIUS, +}; diff --git a/src/components/TextField/filled/utils.ts b/src/components/TextField/filled/utils.ts new file mode 100644 index 0000000000..3a055b8bf9 --- /dev/null +++ b/src/components/TextField/filled/utils.ts @@ -0,0 +1,34 @@ +import type { InternalTheme } from '../../../types'; + +/** + * Returns the raw outline color for a filled field. The disabled state's + * alpha is intentionally NOT baked in here — it is applied via the `opacity` + * style on the (childless) outline View so the value can be a `PlatformColor` + * on Android, which the `color` library cannot parse at runtime. + */ +export const getOutlineColor = ({ + theme, + status, + isFocused, + disabled, +}: { + theme: InternalTheme; + isFocused: boolean; + status?: 'error' | 'disabled'; + disabled: boolean; +}) => { + const { + colors: { error, onSurface, primary, outline }, + } = theme; + + if (disabled) { + return onSurface; + } + if (status === 'error') { + return error; + } + if (isFocused) { + return primary; + } + return outline; +}; diff --git a/src/components/TextField/logic.ts b/src/components/TextField/logic.ts new file mode 100644 index 0000000000..9697dfe6fb --- /dev/null +++ b/src/components/TextField/logic.ts @@ -0,0 +1,261 @@ +import { + useEffect, + useImperativeHandle, + useMemo, + useRef, + useState, +} from 'react'; +import { + Animated, + BlurEvent, + FocusEvent, + I18nManager, + TextInput, + TextStyle, + ViewStyle, +} from 'react-native'; + +import { + ACTIVE_LABEL_FONT_SIZE, + ANIMATION_DURATION_MS, + INACTIVE_LABEL_FONT_SIZE, + INACTIVE_LABEL_TOP_POSITION, +} from './constants'; +import { ACTIVE_LABEL_TOP_POSITION as FILLED_ACTIVE_LABEL_TOP } from './filled/constants'; +import { getFilledTextFieldData } from './filled/logic'; +import { + LABEL_TRANSLATE_X_WITHOUT_ACCESSORY, + LABEL_TRANSLATE_X_WITH_ACCESSORY, + ACTIVE_LABEL_TOP_POSITION as OUTLINED_ACTIVE_LABEL_TOP, +} from './outlined/constants'; +import { getOutlinedTextFieldData } from './outlined/logic'; +import { $pressableStyle } from './styles'; +import type { TextFieldProps, TextFieldSharedApi } from './TextField'; +import { getAccentColors } from './utils'; +import { useInternalTheme } from '../../core/theming'; + +export const useTextField = (props: TextFieldProps) => { + const { + ref, + variant = 'filled', + pressableStyle: $pressableStyleOverride, + theme: themeOverride, + onFocus, + onBlur, + } = props; + + // ======================= + // HOOKS + // ======================= + + const input = useRef(null); + + const theme = useInternalTheme(themeOverride); + + const [isFocused, setIsFocused] = useState(false); + + useImperativeHandle(ref, () => input.current as TextInput); + + // ======================= + // CONSTANTS + // ======================= + + const { isRTL } = I18nManager; + const disabled = props.editable === false || props.status === 'disabled'; + const isFloating = isFocused || !!props.value; + const hasAccessory = isRTL ? !!props.RightAccessory : !!props.LeftAccessory; + const hasError = props.status === 'error'; + + // ======================= + // THEME TOKENS + // ======================= + + const { selectionColor: $selectionColor, cursorColor: $cursorColor } = + getAccentColors({ theme, hasError }); + + // ======================= + // LABEL ANIMATION + // ======================= + + const { + $animatedLabelWrapperStyle, + $animatedLabelTextStyle, + $animatedPlaceholderStyle, + $animatedActiveOutlineStyle, + } = useTextFieldAnimation({ + variant, + isFloating, + isFocused, + hasAccessory, + }); + + // ======================= + // HANDLERS + // ======================= + + const onFocusHandler = (e: FocusEvent) => { + onFocus?.(e); + setIsFocused(true); + }; + + const onBlurHandler = (e: BlurEvent) => { + onBlur?.(e); + setIsFocused(false); + }; + + const focusInput = () => { + if (disabled) return; + input.current?.focus(); + }; + + // ======================= + // SHARED API + // ======================= + + const api: TextFieldSharedApi = { + input, + theme, + isFocused, + disabled, + hasAccessory, + hasError, + $animatedLabelWrapperStyle, + $animatedLabelTextStyle, + $animatedPlaceholderStyle, + $animatedActiveOutlineStyle, + }; + + const LeadingAccessory = isRTL ? props.RightAccessory : props.LeftAccessory; + const TrailingAccessory = isRTL ? props.LeftAccessory : props.RightAccessory; + + // ======================= + // STYLES + // ======================= + + const $pressableStyles = [$pressableStyle, $pressableStyleOverride]; + + const data = { + isFocused, + $pressableStyles, + $selectionColor, + $cursorColor, + $animatedActiveOutlineStyles: undefined, + LeadingAccessory, + TrailingAccessory, + onFocusHandler, + onBlurHandler, + focusInput, + }; + + if (variant === 'filled') { + return { + ...data, + ...getFilledTextFieldData(api, props), + }; + } + + return { + ...data, + ...getOutlinedTextFieldData(api, props), + }; +}; + +const useTextFieldAnimation = ({ + variant, + isFloating, + isFocused, + hasAccessory, +}: { + variant: 'filled' | 'outlined'; + isFloating: boolean; + isFocused: boolean; + hasAccessory: boolean; +}): { + $animatedLabelWrapperStyle: Animated.WithAnimatedObject; + $animatedLabelTextStyle: Animated.WithAnimatedObject; + $animatedPlaceholderStyle: Animated.WithAnimatedObject; + $animatedActiveOutlineStyle?: Animated.WithAnimatedObject; +} => { + const focusProgress = useRef(new Animated.Value(isFocused ? 1 : 0)).current; + + const floatingProgress = useRef( + new Animated.Value(isFloating ? 1 : 0) + ).current; + + useEffect(() => { + Animated.timing(focusProgress, { + toValue: isFocused ? 1 : 0, + duration: ANIMATION_DURATION_MS, + useNativeDriver: true, + }).start(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isFocused]); + + useEffect(() => { + Animated.timing(floatingProgress, { + toValue: isFloating ? 1 : 0, + duration: ANIMATION_DURATION_MS, + useNativeDriver: false, + }).start(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isFloating]); + + return useMemo(() => { + const activeTop = + variant === 'filled' + ? FILLED_ACTIVE_LABEL_TOP + : OUTLINED_ACTIVE_LABEL_TOP; + + const fontSize = floatingProgress.interpolate({ + inputRange: [0, 1], + outputRange: [INACTIVE_LABEL_FONT_SIZE, ACTIVE_LABEL_FONT_SIZE], + }); + + const top = floatingProgress.interpolate({ + inputRange: [0, 1], + outputRange: [INACTIVE_LABEL_TOP_POSITION, activeTop], + }); + + const opacity = floatingProgress.interpolate({ + inputRange: [0, 1], + outputRange: [0, 1], + }); + + if (variant === 'filled') { + const scaleX = focusProgress.interpolate({ + inputRange: [0, 1], + outputRange: [0, 1], + }); + + return { + $animatedLabelWrapperStyle: { top }, + $animatedLabelTextStyle: { fontSize }, + $animatedPlaceholderStyle: { opacity }, + $animatedActiveOutlineStyle: { + transform: [{ scaleX }], + }, + }; + } + + const translateXEnd = hasAccessory + ? LABEL_TRANSLATE_X_WITH_ACCESSORY + : LABEL_TRANSLATE_X_WITHOUT_ACCESSORY; + + return { + $animatedLabelWrapperStyle: { + top, + transform: [ + { + translateX: floatingProgress.interpolate({ + inputRange: [0, 1], + outputRange: [0, translateXEnd], + }), + }, + ], + }, + $animatedLabelTextStyle: { fontSize }, + $animatedPlaceholderStyle: { opacity }, + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [variant, hasAccessory]); +}; diff --git a/src/components/TextField/outlined/constants.ts b/src/components/TextField/outlined/constants.ts new file mode 100644 index 0000000000..e0ea1cf98c --- /dev/null +++ b/src/components/TextField/outlined/constants.ts @@ -0,0 +1,55 @@ +import { I18nManager } from 'react-native'; + +import { + ACCESSORY_SIZE, + LINE_HEIGHT_DELTA, + TEXT_FIELD_ACCESSORY_MARGIN_HORIZONTAL, + TEXT_FIELD_INPUT_WRAPPER_PADDING_HORIZONTAL, + TEXT_FIELD_PADDING_VERTICAL, +} from '../constants'; + +// ================== +// LAYOUT SUPPORT +// ================== + +const isRTL = I18nManager.isRTL; +const layoutSupportMultiplier = isRTL ? -1 : 1; + +// ================== +// LABEL POSITIONING +// ================== +export const LABEL_PADDING_HORIZONTAL = 4; + +export const LABEL_LEFT_OFFSET_WITH_ACCESSORY = + ACCESSORY_SIZE + + TEXT_FIELD_ACCESSORY_MARGIN_HORIZONTAL + + TEXT_FIELD_INPUT_WRAPPER_PADDING_HORIZONTAL - + LABEL_PADDING_HORIZONTAL; + +export const LABEL_LEFT_OFFSET_WITHOUT_ACCESSORY = + TEXT_FIELD_INPUT_WRAPPER_PADDING_HORIZONTAL; + +export const ACTIVE_LABEL_TOP_POSITION = + -TEXT_FIELD_PADDING_VERTICAL + LINE_HEIGHT_DELTA; + +export const LABEL_TRANSLATE_X_WITH_ACCESSORY = + -layoutSupportMultiplier * + (ACCESSORY_SIZE + + TEXT_FIELD_INPUT_WRAPPER_PADDING_HORIZONTAL - + LABEL_PADDING_HORIZONTAL); + +export const LABEL_TRANSLATE_X_WITHOUT_ACCESSORY = + -layoutSupportMultiplier * LABEL_PADDING_HORIZONTAL; + +// ================== +// PLACEHOLDER POSITIONING +// ================== + +export const PLACEHOLDER_TOP_POSITION = + TEXT_FIELD_PADDING_VERTICAL + LINE_HEIGHT_DELTA; + +// ============ +// OPACITY +// ============ + +export const OUTLINE_ALPHA = 0.12; diff --git a/src/components/TextField/outlined/logic.ts b/src/components/TextField/outlined/logic.ts new file mode 100644 index 0000000000..c13db1391e --- /dev/null +++ b/src/components/TextField/outlined/logic.ts @@ -0,0 +1,215 @@ +import { + Animated, + I18nManager, + StyleProp, + TextStyle, + ViewStyle, +} from 'react-native'; + +import { + INPUT_FONT_SIZE, + isWeb, + TEXT_FIELD_INPUT_WRAPPER_PADDING_HORIZONTAL, +} from '../constants'; +import { + $disabledStyle, + $supportingTextStyle, + $inputStyle, + $leadingAccessoryStyle, + $trailingAccessoryStyle, +} from '../styles'; +import type { TextFieldProps, TextFieldSharedApi } from '../TextField'; +import { getSupportingTextColor, getLabelColor } from '../utils'; +import { + LABEL_LEFT_OFFSET_WITH_ACCESSORY, + LABEL_LEFT_OFFSET_WITHOUT_ACCESSORY, + OUTLINE_ALPHA, + PLACEHOLDER_TOP_POSITION, +} from './constants'; +import { + $containerStyle, + $fieldStyle, + $labelTextStyle, + $labelWrapperStyle, + $outlineStyle, +} from './styles'; +import { getOutlineColor } from './utils'; + +export const getOutlinedTextFieldData = ( + api: TextFieldSharedApi, + props: TextFieldProps +) => { + const { + labelProps, + supportingTextProps, + style: $inputStyleOverride, + fieldStyle: $fieldStyleOverride, + containerStyle: $containerStyleOverride, + ...textInputProps + } = props; + + const { + input, + theme, + isFocused, + disabled, + hasAccessory, + hasError, + $animatedLabelWrapperStyle, + $animatedLabelTextStyle, + $animatedPlaceholderStyle, + } = api; + + // ======================= + // CONSTANTS + // ======================= + + const { isRTL } = I18nManager; + + // ======================= + // THEME TOKENS + // ======================= + + const { + colors: { background: labelBackgroundColor, onSurface }, + } = theme; + + const labelColor = getLabelColor({ + theme, + status: props.status, + isFocused, + disabled, + }); + + const outlineColor = getOutlineColor({ + theme, + disabled, + isFocused, + hasError, + }); + + const supportingTextColor = getSupportingTextColor({ + theme, + status: props.status, + disabled, + }); + + // ======================= + // STYLES + // ======================= + + const $fieldStyles = [$fieldStyle, $fieldStyleOverride]; + + /* The outline is a childless absolutely-positioned View, so applying + `opacity` here is safe and lets us pass `outlineColor` through unchanged + (including PlatformColor values on Android). */ + const $outlineStyles = [ + $outlineStyle, + { + borderWidth: isFocused ? 2 : 1, + borderColor: outlineColor, + }, + disabled && { opacity: OUTLINE_ALPHA }, + $fieldStyleOverride, + ]; + + const $containerStyles = [$containerStyle, $containerStyleOverride]; + + const $supportingTextStyles: StyleProp = [ + $supportingTextStyle, + { + color: supportingTextColor, + writingDirection: isRTL ? 'rtl' : 'ltr', + }, + disabled && $disabledStyle, + supportingTextProps?.style, + ]; + + const $animatedLabelWrapperStyles: StyleProp< + Animated.WithAnimatedObject | ViewStyle + > = [ + $labelWrapperStyle, + { + left: hasAccessory + ? LABEL_LEFT_OFFSET_WITH_ACCESSORY + : LABEL_LEFT_OFFSET_WITHOUT_ACCESSORY, + backgroundColor: labelBackgroundColor, + }, + $animatedLabelWrapperStyle, + ]; + + const $animatedLabelTextStyles: StyleProp< + Animated.WithAnimatedObject | TextStyle + > = [ + $labelTextStyle, + { + color: labelColor, + }, + $animatedLabelTextStyle, + disabled && $disabledStyle, + labelProps?.style, + ]; + + const $inputStyles: StyleProp = [ + $inputStyle, + { + color: onSurface, + fontSize: INPUT_FONT_SIZE, + textAlign: isRTL ? 'right' : 'left', + writingDirection: isRTL ? 'rtl' : 'ltr', + }, + textInputProps.multiline && { + height: 'auto' as TextStyle['height'], + }, + isWeb && { + outlineStyle: 'none' as TextStyle['outlineStyle'], + }, + disabled && $disabledStyle, + $inputStyleOverride, + ]; + + const $leadingAccessoryStyles = [ + $leadingAccessoryStyle, + disabled && $disabledStyle, + ]; + + const $trailingAccessoryStyles = [ + $trailingAccessoryStyle, + disabled && $disabledStyle, + ]; + + const $animatedPlaceholderStyles: StyleProp< + Animated.WithAnimatedObject | TextStyle + > = [ + $inputStyle, + { + position: 'absolute', + top: PLACEHOLDER_TOP_POSITION, + left: TEXT_FIELD_INPUT_WRAPPER_PADDING_HORIZONTAL, + fontSize: INPUT_FONT_SIZE, + color: + textInputProps.placeholderTextColor ?? theme.colors.onSurfaceVariant, + textAlign: isRTL ? 'right' : 'left', + writingDirection: isRTL ? 'rtl' : 'ltr', + }, + disabled && $disabledStyle, + $animatedPlaceholderStyle, + ]; + + return { + input, + disabled, + hasError, + $animatedLabelWrapperStyles, + $animatedLabelTextStyles, + $animatedPlaceholderStyles, + $fieldStyles, + $disabledBackgroundStyles: undefined, + $outlineStyles, + $containerStyles, + $supportingTextStyles, + $inputStyles, + $leadingAccessoryStyles, + $trailingAccessoryStyles, + }; +}; diff --git a/src/components/TextField/outlined/styles.ts b/src/components/TextField/outlined/styles.ts new file mode 100644 index 0000000000..5790d15296 --- /dev/null +++ b/src/components/TextField/outlined/styles.ts @@ -0,0 +1,43 @@ +import { TextStyle, ViewStyle } from 'react-native'; + +import { + TEXT_FIELD_BORDER_RADIUS, + TEXT_FIELD_HEIGHT, + TEXT_FIELD_INPUT_WRAPPER_PADDING_HORIZONTAL, + TEXT_FIELD_PADDING_VERTICAL, +} from '../constants'; +import { LABEL_PADDING_HORIZONTAL } from './constants'; + +export const $fieldStyle: ViewStyle = { + minHeight: TEXT_FIELD_HEIGHT, + flexDirection: 'row', + paddingVertical: TEXT_FIELD_PADDING_VERTICAL, + borderRadius: TEXT_FIELD_BORDER_RADIUS, +}; + +export const $outlineStyle: ViewStyle = { + position: 'absolute', + left: 0, + right: 0, + top: 0, + bottom: 0, + borderRadius: TEXT_FIELD_BORDER_RADIUS, +}; + +export const $containerStyle: ViewStyle = { + flex: 1, + paddingHorizontal: TEXT_FIELD_INPUT_WRAPPER_PADDING_HORIZONTAL, + justifyContent: 'center', +}; + +export const $labelWrapperStyle: ViewStyle = { + position: 'absolute', + paddingHorizontal: LABEL_PADDING_HORIZONTAL, +}; + +export const $labelTextStyle: TextStyle = { + fontWeight: '400', + includeFontPadding: false, + paddingVertical: 0, + paddingHorizontal: 0, +}; diff --git a/src/components/TextField/outlined/utils.ts b/src/components/TextField/outlined/utils.ts new file mode 100644 index 0000000000..6cf25b1a60 --- /dev/null +++ b/src/components/TextField/outlined/utils.ts @@ -0,0 +1,39 @@ +import type { InternalTheme } from '../../../types'; + +/** + * Returns the raw outline color for an outlined field. The disabled state's + * alpha is intentionally NOT baked in here — it is applied via the `opacity` + * style on the (childless) outline View so the value can be a `PlatformColor` + * on Android, which the `color` library cannot parse at runtime. + */ +export const getOutlineColor = ({ + theme, + isFocused, + disabled, + hasError, +}: { + theme: InternalTheme; + isFocused: boolean; + disabled: boolean; + hasError: boolean; +}) => { + const { + colors: { outline, onSurface, primary, error }, + } = theme; + + let outlineColor = outline; + + if (isFocused) { + outlineColor = primary; + } + + if (disabled) { + outlineColor = onSurface; + } + + if (hasError) { + outlineColor = error; + } + + return outlineColor; +}; diff --git a/src/components/TextField/styles.ts b/src/components/TextField/styles.ts new file mode 100644 index 0000000000..dc0473bfec --- /dev/null +++ b/src/components/TextField/styles.ts @@ -0,0 +1,45 @@ +import { StyleProp, TextStyle, ViewStyle } from 'react-native'; + +import { + ACCESSORY_SIZE, + HELPER_FONT_SIZE, + HELPER_MARGIN_TOP, + TEXT_FIELD_ACCESSORY_MARGIN_HORIZONTAL, + TEXT_FIELD_INPUT_WRAPPER_PADDING_HORIZONTAL, +} from './constants'; +import { tokens } from '../../styles/themes/v3/tokens'; + +export const $pressableStyle: ViewStyle = {}; + +export const $inputStyle: StyleProp = { + fontWeight: '400', + includeFontPadding: false, + paddingVertical: 0, + paddingHorizontal: 0, +}; + +export const $supportingTextStyle: TextStyle = { + marginTop: HELPER_MARGIN_TOP, + paddingHorizontal: TEXT_FIELD_INPUT_WRAPPER_PADDING_HORIZONTAL, + fontSize: HELPER_FONT_SIZE, + fontWeight: '400', + textAlign: 'left', +}; + +export const $trailingAccessoryStyle: ViewStyle = { + width: ACCESSORY_SIZE, + marginEnd: TEXT_FIELD_ACCESSORY_MARGIN_HORIZONTAL, + justifyContent: 'center', + alignItems: 'center', +}; + +export const $leadingAccessoryStyle: ViewStyle = { + width: ACCESSORY_SIZE, + marginStart: TEXT_FIELD_ACCESSORY_MARGIN_HORIZONTAL, + justifyContent: 'center', + alignItems: 'center', +}; + +export const $disabledStyle: ViewStyle = { + opacity: tokens.md.ref.stateOpacity.disabled, +}; diff --git a/src/components/TextField/utils.ts b/src/components/TextField/utils.ts new file mode 100644 index 0000000000..2c186af77f --- /dev/null +++ b/src/components/TextField/utils.ts @@ -0,0 +1,88 @@ +import type { InternalTheme } from '../../types'; + +export const getAccentColors = ({ + theme, + hasError, +}: { + theme: InternalTheme; + hasError: boolean; +}) => { + const color = hasError ? theme.colors.error : theme.colors.primary; + + return { + selectionColor: color, + cursorColor: color, + }; +}; + +export const getLabelColor = ({ + theme, + status, + isFocused, + disabled, +}: { + theme: InternalTheme; + isFocused: boolean; + status?: 'error' | 'disabled'; + disabled: boolean; +}) => { + const { + colors: { error, primary, onSurface, onSurfaceVariant }, + } = theme; + + if (disabled) { + return onSurface; + } + + if (status === 'error') { + return error; + } + if (isFocused) { + return primary; + } + return onSurfaceVariant; +}; + +export const getSupportingTextColor = ({ + theme, + status, + disabled, +}: { + theme: InternalTheme; + status?: 'error' | 'disabled'; + disabled: boolean; +}) => { + const { + colors: { error, onSurface, onSurfaceVariant }, + } = theme; + + if (disabled) { + return onSurface; + } + + if (status === 'error') { + return error; + } + return onSurfaceVariant; +}; + +/** + * Returns the solid background color for the filled field container, or + * `undefined` when disabled. The disabled tint (`onSurface @ 0.04`) is rendered + * as a separate overlay View whose alpha is applied via the `opacity` style; + * keeping the alpha out of the color string is what makes the component safe + * to use with `PlatformColor` values on Android. + */ +export const getFieldBackgroundColor = ({ + theme, + disabled, +}: { + theme: InternalTheme; + disabled: boolean; +}): string | undefined => { + if (disabled) { + return undefined; + } + + return theme.colors.surfaceContainerHighest; +}; diff --git a/src/components/__tests__/TextField.test.tsx b/src/components/__tests__/TextField.test.tsx new file mode 100644 index 0000000000..f58cd603d9 --- /dev/null +++ b/src/components/__tests__/TextField.test.tsx @@ -0,0 +1,522 @@ +import * as React from 'react'; +import { I18nManager, StyleSheet, TextInput, View } from 'react-native'; + +import { fireEvent, render } from '@testing-library/react-native'; + +import TextField, { + type TextFieldAccessoryProps, +} from '../TextField/TextField'; + +const defaultI18nIsRTL = I18nManager.isRTL; + +afterEach(() => { + I18nManager.isRTL = defaultI18nIsRTL; +}); + +function firstIndexOfTestIdInTree(tree: unknown, testID: string): number { + const serialized = JSON.stringify(tree); + const match = new RegExp(`"testID":\\s*"${testID}"`).exec(serialized); + return match ? match.index : -1; +} + +it('renders filled TextField with label and value', () => { + const tree = render( + {}} /> + ).toJSON(); + + expect(tree).toMatchSnapshot(); +}); + +it('renders outlined TextField with label and value', () => { + const tree = render( + {}} + /> + ).toJSON(); + + expect(tree).toMatchSnapshot(); +}); + +it('renders supporting text below the field', () => { + const { getByText } = render( + {}} + supportingText="Use a valid address" + /> + ); + + expect(getByText('Use a valid address')).toBeTruthy(); +}); + +it('sets aria-invalid on the input when status is error', () => { + const { getByTestId } = render( + {}} + status="error" + testID="tf-input" + /> + ); + + expect(getByTestId('tf-input').props['aria-invalid']).toBe(true); +}); + +it('uses assertive aria-live on supporting text when status is error', () => { + const { getByText } = render( + {}} + supportingText="Invalid" + status="error" + /> + ); + + expect(getByText('Invalid').props['aria-live']).toBe('assertive'); +}); + +it('uses polite aria-live on supporting text when there is no error', () => { + const { getByText } = render( + {}} + supportingText="Optional" + /> + ); + + expect(getByText('Optional').props['aria-live']).toBe('polite'); +}); + +it('marks the input as aria-disabled when editable is false', () => { + const { getByTestId } = render( + {}} + editable={false} + testID="tf-input" + /> + ); + + expect(getByTestId('tf-input').props['aria-disabled']).toBe(true); +}); + +it('marks the input as aria-disabled when status is disabled', () => { + const { getByTestId } = render( + {}} + status="disabled" + testID="tf-input" + /> + ); + + expect(getByTestId('tf-input').props['aria-disabled']).toBe(true); +}); + +it('forwards TextInput props such as testID', () => { + const { getByTestId } = render( + {}} + testID="email-input" + /> + ); + + expect(getByTestId('email-input')).toBeTruthy(); +}); + +it('does not pass TextField-only props through to TextInput', () => { + const { getByTestId } = render( + {}} + testID="tf-native" + /> + ); + + const input = getByTestId('tf-native'); + expect(input.props.variant).toBeUndefined(); + expect(input.props.theme).toBeUndefined(); + expect(input.props.LeftAccessory).toBeUndefined(); + expect(input.props.pressableStyle).toBeUndefined(); + expect(input.props.fieldStyle).toBeUndefined(); + expect(input.props.containerStyle).toBeUndefined(); + expect(input.props.supportingText).toBeUndefined(); + expect(input.props.supportingTextProps).toBeUndefined(); +}); + +it('invokes onFocus and onBlur on the TextInput', () => { + const onFocus = jest.fn(); + const onBlur = jest.fn(); + const { getByTestId } = render( + {}} + onFocus={onFocus} + onBlur={onBlur} + testID="tf-input" + /> + ); + + const input = getByTestId('tf-input'); + fireEvent(input, 'focus'); + fireEvent(input, 'blur'); + + expect(onFocus).toHaveBeenCalledTimes(1); + expect(onBlur).toHaveBeenCalledTimes(1); +}); + +it('focuses the TextInput when the outer Pressable is pressed', () => { + const focusSpy = jest.spyOn(TextInput.prototype, 'focus'); + + const { UNSAFE_getByProps, getByTestId } = render( + {}} + testID="tf-input" + /> + ); + + expect(getByTestId('tf-input')).toBeTruthy(); + + /* Pressable is not exposed as a distinct type in the test renderer; match its props. */ + const pressable = UNSAFE_getByProps({ role: 'none', accessible: false }); + fireEvent.press(pressable); + + expect(focusSpy).toHaveBeenCalled(); + focusSpy.mockRestore(); +}); + +it('does not focus the TextInput when disabled and the Pressable is pressed', () => { + const focusSpy = jest.spyOn(TextInput.prototype, 'focus'); + + const { UNSAFE_getByProps } = render( + {}} + editable={false} + /> + ); + + const pressable = UNSAFE_getByProps({ role: 'none', accessible: false }); + fireEvent.press(pressable); + + expect(focusSpy).not.toHaveBeenCalled(); + focusSpy.mockRestore(); +}); + +it('exposes the TextInput instance via ref prop', () => { + const ref = React.createRef(); + + render( + {}} + testID="tf-input" + /> + ); + + expect(ref.current).toBeTruthy(); + expect(typeof ref.current?.focus).toBe('function'); +}); + +it('passes status, editable, and multiline to accessories', () => { + const leftProps: TextFieldAccessoryProps[] = []; + const rightProps: TextFieldAccessoryProps[] = []; + + function LeftAccessory(props: TextFieldAccessoryProps) { + leftProps.push(props); + return ; + } + + function RightAccessory(props: TextFieldAccessoryProps) { + rightProps.push(props); + return ; + } + + const { getByTestId } = render( + {}} + multiline + status="error" + editable={false} + LeftAccessory={LeftAccessory} + RightAccessory={RightAccessory} + /> + ); + + expect(getByTestId('left-accessory')).toBeTruthy(); + expect(getByTestId('right-accessory')).toBeTruthy(); + expect(leftProps[0]).toMatchObject({ + status: 'error', + editable: false, + multiline: true, + }); + expect(rightProps[0]).toMatchObject({ + status: 'error', + editable: false, + multiline: true, + }); +}); + +it('applies supportingTextProps to the supporting Text', () => { + const { getByTestId } = render( + {}} + supportingText="Hint" + supportingTextProps={{ testID: 'supporting-text' }} + /> + ); + + expect(getByTestId('supporting-text').props.children).toBe('Hint'); +}); + +it('applies RTL text alignment and writing direction to the TextInput (filled)', () => { + I18nManager.isRTL = true; + + const { getByTestId } = render( + {}} + testID="tf-input-rtl" + /> + ); + + expect(StyleSheet.flatten(getByTestId('tf-input-rtl').props.style)).toEqual( + expect.objectContaining({ + textAlign: 'right', + writingDirection: 'rtl', + }) + ); +}); + +it('applies RTL text alignment and writing direction to the TextInput (outlined)', () => { + I18nManager.isRTL = true; + + const { getByTestId } = render( + {}} + testID="tf-input-rtl-outlined" + /> + ); + + expect( + StyleSheet.flatten(getByTestId('tf-input-rtl-outlined').props.style) + ).toEqual( + expect.objectContaining({ + textAlign: 'right', + writingDirection: 'rtl', + }) + ); +}); + +it('applies RTL writing direction to supporting text', () => { + I18nManager.isRTL = true; + + const { getByTestId } = render( + {}} + supportingText="Hint" + supportingTextProps={{ testID: 'supporting-text-rtl' }} + /> + ); + + expect( + StyleSheet.flatten(getByTestId('supporting-text-rtl').props.style) + ).toEqual( + expect.objectContaining({ + writingDirection: 'rtl', + }) + ); +}); + +it('places RightAccessory before LeftAccessory in the tree when RTL', () => { + I18nManager.isRTL = true; + + function LeftAccessory() { + return ; + } + + function RightAccessory() { + return ; + } + + const { toJSON } = render( + {}} + LeftAccessory={LeftAccessory} + RightAccessory={RightAccessory} + testID="tf-input-rtl-order" + /> + ); + + const tree = toJSON(); + expect( + firstIndexOfTestIdInTree(tree, 'rtl-acc-from-right-prop') + ).toBeLessThan(firstIndexOfTestIdInTree(tree, 'rtl-acc-from-left-prop')); +}); + +it('places LeftAccessory before RightAccessory in the tree when LTR', () => { + I18nManager.isRTL = false; + + function LeftAccessory() { + return ; + } + + function RightAccessory() { + return ; + } + + const { toJSON } = render( + {}} + LeftAccessory={LeftAccessory} + RightAccessory={RightAccessory} + testID="tf-input-ltr-order" + /> + ); + + const tree = toJSON(); + expect(firstIndexOfTestIdInTree(tree, 'ltr-acc-from-left-prop')).toBeLessThan( + firstIndexOfTestIdInTree(tree, 'ltr-acc-from-right-prop') + ); +}); + +it('hides placeholder when the TextField is not focused', () => { + const { getByTestId } = render( + {}} + placeholder="e.g. user@example.com" + testID="tf-input" + /> + ); + + expect(getByTestId('tf-input').props.placeholder).toBeUndefined(); +}); + +it('shows placeholder when the TextField is focused', () => { + const { getByTestId, getByText } = render( + {}} + placeholder="e.g. user@example.com" + testID="tf-input" + /> + ); + + fireEvent(getByTestId('tf-input'), 'focus'); + + expect(getByTestId('tf-input').props.placeholder).toBeUndefined(); + expect(getByText('e.g. user@example.com')).toBeTruthy(); +}); + +it('shows placeholder on multiline TextField when focused', () => { + const { getByTestId, getByText } = render( + {}} + placeholder="Add a note…" + multiline + testID="tf-multiline" + /> + ); + + expect(getByTestId('tf-multiline').props.placeholder).toBeUndefined(); + + fireEvent(getByTestId('tf-multiline'), 'focus'); + + expect(getByTestId('tf-multiline').props.placeholder).toBeUndefined(); + expect(getByText('Add a note…')).toBeTruthy(); +}); + +it('hides placeholder again after the TextField loses focus', () => { + const { getByTestId } = render( + {}} + placeholder="e.g. user@example.com" + testID="tf-input" + /> + ); + + fireEvent(getByTestId('tf-input'), 'focus'); + fireEvent(getByTestId('tf-input'), 'blur'); + + expect(getByTestId('tf-input').props.placeholder).toBeUndefined(); +}); + +it('maps a lone LeftAccessory to leading in LTR and trailing in RTL (tree order)', () => { + function LoneLeftAccessory() { + return ; + } + + I18nManager.isRTL = false; + + const { toJSON: toJsonLtr } = render( + {}} + LeftAccessory={LoneLeftAccessory} + testID="tf-lone-ltr" + /> + ); + + I18nManager.isRTL = true; + + const { toJSON: toJsonRtl } = render( + {}} + LeftAccessory={LoneLeftAccessory} + testID="tf-lone-rtl" + /> + ); + + const ltrTree = toJsonLtr(); + expect(firstIndexOfTestIdInTree(ltrTree, 'lone-left-acc')).toBeLessThan( + firstIndexOfTestIdInTree(ltrTree, 'tf-lone-ltr') + ); + + const rtlTree = toJsonRtl(); + expect(firstIndexOfTestIdInTree(rtlTree, 'tf-lone-rtl')).toBeLessThan( + firstIndexOfTestIdInTree(rtlTree, 'lone-left-acc') + ); +}); diff --git a/src/components/__tests__/__snapshots__/TextField.test.tsx.snap b/src/components/__tests__/__snapshots__/TextField.test.tsx.snap new file mode 100644 index 0000000000..236902c2ee --- /dev/null +++ b/src/components/__tests__/__snapshots__/TextField.test.tsx.snap @@ -0,0 +1,328 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders filled TextField with label and value 1`] = ` + + + + + + + Email + + + + + + + +`; + +exports[`renders outlined TextField with label and value 1`] = ` + + + + + + Password + + + + + + + +`; diff --git a/src/index.tsx b/src/index.tsx index 7e609b709e..f2903fa894 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -51,6 +51,7 @@ export { default as Surface } from './components/Surface'; export { default as Switch } from './components/Switch/Switch'; export { default as Appbar } from './components/Appbar'; export { default as TouchableRipple } from './components/TouchableRipple/TouchableRipple'; +export { default as TextField } from './components/TextField/TextField'; export { default as TextInput } from './components/TextInput/TextInput'; export { default as ToggleButton } from './components/ToggleButton'; export { default as SegmentedButtons } from './components/SegmentedButtons/SegmentedButtons'; @@ -135,6 +136,11 @@ export type { Props as SearchbarProps } from './components/Searchbar'; export type { Props as SnackbarProps } from './components/Snackbar'; export type { Props as SurfaceProps } from './components/Surface'; export type { Props as SwitchProps } from './components/Switch/Switch'; +export type { + TextFieldProps, + TextFieldAccessoryProps, + TextFieldVariant, +} from './components/TextField/TextField'; export type { Props as TextInputProps } from './components/TextInput/TextInput'; export type { Props as TextInputAffixProps } from './components/TextInput/Adornment/TextInputAffix'; export type { Props as TextInputIconProps } from './components/TextInput/Adornment/TextInputIcon';