Skip to content

Commit

Permalink
feat: adjust Card (#3158)
Browse files Browse the repository at this point in the history
  • Loading branch information
OlimpiaZurek authored Jun 6, 2022
1 parent 73cb3bc commit 8d3e7a2
Show file tree
Hide file tree
Showing 7 changed files with 328 additions and 92 deletions.
95 changes: 64 additions & 31 deletions example/src/Examples/CardExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,56 +7,83 @@ import {
Button,
IconButton,
useTheme,
Chip,
Text,
Switch,
} from 'react-native-paper';
import { PreferencesContext } from '..';
import ScreenWrapper from '../ScreenWrapper';

const CardExample = () => {
const { colors } = useTheme();
const [isOutlined, setIsOutlined] = React.useState(false);
const mode = isOutlined ? 'outlined' : 'elevated';
type Mode = 'elevated' | 'outlined' | 'filled';

const CardExample = () => {
const { colors, isV3 } = useTheme();
const [selectedMode, setSelectedMode] = React.useState('elevated' as Mode);
const [isSelected, setIsSelected] = React.useState(false);
const preferences = React.useContext(PreferencesContext);

const modes = isV3
? ['elevated', 'outlined', 'filled']
: ['elevated', 'outlined'];

const TextComponent = isV3 ? Text : Paragraph;

return (
<ScreenWrapper contentContainerStyle={styles.content}>
<View style={styles.preference}>
<Text>Outlined</Text>
<Switch
value={isOutlined}
onValueChange={() =>
setIsOutlined((prevIsOutlined) => !prevIsOutlined)
}
/>
{(modes as Mode[]).map((mode) => (
<Chip
key={mode}
selected={selectedMode === mode}
mode="outlined"
onPress={() => setSelectedMode(mode)}
style={styles.chip}
>
{mode}
</Chip>
))}
</View>
<ScrollView
style={[styles.container, { backgroundColor: colors?.background }]}
contentContainerStyle={styles.content}
>
<Card style={styles.card} mode={mode}>
<Card style={styles.card} mode={selectedMode}>
<Card.Cover
source={require('../../assets/images/wrecked-ship.jpg')}
/>
<Card.Title title="Abandoned Ship" />
<Card.Content>
<Paragraph>
<TextComponent variant="bodyMedium">
The Abandoned Ship is a wrecked ship located on Route 108 in
Hoenn, originally being a ship named the S.S. Cactus. The second
part of the ship can only be accessed by using Dive and contains
the Scanner.
</Paragraph>
</TextComponent>
</Card.Content>
</Card>
<Card style={styles.card} mode={mode}>
{isV3 && (
<Card style={styles.card} mode={selectedMode}>
<Card.Cover source={require('../../assets/images/bridge.jpg')} />
<Card.Title
title="Title variant"
subtitle="Subtitle variant"
titleVariant="headlineMedium"
subtitleVariant="bodyLarge"
/>
<Card.Content>
<TextComponent variant="bodyMedium">
This is a card using title and subtitle with specified variants.
</TextComponent>
</Card.Content>
</Card>
)}
<Card style={styles.card} mode={selectedMode}>
<Card.Cover source={require('../../assets/images/forest.jpg')} />
<Card.Actions>
<Button onPress={() => {}}>Share</Button>
<Button onPress={() => {}}>Explore</Button>
</Card.Actions>
</Card>
<Card style={styles.card} mode={mode}>
<Card style={styles.card} mode={selectedMode}>
<Card.Title
title="Berries that are trimmed at the end"
subtitle="Omega Ruby"
Expand All @@ -66,24 +93,28 @@ const CardExample = () => {
)}
/>
<Card.Content>
<Paragraph>
<TextComponent variant="bodyMedium">
Dotted around the Hoenn region, you will find loamy soil, many of
which are housing berries. Once you have picked the berries, then
you have the ability to use that loamy soil to grow your own
berries. These can be any berry and will require attention to get
the best crop.
</Paragraph>
</TextComponent>
</Card.Content>
</Card>
<Card style={styles.card} mode={mode}>
<Card style={styles.card} mode={selectedMode}>
<Card.Cover
source={require('../../assets/images/strawberries.jpg')}
/>
<Card.Title
title="Just Strawberries"
subtitle="... and only Strawberries"
right={(props: any) => (
<IconButton {...props} icon="chevron-down" onPress={() => {}} />
<IconButton
{...props}
icon={isSelected ? 'heart' : 'heart-outline'}
onPress={() => setIsSelected(!isSelected)}
/>
)}
/>
</Card>
Expand All @@ -92,50 +123,50 @@ const CardExample = () => {
onPress={() => {
Alert.alert('The Chameleon is Pressed');
}}
mode={mode}
mode={selectedMode}
>
<Card.Cover source={require('../../assets/images/chameleon.jpg')} />
<Card.Title title="Pressable Chameleon" />
<Card.Content>
<Paragraph>
<TextComponent variant="bodyMedium">
This is a pressable chameleon. If you press me, I will alert.
</Paragraph>
</TextComponent>
</Card.Content>
</Card>
<Card
style={styles.card}
onLongPress={() => {
Alert.alert('The City is Long Pressed');
}}
mode={mode}
mode={selectedMode}
>
<Card.Cover source={require('../../assets/images/city.jpg')} />
<Card.Title
title="Long Pressable City"
left={(props) => <Avatar.Icon {...props} icon="city" />}
/>
<Card.Content>
<Paragraph>
<TextComponent variant="bodyMedium">
This is a long press only city. If you long press me, I will
alert.
</Paragraph>
</TextComponent>
</Card.Content>
</Card>
<Card
style={styles.card}
onPress={() => {
preferences.toggleTheme();
}}
mode={mode}
mode={selectedMode}
>
<Card.Title
title="Pressable Theme Change"
left={(props) => <Avatar.Icon {...props} icon="format-paint" />}
/>
<Card.Content>
<Paragraph>
<TextComponent variant="bodyMedium">
This is pressable card. If you press me, I will switch the theme.
</Paragraph>
</TextComponent>
</Card.Content>
</Card>
</ScrollView>
Expand All @@ -155,10 +186,12 @@ const styles = StyleSheet.create({
card: {
margin: 4,
},
chip: {
margin: 4,
},
preference: {
alignItems: 'center',
flexDirection: 'row',
justifyContent: 'space-between',
paddingVertical: 12,
paddingHorizontal: 8,
},
Expand Down
70 changes: 54 additions & 16 deletions src/components/Card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import {
View,
ViewStyle,
} from 'react-native';
import color from 'color';
import { white, black } from '../../styles/themes/v2/colors';
import CardContent from './CardContent';
import CardActions from './CardActions';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand All @@ -18,6 +16,7 @@ import CardTitle, { CardTitle as _CardTitle } from './CardTitle';
import Surface from '../Surface';
import { withTheme } from '../../core/theming';
import type { Theme } from '../../types';
import { getCardColors } from './helpers';

type OutlinedCardProps = {
mode: 'outlined';
Expand All @@ -29,8 +28,15 @@ type ElevatedCardProps = {
elevation?: number;
};

type FilledCardProps = {
mode?: 'filled';
elevation?: never;
};

type HandlePressType = 'in' | 'out';

type Mode = 'elevated' | 'outlined' | 'filled';

type Props = React.ComponentProps<typeof Surface> & {
/**
* Changes Card shadow and background on iOS and Android.
Expand All @@ -47,9 +53,10 @@ type Props = React.ComponentProps<typeof Surface> & {
/**
* Mode of the Card.
* - `elevated` - Card with elevation.
* - `filled` - Card with without outline and elevation @supported Available in v3.x with theme version 3
* - `outlined` - Card with an outline.
*/
mode?: 'elevated' | 'outlined';
mode?: Mode;
/**
* Content of the `Card`.
*/
Expand Down Expand Up @@ -113,7 +120,14 @@ const Card = ({
testID,
accessible,
...rest
}: (OutlinedCardProps | ElevatedCardProps) & Props) => {
}: (OutlinedCardProps | ElevatedCardProps | FilledCardProps) & Props) => {
const isMode = React.useCallback(
(modeToCompare: Mode) => {
return cardMode === modeToCompare;
},
[cardMode]
);

// Default animated value
const { current: elevation } = React.useRef<Animated.Value>(
new Animated.Value(cardElevation)
Expand Down Expand Up @@ -185,30 +199,48 @@ const Card = ({
? (child.type as any).displayName
: null
);
const borderColor = color(dark ? white : black)
.alpha(0.12)
.rgb()
.string();
const computedElevation =
dark && isAdaptiveMode ? elevationDarkAdaptive : elevation;

const { backgroundColor, borderColor } = getCardColors({
theme,
mode: cardMode,
isAdaptiveMode,
elevation,
});

return (
<Surface
style={[
{
borderRadius: roundness,
borderColor,
},
!isV3 && {
elevation: computedElevation as unknown as number,
backgroundColor: backgroundColor as unknown as string,
},
cardMode === 'outlined' ? styles.outlined : {},
!isV3 && isMode('outlined')
? styles.resetElevation
: {
elevation: computedElevation as unknown as number,
},
style,
]}
theme={theme}
{...(isV3 && { elevation: computedElevation })}
{...(isV3 && {
elevation: isMode('elevated') ? computedElevation : 0,
})}
{...rest}
>
{isMode('outlined') && (
<View
pointerEvents="none"
style={[
{
borderRadius: roundness,
borderColor,
},
styles.outline,
]}
/>
)}
<TouchableWithoutFeedback
delayPressIn={0}
disabled={!(onPress || onLongPress)}
Expand Down Expand Up @@ -249,9 +281,15 @@ const styles = StyleSheet.create({
flexGrow: 1,
flexShrink: 1,
},
outlined: {
elevation: 0,
outline: {
borderWidth: 1,
position: 'absolute',
width: '100%',
height: '100%',
zIndex: 2,
},
resetElevation: {
elevation: 0,
},
});

Expand Down
Loading

0 comments on commit 8d3e7a2

Please sign in to comment.