Skip to content

Commit

Permalink
design feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
onghwan committed Feb 10, 2025
1 parent cfe1ce4 commit 2538c1d
Show file tree
Hide file tree
Showing 10 changed files with 255 additions and 24 deletions.
3 changes: 3 additions & 0 deletions packages/k2-alpine/src/assets/icons/arrow_down.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions packages/k2-alpine/src/components/Button/Button.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ScrollView, Text, View } from '../Primitives'
import Link from '../../utils/Link'
import { useTheme } from '../..'
import { Button, ButtonSize, ButtonType } from './Button'
import { FilterButton } from './FilterButton'

export default {
title: 'Button'
Expand Down Expand Up @@ -103,6 +104,13 @@ export const All = (): JSX.Element => {
}}>
disabled
</Button>
<View
style={{
marginTop: 20,
flexDirection: 'row'
}}>
<FilterButton title={'Most tradable'} />
</View>
<View style={{ height: 160 }} />
</ScrollView>
</BackgroundComponent>
Expand Down
20 changes: 15 additions & 5 deletions packages/k2-alpine/src/components/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,21 @@ export type ButtonSize = 'small' | 'medium' | 'large'

type ButtonIconType = 'check' | 'expandMore' | 'google' | 'apple'

const BUTTON_ICON_TYPES = ['check', 'expandMore', 'google', 'apple'] as const

const isButtonIconType = (value: unknown): value is ButtonIconType => {
return (BUTTON_ICON_TYPES as readonly string[]).includes(value as string)
}

interface ButtonProps {
onPress?: () => void
disabled?: boolean
style?: StyleProp<ViewStyle>
testID?: string
type: ButtonType
size: ButtonSize
leftIcon?: ButtonIconType
rightIcon?: ButtonIconType
leftIcon?: ButtonIconType | JSX.Element
rightIcon?: ButtonIconType | JSX.Element
}

