Skip to content

Commit

Permalink
refactor(swap): expandable card (#2669)
Browse files Browse the repository at this point in the history
  • Loading branch information
stackchain authored Sep 8, 2023
2 parents fcb290c + e11cc85 commit a7aa5cd
Show file tree
Hide file tree
Showing 10 changed files with 453 additions and 466 deletions.
2 changes: 1 addition & 1 deletion apps/wallet-mobile/.storybook/storybook.requires.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ import {Modal as RNModal, Platform, StyleSheet, Text, TouchableOpacity, View, Vi
import {Icon} from '../Icon'
import {Spacer} from '../Spacer'

export type BottomSheetState = {
openId: string | null
title: string
content?: React.ReactNode
}

type BottomSheetModalProps = {
title: string
isOpen: boolean
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import {action} from '@storybook/addon-actions'
import {storiesOf} from '@storybook/react-native'
import React from 'react'
import {StyleSheet, Text, View} from 'react-native'

import {Icon} from '../Icon'
import {Spacer} from '../Spacer'
import {ExpandableInfoCard, Footer, HeaderWrapper, HiddenInfoWrapper, MainInfoWrapper} from './ExpandableInfoCard'

const styles = StyleSheet.create({
container: {
flex: 1,
padding: 16,
},
})
storiesOf('Expandable Info Card', module)
.addDecorator((story) => <View style={styles.container}>{story()}</View>)
.add('with Box Shadow', () => {
const [hiddenInfoOpenId, setHiddenInfoOpenId] = React.useState<string | null>(null)

const extended = hiddenInfoOpenId === '1234'

return (
<ExpandableInfoCard
adornment={<HiddenInfo id="1234" setBottomSheetState={() => null} />}
extended={extended}
header={
<Header
assetFromLabel="ADA"
assetToLabel="DOGE"
extended={extended}
onPress={() => setHiddenInfoOpenId(hiddenInfoOpenId !== '1234' ? '1234' : null)}
/>
}
footer={
<Footer onPress={() => action('footer clicked')}>
<Text>FOOTER LABEL</Text>
</Footer>
}
withBoxShadow
>
<MainInfo />
</ExpandableInfoCard>
)
})
.add('without Box Shadow', () => {
const [hiddenInfoOpenId, setHiddenInfoOpenId] = React.useState<string | null>(null)

const extended = hiddenInfoOpenId === '1234'

return (
<ExpandableInfoCard
adornment={<HiddenInfo id="1234" setBottomSheetState={() => null} />}
extended={extended}
header={
<Header
assetFromLabel="ADA"
assetToLabel="DOGE"
extended={extended}
onPress={() => setHiddenInfoOpenId(hiddenInfoOpenId !== '1234' ? '1234' : null)}
/>
}
footer={
<Footer onPress={() => action('footer clicked')}>
<Text>FOOTER LABEL</Text>
</Footer>
}
>
<MainInfo />
</ExpandableInfoCard>
)
})

const Header = ({
assetFromLabel,
assetToLabel,
extended,
onPress,
}: {
assetFromLabel: string
assetToLabel: string
extended: boolean
onPress: () => void
}) => {
return (
<HeaderWrapper extended={extended} onPress={onPress}>
<View style={{flexDirection: 'row', alignItems: 'center'}}>
<Icon.YoroiNightly size={24} />

<Spacer width={4} />

<Text>{assetFromLabel}</Text>

<Text>/</Text>

<Spacer width={4} />

<Icon.Assets size={24} />

<Spacer width={4} />

<Text>{assetToLabel}</Text>
</View>
</HeaderWrapper>
)
}

const HiddenInfo = ({id, setBottomSheetState}) => {
return (
<View>
{[
{
label: 'Min ADA',
value: '2 ADA',
info: 'Fake content',
},
{
label: 'Min Received',
value: '2.99 USDA',
info: 'Fake content',
},
{
label: 'Fees',
value: '2 ADA',
info: 'Fake content',
},
].map((item) => (
<HiddenInfoWrapper
key={item.label}
value={item.value}
label={item.label}
onPress={() => {
setBottomSheetState({
openId: id,
title: item.label,
content: item.info,
})
}}
/>
))}
</View>
)
}

const MainInfo = () => {
return (
<View>
{[
{label: 'Token price', value: '3 ADA'},
{label: 'Token amount', value: '3 USDA'},
].map((item, index) => (
<MainInfoWrapper key={index} label={item.label} value={item.value} isLast={index === 1} />
))}
</View>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,90 +3,80 @@ import {StyleSheet, Text, View} from 'react-native'
import {TouchableOpacity} from 'react-native-gesture-handler'
import SkeletonPlaceholder from 'react-native-skeleton-placeholder'

import {Icon, Spacer} from '../../../../../components'
import {BottomSheetModal} from '../../../../../components/BottomSheetModal'
import {COLORS} from '../../../../../theme'

export type BottomSheetState = {
openId: string | null
title: string
content?: React.ReactNode
}
import {COLORS} from '../../theme'
import {Icon} from '../Icon'
import {Spacer} from '../Spacer'

export type ExpandableInfoCardProps = {
id: string
label: React.ReactNode | null
mainInfo: React.ReactNode
hiddenInfo: React.ReactNode
navigateTo?: () => void
onPress?: () => void
buttonLabel?: string
adornment: React.ReactNode
extended: boolean
children: React.ReactNode
header: React.ReactNode
footer?: React.ReactNode
withBoxShadow?: boolean
hiddenInfoOpenId: string | null
setHiddenInfoOpenId: (hiddenInfoOpenId: string | null) => void
bottomSheetState: BottomSheetState
setBottomSheetState: (state: BottomSheetState) => void
}

export const ExpandableInfoCard = ({
id,
label,
mainInfo,
hiddenInfo,
navigateTo,
buttonLabel,
onPress,
withBoxShadow,
hiddenInfoOpenId,
setHiddenInfoOpenId,
setBottomSheetState,
bottomSheetState,
children,
extended,
adornment,
header,
withBoxShadow = false,
footer = null,
}: ExpandableInfoCardProps) => {
return (
<View>
<Spacer height={8} />

<View style={[styles.container, withBoxShadow && styles.shadowProp]}>
<View style={styles.flexBetween}>
<TouchableOpacity onPress={() => navigateTo?.()}>
<Text style={[styles.label]}>{label}</Text>
</TouchableOpacity>

<TouchableOpacity onPress={() => setHiddenInfoOpenId(hiddenInfoOpenId !== id ? id : null)}>
{hiddenInfoOpenId === id ? (
<Icon.Chevron direction="up" size={24} />
) : (
<Icon.Chevron direction="down" size={24} />
)}
</TouchableOpacity>
</View>
{header}

<Spacer height={8} />

{children}

<Spacer height={8} />

{mainInfo}
{extended && adornment}

{hiddenInfoOpenId === id && hiddenInfo}
{footer}

{buttonLabel != null && (
<TouchableOpacity style={styles.button} onPress={onPress && onPress}>
<Text style={styles.buttonLabel}>{buttonLabel}</Text>
</TouchableOpacity>
)}
<Spacer height={8} />
</View>

<Spacer height={16} />

<BottomSheetModal
isOpen={bottomSheetState.openId === id}
title={bottomSheetState.title}
onClose={() => {
setBottomSheetState({openId: null, title: '', content: ''})
}}
>
<Text style={styles.text}>{bottomSheetState.content}</Text>
</BottomSheetModal>
<Spacer height={8} />
</View>
)
}

export const HeaderWrapper = ({
children,
extended,
onPress,
}: {
children: React.ReactNode
extended: boolean
onPress: () => void
}) => {
return (
<View style={styles.flexBetween}>
{children}

<TouchableOpacity onPress={onPress}>
{extended ? <Icon.Chevron direction="up" size={24} /> : <Icon.Chevron direction="down" size={24} />}
</TouchableOpacity>
</View>
)
}

export const Footer = ({children, onPress}: {children: React.ReactNode; onPress: () => void}) => {
return (
<TouchableOpacity onPress={onPress}>
<Text style={styles.buttonLabel}>{children}</Text>
</TouchableOpacity>
)
}

export const HiddenInfoWrapper = ({
label,
info,
Expand All @@ -95,13 +85,11 @@ export const HiddenInfoWrapper = ({
}: {
label: string
info?: React.ReactNode
onPress
onPress?: () => void
value: React.ReactNode
}) => {
return (
<View>
<Spacer height={8} />

<View style={styles.flexBetween}>
<View style={styles.flex}>
<Text style={[styles.text, styles.gray]}>{label}</Text>
Expand All @@ -117,6 +105,8 @@ export const HiddenInfoWrapper = ({

{typeof value === 'string' ? <Text style={styles.text}>{value}</Text> : value}
</View>

<Spacer height={8} />
</View>
)
}
Expand Down Expand Up @@ -171,11 +161,6 @@ const styles = StyleSheet.create({
justifyContent: 'space-between',
alignItems: 'center',
},
label: {
color: COLORS.SHELLEY_BLUE,
fontWeight: '500',
fontSize: 16,
},
flex: {
flexDirection: 'row',
alignItems: 'center',
Expand All @@ -188,10 +173,10 @@ const styles = StyleSheet.create({
color: '#242838',
},
gray: {
color: COLORS.GRAY,
},
button: {
width: 111,
color: '#6B7384',
fontFamily: 'Rubik',
fontSize: 16,
fontWeight: '400',
},
buttonLabel: {
fontSize: 14,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './ExpandableInfoCard'
1 change: 1 addition & 0 deletions apps/wallet-mobile/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export * from './Checkbox'
export * from './CopyButton'
export * from './DangerousActionModal'
export * from './ErrorModal'
export * from './ExpandableInfoCard'
export * from './FadeIn'
export * from './FadeOut'
export * from './Hr'
Expand Down
Loading

0 comments on commit a7aa5cd

Please sign in to comment.