Skip to content
Merged
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
140 changes: 70 additions & 70 deletions assets/figma/variables.json

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions src/components/molecules/Field/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ const layoutPropsKeys = [
export const Input = forwardRef<Partial<TextInput>, FieldInputProps>(
(
{
isRequired,
errorMessage,
helperText,
isInvalid,
isRequired,
label,
helperText,
errorMessage,
onFocus,
onBlur,
labelStyle,
onBlur,
onFocus,
...props
},
ref
Expand Down Expand Up @@ -90,13 +90,13 @@ export const Input = forwardRef<Partial<TextInput>, FieldInputProps>(
return (
<Box {...layoutProps} width="100%" mb="2">
<Pressable onPress={handleFocus}>
<FormLabel label={label} isRequired={isRequired} labelStyle={labelStyle} />
<FormLabel {...{ isRequired, label, labelStyle }} />
<BaseInput
isInvalid={isInvalid || Boolean(errorMessage)}
{...inputProps}
ref={_inputRef}
/>
<FormErrorMessage errorMessage={errorMessage} />
<FormErrorMessage {...{ errorMessage }} />
</Pressable>
</Box>
)
Expand Down
65 changes: 32 additions & 33 deletions src/components/organisms/Menu/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { AbsoluteFullFill, Box, TouchableProps, ScrollView } from '@baca/design-system/components'
import { Box, TouchableProps, ScrollView, Pressable } from '@baca/design-system/components'
import { useRef, useState, useMemo, useTheme, useCallback } from '@baca/hooks'
import { Portal } from '@gorhom/portal'
import React, { NamedExoticComponent, PropsWithChildren, memo } from 'react'
import { View, Modal, TouchableWithoutFeedback } from 'react-native'
import { View, Modal } from 'react-native'

import { MenuItem } from '../../molecules/MenuItem'

Expand Down Expand Up @@ -120,37 +120,36 @@ const Menu = memo<MenuProps>(
visible={isOpen}
onRequestClose={handleClose}
>
<TouchableWithoutFeedback onPress={handleClose}>
<AbsoluteFullFill backgroundColor="bg.active" bgOpacity={0.1} />
</TouchableWithoutFeedback>
{triggerPosition && (
<Box
position="absolute"
top={triggerPosition?.y}
left={triggerPosition?.x}
p={2}
backgroundColor="fg.white"
borderRadius={4}
{...shadows['4']}
>
<ScrollView scrollEnabled={scrollable}>
{React.Children.map(props.children, (child) => {
if (React.isValidElement(child)) {
return React.cloneElement(child, {
...child.props,
onPress: () => {
if (closeOnSelect) {
handleClose()
}
child.props.onPress?.()
},
})
}
return child
})}
</ScrollView>
</Box>
)}
<Pressable onPress={handleClose} flex={1} bg="Base.black" bgOpacity={0.1}>
{triggerPosition && (
<Box
position="absolute"
top={triggerPosition?.y}
left={triggerPosition?.x}
p={2}
backgroundColor="bg.primary"
borderRadius={4}
{...shadows['4']}
>
<ScrollView scrollEnabled={scrollable}>
{React.Children.map(props.children, (child) => {
if (React.isValidElement(child)) {
return React.cloneElement(child, {
...child.props,
onPress: () => {
if (closeOnSelect) {
handleClose()
}
child.props.onPress?.()
},
})
}
return child
})}
</ScrollView>
</Box>
)}
</Pressable>
</Modal>
</Portal>
</>
Expand Down
30 changes: 30 additions & 0 deletions src/design-system/components/BoxWithShadow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { FC, PropsWithChildren, useMemo } from 'react'

import { Box, BoxProps } from './Box'
import { theme } from '../config'

const { errorShadow, focusShadow } = theme.light.shadows

type BoxWithShadowProps = {
isInvalid?: boolean
isFocused?: boolean
} & BoxProps

export const BoxWithShadow: FC<PropsWithChildren<BoxWithShadowProps>> = ({
children,
isInvalid,
isFocused,
style,
...rest
}) => {
const shadowProps = useMemo(
() => (isInvalid ? errorShadow : isFocused ? focusShadow : {}),
[isInvalid, isFocused]
)

return (
<Box borderRadius={8} style={[style, shadowProps]} {...rest}>
{children}
</Box>
)
}
4 changes: 2 additions & 2 deletions src/design-system/components/Button/Button.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ describe('Button', () => {
const { getByTestId } = render(<Button.SecondaryColor title="Button" />)
expect(getByTestId('baseButton').props.style).toStrictEqual({
...baseStyles,
backgroundColor: theme.light.colors.button.secondary.bg,
borderColor: theme.light.colors.button.secondary.border,
backgroundColor: theme.light.colors.button.secondary.color.bg,
borderColor: theme.light.colors.button.secondary.color.border,
borderWidth: 1,
})
})
Expand Down
27 changes: 25 additions & 2 deletions src/design-system/components/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,17 @@ import {
TextStyle,
StyleProp,
View,
Platform,
} from 'react-native'

import { ButtonSize, ButtonVariant, buttonSizeVariants, buttonVariants, theme } from '../../config'
import {
ButtonSize,
ButtonVariant,
buttonSizeVariants,
buttonVariants,
getButtonShadowStyle,
theme,
} from '../../config'
import { generateStyledComponent } from '../../utils'
import { Box } from '../Box'
import { Loader } from '../Loader'
Expand Down Expand Up @@ -81,6 +89,10 @@ const RawButton = memo(
[variant]
)

const pressedStyles = useMemo<ViewStyle>(() => {
return getButtonShadowStyle({ variant })
}, [variant])

const hoveredStyles = useMemo<ViewStyle>(
() => ({
backgroundColor: getColorValue({
Expand Down Expand Up @@ -184,7 +196,17 @@ const RawButton = memo(
({ pressed }: PressableStateCallbackType): StyleProp<ViewStyle> =>
StyleSheet.flatten<ViewStyle>([
styles.baseButton,
pressed || isHovered ? hoveredStyles : defaultStyles,
{
...Platform.select({
default:
pressed || isHovered ? { ...hoveredStyles, ...pressedStyles } : defaultStyles,
web: pressed
? { ...defaultStyles, ...pressedStyles }
: isHovered
? hoveredStyles
: defaultStyles,
}),
},
disabled && disabledStyles,
loading && disabledStyles,
buttonSizeStyle,
Expand All @@ -198,6 +220,7 @@ const RawButton = memo(
hoveredStyles,
isHovered,
loading,
pressedStyles,
style,
]
)
Expand Down
83 changes: 51 additions & 32 deletions src/design-system/components/Checkbox.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { useTheme } from '@baca/hooks'
import { forwardRef, useCallback, useMemo } from 'react'
import { View, Pressable, StyleSheet } from 'react-native'

Expand All @@ -7,76 +6,96 @@ import { Icon } from './Icon'
import { Text } from './Text'
import { CheckboxProps } from './types'

const hitSlop = {
top: 5,
left: 5,
bottom: 5,
}

const checkboxSizes = {
sm: {
boxSize: 16,
iconSize: 12,
},
md: {
boxSize: 20,
iconSize: 14,
},
} as const

export const Checkbox = forwardRef<View, CheckboxProps>(
(
{
disabled,
value,
onChange,
checkboxes,
checkboxText,
size = 22,
isError,
disabled,
isChecked,
checkboxes,
isError,
onChange,
size = 'sm',
value,
...props
},
ref
) => {
const { colors } = useTheme()
const checkboxSize = useMemo(() => checkboxSizes[size], [size])

const handleValueChange = useCallback(() => {
return checkboxes ? onChange(value) : onChange(!value)
}, [onChange, value, checkboxes])

const iconColor = useMemo(() => {
const iconColor = useMemo<ColorNames>(() => {
if (disabled && value) {
return 'icon.fg.brand'
return 'fg.disabled_subtle'
}

return 'text.primary'
return 'fg.white'
}, [disabled, value])

const bgColor = useMemo(() => {
const bgColor = useMemo<ColorNames>(() => {
if (!value) {
return colors.text.white
return 'fg.white'
}
if (disabled) {
return colors.text.placeholder
return 'bg.disabled_subtle'
}

return colors.alpha.black[10]
}, [disabled, value, colors])
return 'bg.brand.solid'
}, [disabled, value])

const borderColor = useMemo(
() => (isError ? 'border.error' : disabled ? 'border.disabled' : 'border.primary'),
[isError, disabled]
const borderColor = useMemo<ColorNames>(
() =>
disabled
? 'border.disabled'
: isError
? 'border.error'
: value
? 'bg.brand.solid'
: 'border.primary',
[value, isError, disabled]
)

return (
<Pressable
ref={ref}
{...{ disabled, hitSlop, ref }}
onPress={handleValueChange}
hitSlop={{
top: 5,
left: 5,
bottom: 5,
}}
style={styles.mainContainer}
disabled={disabled}
>
<View style={styles.row}>
<Box
style={[
styles.checkbox,
{
backgroundColor: bgColor,
height: size,
width: size,
height: checkboxSize.boxSize,
width: checkboxSize.boxSize,
},
]}
borderColor={borderColor}
{...props}
bg={bgColor}
{...{ ...props, borderColor }}
>
{isChecked ? <Icon color={iconColor} name="check-line" size={18} /> : null}
{isChecked ? (
<Icon color={iconColor} name="check-line" size={checkboxSize.iconSize} />
) : null}
</Box>
<Text>{checkboxText}</Text>
</View>
Expand Down
8 changes: 5 additions & 3 deletions src/design-system/components/FormLabel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ export const FormLabel = ({ label, isRequired, labelStyle }: FormLabelProps) =>
return (
<View style={[styles.wrapper, { ...(label && styles.wrapperWithLabel) }]}>
{label && (
<Text style={[labelStyle, { color: labelStyle?.color || colors.text.brand.primary }]}>
<Text.SmMedium style={[labelStyle, { color: labelStyle?.color || colors.text.secondary }]}>
{label}
{isRequired && (
<Text style={[stylesForRequired, { color: colors.text.error.primary }]}>*</Text>
<Text.SmMedium style={[stylesForRequired, { color: colors.text.error.primary }]}>
*
</Text.SmMedium>
)}
</Text>
</Text.SmMedium>
)}
</View>
)
Expand Down
Loading