Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/components/Appbar/AppbarHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
getAppbarBorders,
} from './utils';
import { useInternalTheme } from '../../core/theming';
import shadow from '../../theme/shadow';
import { shadow } from '../../theme/tokens/sys/elevation';
import type { ThemeProp } from '../../types';

export type Props = Omit<
Expand Down Expand Up @@ -141,7 +141,7 @@ const AppbarHeader = ({
paddingHorizontal: Math.max(left, right),
},
borderRadius,
shadow(elevation) as ViewStyle,
shadow(elevation, theme.colors.shadow) as ViewStyle,
]}
>
<Appbar
Expand Down
11 changes: 4 additions & 7 deletions src/components/Menu/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context';

import MenuItem from './MenuItem';
import { useInternalTheme } from '../../core/theming';
import type { Elevation, Theme, ThemeProp } from '../../types';
import { ElevationLevels } from '../../types';
import type { Elevation, ElevationLevel, Theme, ThemeProp } from '../../types';
import { addEventListener } from '../../utils/addEventListener';
import { BackHandler } from '../../utils/BackHandler/BackHandler';
import Portal from '../Portal/Portal';
Expand Down Expand Up @@ -105,10 +104,6 @@ const EASING = Easing.bezier(0.4, 0, 0.2, 1);
const WINDOW_LAYOUT = Dimensions.get('window');

const DEFAULT_ELEVATION: Elevation = 2;
export const ELEVATION_LEVELS_MAP = Object.values(
ElevationLevels
) as ElevationLevels[];

const DEFAULT_MODE = 'elevated';

const focusFirstDOMNode = (el: View | null | undefined) => {
Expand Down Expand Up @@ -675,7 +670,9 @@ const Menu = ({
shadowMenuContainerStyle,
{
backgroundColor:
md3Colors.elevation[ELEVATION_LEVELS_MAP[elevation]],
md3Colors.elevation[
`level${elevation}` as ElevationLevel
],
},
contentStyle,
]}
Expand Down
63 changes: 29 additions & 34 deletions src/components/Surface.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ import {
} from 'react-native';

import { useInternalTheme } from '../core/theming';
import shadow from '../theme/shadow';
import {
androidElevationLevels,
elevationInputRange,
shadow,
shadowLayers,
} from '../theme/tokens/sys/elevation';
import type { Elevation, Theme, ThemeProp } from '../types';
import { isAnimatedValue } from '../utils/animations';
import { forwardRef } from '../utils/forwardRef';
Expand Down Expand Up @@ -75,54 +80,41 @@ const outerLayerStyleProperties: (keyof ViewStyle)[] = [
'opacity',
];

const shadowColor = '#000';
const iOSShadowOutputRanges = [
{
shadowOpacity: 0.15,
height: [0, 1, 2, 4, 6, 8],
shadowRadius: [0, 3, 6, 8, 10, 12],
},
{
shadowOpacity: 0.3,
height: [0, 1, 1, 1, 2, 4],
shadowRadius: [0, 1, 2, 3, 3, 4],
},
];
const inputRange = [0, 1, 2, 3, 4, 5];
function getStyleForShadowLayer(
elevation: SurfaceElevation,
layer: 0 | 1
layer: 0 | 1,
shadowColor: string
): Animated.WithAnimatedValue<ShadowStyleIOS> {
if (isAnimatedValue(elevation)) {
return {
shadowColor,
shadowOpacity: elevation.interpolate({
inputRange: [0, 1],
outputRange: [0, iOSShadowOutputRanges[layer].shadowOpacity],
outputRange: [0, shadowLayers[layer].shadowOpacity],
extrapolate: 'clamp',
}),
shadowOffset: {
width: 0,
height: elevation.interpolate({
inputRange,
outputRange: iOSShadowOutputRanges[layer].height,
inputRange: [...elevationInputRange],
outputRange: [...shadowLayers[layer].height],
}),
},
shadowRadius: elevation.interpolate({
inputRange,
outputRange: iOSShadowOutputRanges[layer].shadowRadius,
inputRange: [...elevationInputRange],
outputRange: [...shadowLayers[layer].shadowRadius],
}),
};
}

return {
shadowColor,
shadowOpacity: elevation ? iOSShadowOutputRanges[layer].shadowOpacity : 0,
shadowOpacity: elevation ? shadowLayers[layer].shadowOpacity : 0,
shadowOffset: {
width: 0,
height: iOSShadowOutputRanges[layer].height[elevation],
height: shadowLayers[layer].height[elevation],
},
shadowRadius: iOSShadowOutputRanges[layer].shadowRadius[elevation],
shadowRadius: shadowLayers[layer].shadowRadius[elevation],
};
}

Expand All @@ -131,13 +123,15 @@ const SurfaceIOS = forwardRef<
Omit<Props, 'elevation'> & {
elevation: SurfaceElevation;
backgroundColor?: string | Animated.AnimatedInterpolation<string | number>;
shadowColor: string;
}
>(
(
{
elevation,
style,
backgroundColor,
shadowColor,
testID,
children,
mode = 'elevated',
Expand Down Expand Up @@ -173,14 +167,14 @@ const SurfaceIOS = forwardRef<
const isElevated = mode === 'elevated';

const outerLayerViewStyles = {
...(isElevated && getStyleForShadowLayer(elevation, 0)),
...(isElevated && getStyleForShadowLayer(elevation, 0, shadowColor)),
...outerLayerStyles,
...borderRadiusStyles,
backgroundColor: bgColor,
};

const innerLayerViewStyles = {
...(isElevated && getStyleForShadowLayer(elevation, 1)),
...(isElevated && getStyleForShadowLayer(elevation, 1, shadowColor)),
...filteredStyles,
...borderRadiusStyles,
flex:
Expand All @@ -191,7 +185,7 @@ const SurfaceIOS = forwardRef<
};

return [outerLayerViewStyles, innerLayerViewStyles];
}, [style, elevation, backgroundColor, mode, container]);
}, [style, elevation, backgroundColor, shadowColor, mode, container]);

