diff --git a/.eslintrc.js b/.eslintrc.js index 8616af42..52944b83 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -42,24 +42,49 @@ module.exports = { 2, { skip: [ - 'Text.H1', - 'Text.H1Bold', - 'Text.H2', - 'Text.H2Bold', - 'Text.H3', - 'Text.H3Bold', - 'Text.H4', - 'Text.H4Bold', - 'Text.H5', - 'Text.H5Bold', - 'Text.H6', - 'Text.H6Bold', - 'Text.Body', - 'Text.Bold', - 'Text.Caption', - 'Text.CaptionBold', - 'Text.Subtitle', - 'Text.SubtitleBold', + 'Text.LgBold', + 'Text.LgMedium', + 'Text.LgRegular', + 'Text.LgSemibold', + 'Text.MdBold', + 'Text.MdMedium', + 'Text.MdRegular', + 'Text.MdSemibold', + 'Text.SmBold', + 'Text.SmMedium', + 'Text.SmRegular', + 'Text.SmSemibold', + 'Text.XlBold', + 'Text.XlMedium', + 'Text.XlRegular', + 'Text.XlSemibold', + 'Text.XsBold', + 'Text.XsMedium', + 'Text.XsRegular', + 'Text.XsSemibold', + + 'Display', + 'Display.LgBold', + 'Display.LgMedium', + 'Display.LgRegular', + 'Display.LgSemibold', + 'Display.MdBold', + 'Display.MdMedium', + 'Display.MdRegular', + 'Display.MdSemibold', + 'Display.SmBold', + 'Display.SmMedium', + 'Display.SmRegular', + 'Display.SmSemibold', + 'Display.XlBold', + 'Display.XlMedium', + 'Display.XlRegular', + 'Display.XlSemibold', + 'Display.XsBold', + 'Display.XsMedium', + 'Display.XsRegular', + 'Display.XsSemibold', + 'Button', 'Heading', 'Menu.Item', diff --git a/.gitignore b/.gitignore index 87431789..98645798 100644 --- a/.gitignore +++ b/.gitignore @@ -23,10 +23,11 @@ dist/ # project files # CONFIG: uncomment following lines -# .env -# .env.qa -# .env.production -# .env.staging +.env +.env.qa +.env.production +.env.staging +env.json # Local Netlify folder .netlify diff --git a/.vscode/settings.json b/.vscode/settings.json index 70ffdf77..4a67ca0f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,5 @@ { - "cSpell.words": ["icomoon", "notificated", "postsecondary"], + "cSpell.words": ["icomoon", "notificated", "postsecondary", "Touchables"], "todohighlight.keywords": [ { "text": "CONFIG:", diff --git a/assets/fonts/Lato_Black.ttf b/assets/fonts/Lato_Black.ttf deleted file mode 100644 index a4a924f9..00000000 Binary files a/assets/fonts/Lato_Black.ttf and /dev/null differ diff --git a/assets/fonts/Lato_Bold.ttf b/assets/fonts/Lato_Bold.ttf index b63a14d6..1d23c706 100644 Binary files a/assets/fonts/Lato_Bold.ttf and b/assets/fonts/Lato_Bold.ttf differ diff --git a/assets/fonts/Lato_Light.ttf b/assets/fonts/Lato_Light.ttf deleted file mode 100644 index dfa72ce8..00000000 Binary files a/assets/fonts/Lato_Light.ttf and /dev/null differ diff --git a/assets/fonts/Lato_Medium.ttf b/assets/fonts/Lato_Medium.ttf new file mode 100644 index 00000000..0648fb2d Binary files /dev/null and b/assets/fonts/Lato_Medium.ttf differ diff --git a/assets/fonts/Lato_SemiBold.ttf b/assets/fonts/Lato_SemiBold.ttf new file mode 100644 index 00000000..3b1bcccc Binary files /dev/null and b/assets/fonts/Lato_SemiBold.ttf differ diff --git a/assets/fonts/Lato_Thin.ttf b/assets/fonts/Lato_Thin.ttf deleted file mode 100644 index ba58da1a..00000000 Binary files a/assets/fonts/Lato_Thin.ttf and /dev/null differ diff --git a/src/components/AppLoading.tsx b/src/components/AppLoading.tsx index 912abd32..e776ae50 100644 --- a/src/components/AppLoading.tsx +++ b/src/components/AppLoading.tsx @@ -11,11 +11,10 @@ SplashScreen.preventAutoHideAsync() export const AppLoading: FC = ({ children }) => { const isLoadingComplete = useCachedResources() const [fontsLoaded, fontError] = useFonts({ - Lato_100Thin: require('../../assets/fonts/Lato_Thin.ttf'), - Lato_300Light: require('../../assets/fonts/Lato_Light.ttf'), Lato_400Regular: require('../../assets/fonts/Lato_Regular.ttf'), + Lato_500Medium: require('../../assets/fonts/Lato_Medium.ttf'), + Lato_600SemiBold: require('../../assets/fonts/Lato_SemiBold.ttf'), Lato_700Bold: require('../../assets/fonts/Lato_Bold.ttf'), - Lato_900Black: require('../../assets/fonts/Lato_Black.ttf'), IcoMoon: require('../../assets/icomoon/icomoon.ttf'), }) diff --git a/src/components/Header.tsx b/src/components/Header.tsx index fd02683d..0b552871 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -21,9 +21,9 @@ export const Header = ({ options }: NativeStackHeaderProps) => { <> - + {options.title} - + ) : ( diff --git a/src/components/LanguagePicker.tsx b/src/components/LanguagePicker.tsx index 806eabf5..984d0f17 100644 --- a/src/components/LanguagePicker.tsx +++ b/src/components/LanguagePicker.tsx @@ -43,9 +43,7 @@ export const LanguagePicker: React.FC = () => { return ( - - {languages?.[language]?.emoji} - + {languages?.[language]?.emoji} diff --git a/src/design-system/bottomSheets/BottomSheetHeader.tsx b/src/design-system/bottomSheets/BottomSheetHeader.tsx index 2a9b79ec..5cb0cedf 100644 --- a/src/design-system/bottomSheets/BottomSheetHeader.tsx +++ b/src/design-system/bottomSheets/BottomSheetHeader.tsx @@ -22,9 +22,9 @@ export const BottomSheetHeader = ({ return ( - + {title} - + {showCloseButton && ( diff --git a/src/design-system/components/Button/Button.test.tsx b/src/design-system/components/Button/Button.test.tsx index 2ea0c888..433ea986 100644 --- a/src/design-system/components/Button/Button.test.tsx +++ b/src/design-system/components/Button/Button.test.tsx @@ -1,9 +1,17 @@ import { theme } from '@baca/design-system' import { cleanup, render, fireEvent, act } from '@baca/utils/testUtils' -import { StyleSheet } from 'react-native' import { Button } from './Button' +const baseStyles = { + alignItems: 'center', + borderRadius: 4, + flexDirection: 'row', + justifyContent: 'center', + paddingHorizontal: 14, + paddingVertical: 10, +} + afterEach(cleanup) describe('Button', () => { it('renders correctly', () => { @@ -14,80 +22,115 @@ describe('Button', () => { it('renders correctly Button.Primary', () => { const { getByTestId } = render() expect(getByTestId('baseButton').props.style).toStrictEqual({ + ...baseStyles, alignItems: 'center', backgroundColor: theme.light.colors.button.primary.bg, - borderColor: 'transparent', - borderRadius: 4, - borderWidth: undefined, - flexDirection: 'row', - justifyContent: 'center', - minWidth: 128, - paddingHorizontal: 24, - paddingVertical: 8, + borderColor: theme.light.colors.button.primary.border, + borderWidth: 1, + }) + }) + + it('renders correctly Button.PrimaryDestructive', () => { + const { getByTestId } = render() + expect(getByTestId('baseButton').props.style).toStrictEqual({ + ...baseStyles, + alignItems: 'center', + backgroundColor: theme.light.colors.button.primary.error.bg, + borderColor: theme.light.colors.button.primary.error.border, + borderWidth: 1, }) }) - it('renders correctly Button.Secondary', () => { - const { getByTestId } = render() + it('renders correctly Button.SecondaryColor', () => { + const { getByTestId } = render() expect(getByTestId('baseButton').props.style).toStrictEqual({ + ...baseStyles, alignItems: 'center', backgroundColor: theme.light.colors.button.secondary.bg, - borderColor: 'transparent', - borderRadius: 4, - borderWidth: undefined, - flexDirection: 'row', - justifyContent: 'center', - minWidth: 128, - paddingHorizontal: 24, - paddingVertical: 8, + borderColor: theme.light.colors.button.secondary.border, + borderWidth: 1, }) }) - it('renders correctly Button.Outline', () => { - const { getByTestId } = render() + it('renders correctly Button.SecondaryGray', () => { + const { getByTestId } = render() expect(getByTestId('baseButton').props.style).toStrictEqual({ + ...baseStyles, alignItems: 'center', - backgroundColor: theme.light.colors.button.tertiary.fg, - borderColor: theme.light.colors.border.primary, - borderRadius: 4, - borderWidth: StyleSheet.hairlineWidth, - flexDirection: 'row', - justifyContent: 'center', - minWidth: 128, - paddingHorizontal: 24, - paddingVertical: 8, + backgroundColor: theme.light.colors.button.secondary.bg, + borderColor: theme.light.colors.button.secondary.border, + borderWidth: 1, }) }) - it('renders correctly Button.Ghost', () => { - const { getByTestId } = render() + it('renders correctly Button.SecondaryDestructive', () => { + const { getByTestId } = render() expect(getByTestId('baseButton').props.style).toStrictEqual({ + ...baseStyles, alignItems: 'center', - backgroundColor: theme.light.colors.button.tertiary.fg, + backgroundColor: theme.light.colors.button.secondary.error.bg, + borderColor: theme.light.colors.button.secondary.error.border, + borderWidth: 1, + }) + }) + + it('renders correctly Button.TertiaryColor', () => { + const { getByTestId } = render() + expect(getByTestId('baseButton').props.style).toStrictEqual({ + ...baseStyles, + backgroundColor: 'transparent', borderColor: 'transparent', - borderRadius: 4, borderWidth: undefined, - flexDirection: 'row', - justifyContent: 'center', - minWidth: 128, - paddingHorizontal: 24, - paddingVertical: 8, }) }) - it('renders correctly Button.Link', () => { - const { getByTestId } = render() + it('renders correctly Button.TertiaryGray', () => { + const { getByTestId } = render() expect(getByTestId('baseButton').props.style).toStrictEqual({ - alignItems: 'center', - backgroundColor: theme.light.colors.button.tertiary.fg, + ...baseStyles, + backgroundColor: 'transparent', + borderColor: 'transparent', + borderWidth: undefined, + }) + }) + + it('renders correctly Button.TertiaryDestructive', () => { + const { getByTestId } = render() + expect(getByTestId('baseButton').props.style).toStrictEqual({ + ...baseStyles, + backgroundColor: 'transparent', + borderColor: 'transparent', + borderWidth: undefined, + }) + }) + + it('renders correctly Button.LinkColor', () => { + const { getByTestId } = render() + expect(getByTestId('baseButton').props.style).toStrictEqual({ + ...baseStyles, + backgroundColor: 'transparent', + borderColor: 'transparent', + borderWidth: undefined, + }) + }) + + it('renders correctly Button.LinkGray', () => { + const { getByTestId } = render() + expect(getByTestId('baseButton').props.style).toStrictEqual({ + ...baseStyles, + backgroundColor: 'transparent', + borderColor: 'transparent', + borderWidth: undefined, + }) + }) + + it('renders correctly Button.LinkDestructive', () => { + const { getByTestId } = render() + expect(getByTestId('baseButton').props.style).toStrictEqual({ + ...baseStyles, + backgroundColor: 'transparent', borderColor: 'transparent', - borderRadius: 4, borderWidth: undefined, - flexDirection: 'row', - justifyContent: 'center', - minWidth: 128, - paddingHorizontal: 24, - paddingVertical: 8, }) }) diff --git a/src/design-system/components/Button/Button.tsx b/src/design-system/components/Button/Button.tsx index 7740c9f0..08e474a0 100644 --- a/src/design-system/components/Button/Button.tsx +++ b/src/design-system/components/Button/Button.tsx @@ -20,18 +20,19 @@ import { View, } from 'react-native' -import { buttonVariants, theme } from '../../config' +import { ButtonSize, ButtonVariant, buttonSizeVariants, buttonVariants, theme } from '../../config' import { generateStyledComponent } from '../../utils' import { Box } from '../Box' import { Loader } from '../Loader' import { Text } from '../Text' +import { useHover } from '../Touchables/useHover' import { StyledProps } from '../types' export type ButtonProps = StyledProps & PressableProps & { title?: string variant?: ButtonVariant - size?: 'sm' | 'md' | 'lg' + size?: ButtonSize loading?: boolean disabled?: boolean leftIcon?: JSX.Element @@ -46,11 +47,8 @@ const styles = StyleSheet.create({ borderRadius: 4, flexDirection: 'row', justifyContent: 'center', - paddingHorizontal: 16, - paddingVertical: 8, }, baseText: { - color: theme.light.colors.text.primary, fontStyle: 'normal', fontWeight: '400', letterSpacing: 0, @@ -77,69 +75,70 @@ const RawButton = memo( ref ) => { const { colorScheme } = useColorScheme() - const { pressedStyle, notPressedStyle, disabledStyle } = useMemo( + const { hoverProps, isHovered } = useHover() + const { hoveredStyle, defaultStyle, disabledStyle } = useMemo( () => buttonVariants[variant], [variant] ) - const pressedStyles = useMemo( + const hoveredStyles = useMemo( () => ({ backgroundColor: getColorValue({ - color: pressedStyle.backgroundColor, + color: hoveredStyle.backgroundColor, colors: colorScheme === 'light' ? theme.light.colors : theme.dark.colors, }), borderColor: getColorValue({ - color: pressedStyle.borderColor!, + color: hoveredStyle.borderColor!, colors: colorScheme === 'light' ? theme.light.colors : theme.dark.colors, }), - borderWidth: pressedStyle.borderWidth, + borderWidth: hoveredStyle.borderWidth, }), [ colorScheme, - pressedStyle.backgroundColor, - pressedStyle.borderColor, - pressedStyle.borderWidth, + hoveredStyle.backgroundColor, + hoveredStyle.borderColor, + hoveredStyle.borderWidth, ] ) - const pressedColorStyle = useMemo( + const hoverColorStyle = useMemo( () => ({ color: getColorValue({ - color: pressedStyle.color!, + color: hoveredStyle.color!, colors: colorScheme === 'light' ? theme.light.colors : theme.dark.colors, }), }), - [colorScheme, pressedStyle.color] + [colorScheme, hoveredStyle.color] ) - const notPressedStyles = useMemo( + const defaultStyles = useMemo( () => ({ backgroundColor: getColorValue({ - color: notPressedStyle.backgroundColor, + color: defaultStyle.backgroundColor, colors: colorScheme === 'light' ? theme.light.colors : theme.dark.colors, }), borderColor: getColorValue({ - color: notPressedStyle.borderColor!, + color: defaultStyle.borderColor!, colors: colorScheme === 'light' ? theme.light.colors : theme.dark.colors, }), - borderWidth: notPressedStyle.borderWidth, + borderWidth: defaultStyle.borderWidth, }), [ colorScheme, - notPressedStyle.backgroundColor, - notPressedStyle.borderColor, - notPressedStyle.borderWidth, + defaultStyle.backgroundColor, + defaultStyle.borderColor, + defaultStyle.borderWidth, ] ) - const notPressedColorStyle = useMemo( + const defaultColorStyle = useMemo( () => ({ color: getColorValue({ - color: notPressedStyle.color!, + color: defaultStyle.color!, colors: colorScheme === 'light' ? theme.light.colors : theme.dark.colors, }), }), - [colorScheme, notPressedStyle.color] + [colorScheme, defaultStyle.color] ) const disabledStyles = useMemo( @@ -171,37 +170,47 @@ const RawButton = memo( }), [colorScheme, disabledStyle.color] ) + const buttonSizeVariant = buttonSizeVariants[size] const buttonSizeStyle = useMemo( () => ({ - paddingHorizontal: size === 'sm' ? 12 : size === 'md' ? 24 : 48, - minWidth: size === 'sm' ? 64 : size === 'md' ? 128 : 256, + paddingHorizontal: buttonSizeVariant.paddingHorizontal, + paddingVertical: buttonSizeVariant.paddingVertical, }), - [size] + [buttonSizeVariant.paddingHorizontal, buttonSizeVariant.paddingVertical] ) const pressableStyleFunction = useCallback( ({ pressed }: PressableStateCallbackType): StyleProp => StyleSheet.flatten([ styles.baseButton, - pressed ? pressedStyles : notPressedStyles, + pressed || isHovered ? hoveredStyles : defaultStyles, disabled && disabledStyles, loading && disabledStyles, buttonSizeStyle, typeof style === 'function' ? style({ pressed }) : style, ]), - [pressedStyles, notPressedStyles, loading, buttonSizeStyle, disabled, disabledStyles, style] + [ + buttonSizeStyle, + defaultStyles, + disabled, + disabledStyles, + hoveredStyles, + isHovered, + loading, + style, + ] ) const pressableTextStyleFunction = useCallback( ({ pressed }: PressableStateCallbackType) => StyleSheet.flatten([ styles.baseText, - pressed ? pressedColorStyle : notPressedColorStyle, + pressed ? hoverColorStyle : defaultColorStyle, disabled && disabledColorStyle, textStyle, ]), - [pressedColorStyle, notPressedColorStyle, disabled, disabledColorStyle, textStyle] + [hoverColorStyle, defaultColorStyle, disabled, disabledColorStyle, textStyle] ) const childrenElement = useCallback( @@ -211,47 +220,47 @@ const RawButton = memo( } if (title) { return ( - {title} - + ) } if (typeof children === 'string') { return ( - {children} - + ) } return children }, - [children, loading, pressableTextStyleFunction, title] + [buttonSizeVariant.textVariant, children, loading, pressableTextStyleFunction, title] ) return ( {(props: PressableStateCallbackType) => ( <> - {leftIcon && {leftIcon}} + {leftIcon && {leftIcon}} {childrenElement(props)} - {rightIcon && {rightIcon}} + {rightIcon && {rightIcon}} )} @@ -259,7 +268,7 @@ const RawButton = memo( } ) ) -export type ButtonVariant = 'Primary' | 'Secondary' | 'Outline' | 'Ghost' | 'Link' + type ButtonComposition = ForwardRefExoticComponent< PropsWithoutRef & RefAttributes > & { @@ -275,9 +284,15 @@ const generateButtonVariant = (variant: ButtonVariant) => forwardRef((props, ref) => diff --git a/src/screens/LandingScreen.tsx b/src/screens/LandingScreen.tsx index ab343deb..dcfe8b8c 100644 --- a/src/screens/LandingScreen.tsx +++ b/src/screens/LandingScreen.tsx @@ -33,9 +33,9 @@ export const LandingScreen = () => { source={colorScheme === 'light' ? lightLogo : darkLogo} style={styles.logo} /> - {t('hello')} - {t('thanks')} - {t('app_information')} + {t('hello')} + {t('thanks')} + {t('app_information')} diff --git a/src/screens/ProfileScreen.tsx b/src/screens/ProfileScreen.tsx index d3e9b521..d78c83cd 100644 --- a/src/screens/ProfileScreen.tsx +++ b/src/screens/ProfileScreen.tsx @@ -15,8 +15,8 @@ export const ProfileScreen = () => { return ( - Profile - Update your personal details here. + Profile + Update your personal details here. { - { testID="backProfileButton" > {t('common.cancel')} - +