export const Button = forwardRef<
Expand Down Expand Up @@ -104,7 +110,9 @@ export const Button = forwardRef<
alignItems: 'center',
...sizeStyles[size]
}}>
{leftIcon
{React.isValidElement(leftIcon)
? leftIcon
: isButtonIconType(leftIcon)
? getIcon(leftIcon, {
width: iconWidth,
height: iconWidth,
Expand All @@ -122,7 +130,9 @@ export const Button = forwardRef<
}}>
{children}
</Text>
{rightIcon
{React.isValidElement(rightIcon)
? rightIcon
: isButtonIconType(rightIcon)
? getIcon(rightIcon, {
width: iconWidth,
height: iconWidth,
Expand Down Expand Up @@ -202,7 +212,7 @@ const getBackgroundColor = (
}
}

const getTintColor = (
export const getTintColor = (
type: ButtonType,
theme: K2AlpineTheme,
disabled: boolean | undefined
Expand Down
33 changes: 33 additions & 0 deletions packages/k2-alpine/src/components/Button/FilterButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from 'react'
import { ViewStyle } from 'react-native'
import { Icons } from '../../theme/tokens/Icons'
import { useTheme } from '../../hooks'
import { Button, getTintColor } from './Button'

export const FilterButton = ({
title,
style,
disabled,
onPress
}: {
title: string
style?: ViewStyle
disabled?: boolean
onPress?: () => void
}): JSX.Element => {
const { theme } = useTheme()
const tintColor = getTintColor('secondary', theme, disabled)

return (
<Button
style={style}
size="small"
type="secondary"
onPress={onPress}
rightIcon={
<Icons.Custom.ArrowDown style={{ marginLeft: 5 }} color={tintColor} />
}>
{title}
</Button>
)
}
35 changes: 35 additions & 0 deletions packages/k2-alpine/src/components/Dropdown/DropdownBackground.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { BlurView } from 'expo-blur'
import React from 'react'
import { Platform } from 'react-native'
import { View } from '../Primitives'
import { useTheme } from '../../hooks'
import { colors } from '../../theme/tokens/colors'

export const DropdownBackground = ({
children
}: {
children: React.ReactNode
}): JSX.Element => {
const { theme } = useTheme()

return Platform.OS === 'ios' ? (
<BlurView
tint={'default'}
style={{
minWidth: 240
}}
intensity={100}
experimentalBlurMethod="dimezisBlurView">
{children}
</BlurView>
) : (
<View
sx={{
backgroundColor: theme.isDark
? colors.$neutral950
: colors.$neutralWhite
}}>
{children}
</View>
)
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import React, { useState } from 'react'
import React, { useRef, useState } from 'react'
import { TouchableOpacity } from 'react-native'
import { Rect } from 'react-native-popover-view'
import { ScrollView, Text, View } from '../Primitives'
import { Button } from '../Button/Button'
import { showAlert } from '../Alert/Alert'
import { IndexPath, SimpleDropdown } from './SimpleDropdown'
import { usePopoverAnchor } from './usePopoverAnchor'

export default {
title: 'Dropdown'
Expand All @@ -20,6 +23,8 @@ export const All = (): JSX.Element => {
<SingleSectionMultipleSelectionDropdown />
<MultipleSectionSingleSelectionDropdown />
<MultipleSectionMultipleSelectionDropdown />
<LeftAlignedDropdown />
<RightAlignedDropdown />
</View>
</ScrollView>
)
Expand Down Expand Up @@ -178,3 +183,89 @@ const MultipleSectionMultipleSelectionDropdown = (): JSX.Element => {
</View>
)
}

const LeftAlignedDropdown = (): JSX.Element => {
const sections = [
['All networks', 'Avalanche C-Chain', 'Bitcoin network', 'Ethereum']
]
const [selectedRow, setSelectedRow] = useState<IndexPath>({
section: 0,
row: 0
})
const sourceRef = useRef<TouchableOpacity>(null)

const { anchorRect, isPopoverVisible, onShowPopover, onHidePopover } =
usePopoverAnchor(sourceRef)

return (
<View
style={{
gap: 12
}}>
<Text>Left aligned</Text>
<Button
ref={sourceRef}
type="primary"
size="medium"
onPress={onShowPopover}>
{sections[selectedRow.section]?.[selectedRow.row]}
</Button>
<SimpleDropdown
from={
anchorRect
? new Rect(anchorRect.x, anchorRect.y, 0, anchorRect.height)
: undefined
}
isVisible={isPopoverVisible}
offset={10}
sections={sections}
selectedRows={[selectedRow]}
onSelectRow={indexPath => setSelectedRow(indexPath)}
onRequestClose={onHidePopover}
/>
</View>
)
}

const RightAlignedDropdown = (): JSX.Element => {
const sections = [
['All networks', 'Avalanche C-Chain', 'Bitcoin network', 'Ethereum']
]
const [selectedRow, setSelectedRow] = useState<IndexPath>({
section: 0,
row: 0
})
const sourceRef = useRef<TouchableOpacity>(null)

const { anchorRect, isPopoverVisible, onShowPopover, onHidePopover } =
usePopoverAnchor(sourceRef)

return (
<View
style={{
gap: 12
}}>
<Text>Right aligned</Text>
<Button
ref={sourceRef}
type="primary"
size="medium"
onPress={onShowPopover}>
{sections[selectedRow.section]?.[selectedRow.row]}
</Button>
<SimpleDropdown
from={
anchorRect
? new Rect(anchorRect.width, anchorRect.y, 0, anchorRect.height)
: undefined
}
isVisible={isPopoverVisible}
offset={10}
sections={sections}
selectedRows={[selectedRow]}
onSelectRow={indexPath => setSelectedRow(indexPath)}
onRequestClose={onHidePopover}
/>
</View>
)
}
38 changes: 22 additions & 16 deletions packages/k2-alpine/src/components/Dropdown/SimpleDropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React, { useRef } from 'react'
import Popover from 'react-native-popover-view'
import { BlurView } from 'expo-blur'
import Popover, { Rect } from 'react-native-popover-view'
import { Platform } from 'react-native'
import { Text, View, TouchableOpacity } from '../Primitives'
import { useTheme } from '../../hooks'
import { Separator } from '../Separator/Separator'
import { Icons } from '../../theme/tokens/Icons'
import { DropdownBackground } from './DropdownBackground'

export const SimpleDropdown = <T extends { toString(): string }>({
from,
Expand All @@ -13,15 +14,19 @@ export const SimpleDropdown = <T extends { toString(): string }>({
offset = 0,
allowsMultipleSelection = false,
onSelectRow,
onDeselectRow
onDeselectRow,
onRequestClose,
isVisible
}: {
from: React.ReactNode
from: React.ReactNode | Rect
sections: T[][]
selectedRows: IndexPath[]
allowsMultipleSelection?: boolean
offset?: number
onSelectRow: (indexPath: IndexPath) => void
onDeselectRow?: (indexPath: IndexPath) => void
onRequestClose?: () => void
isVisible?: boolean
}): JSX.Element => {
const { theme } = useTheme()
const popoverRef = useRef<Popover>()
Expand All @@ -48,28 +53,28 @@ export const SimpleDropdown = <T extends { toString(): string }>({
)
}

const groupSeparatorHeight = Platform.OS === 'ios' ? 6 : 1
const backgroundBorderRadius = Platform.OS === 'ios' ? 10 : 4

return (
<Popover
// @ts-expect-error
ref={popoverRef}
from={from}
isVisible={isVisible}
offset={offset}
onRequestClose={onRequestClose}
popoverStyle={{
borderRadius: 10,
borderRadius: backgroundBorderRadius,
shadowOffset: { width: 0, height: 15 },
shadowRadius: 30,
shadowOpacity: 0.3,
backgroundColor: 'transparent'
backgroundColor: 'transparent',
minWidth: 200
}}
arrowSize={{ width: -10, height: 0 }}
backgroundStyle={{ backgroundColor: 'transparent' }}>
<BlurView
tint={'default'}
style={{
minWidth: 240
}}
intensity={100}
experimentalBlurMethod="dimezisBlurView">
<DropdownBackground>
{sections.map((section, sectionIndex) => {
return (
<View key={sectionIndex}>
Expand Down Expand Up @@ -107,22 +112,23 @@ export const SimpleDropdown = <T extends { toString(): string }>({
)}
</View>
</TouchableOpacity>
{rowIndex !== section.length - 1 && <Separator />}
{rowIndex !== section.length - 1 &&
Platform.OS === 'ios' && <Separator />}
</View>
)
})}
{sectionIndex !== sections.length - 1 && (
<View
sx={{
height: 6,
height: groupSeparatorHeight,
backgroundColor: theme.colors.$borderPrimary
}}
/>
)}
</View>
)
})}
</BlurView>
</DropdownBackground>
</Popover>
)
}
Expand Down
Loading

0 comments on commit 2538c1d

Please sign in to comment.