return (
<Animated.View
Expand Down Expand Up @@ -255,13 +249,11 @@ const Surface = forwardRef<View, Props>(

const { colors } = theme as Theme;

const inputRange = [0, 1, 2, 3, 4, 5];

const backgroundColor = (() => {
if (isAnimatedValue(elevation)) {
return elevation.interpolate({
inputRange,
outputRange: inputRange.map((elevation) => {
inputRange: [...elevationInputRange],
outputRange: [...elevationInputRange].map((elevation) => {
return colors.elevation?.[`level${elevation as Elevation}`];
}),
});
Expand All @@ -282,7 +274,9 @@ const Surface = forwardRef<View, Props>(
testID={testID}
style={[
{ backgroundColor },
elevation && isElevated ? shadow(elevation) : null,
elevation && isElevated
? shadow(elevation, theme.colors.shadow)
: null,
style,
]}
>
Expand All @@ -292,12 +286,12 @@ const Surface = forwardRef<View, Props>(
}

if (Platform.OS === 'android') {
const elevationLevel = [0, 3, 6, 9, 12, 15];
const elevationLevel = [...androidElevationLevels];

const getElevationAndroid = () => {
if (isAnimatedValue(elevation)) {
return elevation.interpolate({
inputRange,
inputRange: [...elevationInputRange],
outputRange: elevationLevel,
});
}
Expand Down Expand Up @@ -340,6 +334,7 @@ const Surface = forwardRef<View, Props>(
ref={ref}
elevation={elevation}
backgroundColor={backgroundColor}
shadowColor={theme.colors.shadow}
style={style}
testID={testID}
mode={mode}
Expand Down
28 changes: 14 additions & 14 deletions src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ exports[`Appbar does not pass any additional props to Searchbar 1`] = `
{
"backgroundColor": "rgba(254, 247, 255, 1)",
"height": 64,
"shadowColor": "#000",
"shadowColor": "rgba(0, 0, 0, 1)",
"shadowOffset": {
"height": 0,
"width": 0,
Expand All @@ -31,7 +31,7 @@ exports[`Appbar does not pass any additional props to Searchbar 1`] = `
"paddingLeft": undefined,
"paddingRight": undefined,
"paddingTop": undefined,
"shadowColor": "#000",
"shadowColor": "rgba(0, 0, 0, 1)",
"shadowOffset": {
"height": 0,
"width": 0,
Expand All @@ -48,7 +48,7 @@ exports[`Appbar does not pass any additional props to Searchbar 1`] = `
{
"backgroundColor": "rgba(236, 230, 240, 1)",
"borderRadius": 28,
"shadowColor": "#000",
"shadowColor": "rgba(0, 0, 0, 1)",
"shadowOffset": {
"height": 0,
"width": 0,
Expand All @@ -68,7 +68,7 @@ exports[`Appbar does not pass any additional props to Searchbar 1`] = `
"borderRadius": 28,
"flex": undefined,
"flexDirection": "row",
"shadowColor": "#000",
"shadowColor": "rgba(0, 0, 0, 1)",
"shadowOffset": {
"height": 0,
"width": 0,
Expand All @@ -87,7 +87,7 @@ exports[`Appbar does not pass any additional props to Searchbar 1`] = `
"borderRadius": 20,
"height": 40,
"margin": 6,
"shadowColor": "#000",
"shadowColor": "rgba(0, 0, 0, 1)",
"shadowOffset": {
"height": 0,
"width": 0,
Expand All @@ -110,7 +110,7 @@ exports[`Appbar does not pass any additional props to Searchbar 1`] = `
"elevation": 0,
"flex": 1,
"overflow": "hidden",
"shadowColor": "#000",
"shadowColor": "rgba(0, 0, 0, 1)",
"shadowOffset": {
"height": 0,
"width": 0,
Expand Down Expand Up @@ -279,7 +279,7 @@ exports[`Appbar does not pass any additional props to Searchbar 1`] = `
"borderRadius": 20,
"height": 40,
"margin": 6,
"shadowColor": "#000",
"shadowColor": "rgba(0, 0, 0, 1)",
"shadowOffset": {
"height": 0,
"width": 0,
Expand All @@ -302,7 +302,7 @@ exports[`Appbar does not pass any additional props to Searchbar 1`] = `
"elevation": 0,
"flex": 1,
"overflow": "hidden",
"shadowColor": "#000",
"shadowColor": "rgba(0, 0, 0, 1)",
"shadowOffset": {
"height": 0,
"width": 0,
Expand Down Expand Up @@ -427,7 +427,7 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A
{
"backgroundColor": "rgba(254, 247, 255, 1)",
"height": 64,
"shadowColor": "#000",
"shadowColor": "rgba(0, 0, 0, 1)",
"shadowOffset": {
"height": 0,
"width": 0,
Expand All @@ -451,7 +451,7 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A
"paddingLeft": undefined,
"paddingRight": undefined,
"paddingTop": undefined,
"shadowColor": "#000",
"shadowColor": "rgba(0, 0, 0, 1)",
"shadowOffset": {
"height": 0,
"width": 0,
Expand All @@ -470,7 +470,7 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A
"borderRadius": 20,
"height": 40,
"margin": 6,
"shadowColor": "#000",
"shadowColor": "rgba(0, 0, 0, 1)",
"shadowOffset": {
"height": 0,
"width": 0,
Expand All @@ -493,7 +493,7 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A
"elevation": 0,
"flex": 1,
"overflow": "hidden",
"shadowColor": "#000",
"shadowColor": "rgba(0, 0, 0, 1)",
"shadowOffset": {
"height": 0,
"width": 0,
Expand Down Expand Up @@ -721,7 +721,7 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A
"borderRadius": 20,
"height": 40,
"margin": 6,
"shadowColor": "#000",
"shadowColor": "rgba(0, 0, 0, 1)",
"shadowOffset": {
"height": 0,
"width": 0,
Expand All @@ -744,7 +744,7 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A
"elevation": 0,
"flex": 1,
"overflow": "hidden",
"shadowColor": "#000",
"shadowColor": "rgba(0, 0, 0, 1)",
"shadowOffset": {
"height": 0,
"width": 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ exports[`Card renders an outlined card 1`] = `
{
"backgroundColor": "rgba(254, 247, 255, 1)",
"borderRadius": 12,
"shadowColor": "#000",
"shadowColor": "rgba(0, 0, 0, 1)",
"shadowOffset": {
"height": 0,
"width": 0,
Expand All @@ -25,7 +25,7 @@ exports[`Card renders an outlined card 1`] = `
"backgroundColor": "rgba(254, 247, 255, 1)",
"borderRadius": 12,
"flex": undefined,
"shadowColor": "#000",
"shadowColor": "rgba(0, 0, 0, 1)",
"shadowOffset": {
"height": 0,
"width": 0,
Expand Down
7 changes: 4 additions & 3 deletions src/components/__tests__/Menu.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { Animated, Dimensions, StyleSheet, View } from 'react-native';
import { act, render, screen, waitFor } from '@testing-library/react-native';

import { getTheme } from '../../core/theming';
import { Elevation } from '../../types';
import { Elevation, ElevationLevel } from '../../types';
import Button from '../Button/Button';
import Menu, { ELEVATION_LEVELS_MAP } from '../Menu/Menu';
import Menu from '../Menu/Menu';
import Portal from '../Portal/Portal';

const styles = StyleSheet.create({
Expand Down Expand Up @@ -87,7 +87,8 @@ it('renders menu with content styles', () => {
);

expect(getByTestId('menu-surface')).toHaveStyle({
backgroundColor: theme.colors.elevation[ELEVATION_LEVELS_MAP[elevation]],
backgroundColor:
theme.colors.elevation[`level${elevation}` as ElevationLevel],
});
})
);
Expand Down
Loading
Loading