From c8f264b78b1dfb95f68bfb820bd012828cd5fddc Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Tue, 29 Oct 2024 21:14:54 +0000 Subject: Settings revamp (#5745) * start building storybook * add title * add some styles * try out new icons * more settings list component parts * make text do the spacing * clean up storybook * gated new settings screen * switch account * add current profile * use Layout.Screen * Layout.Header and Layout.Content * translate helpdesk text thanks @surfdude29! Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com> * add account settings * undo changes to export car dialog * privacy and security screen * Translate protect account stuff Thanks @surfdude29! Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com> * content and media settings * about settings * 2fa copy Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com> * a11y and appearance * use new components for appearance settings * redesign accessibility settings * Update ContentAndMediaSettings.tsx Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com> * add divider * remove a11y and appearance middleman screen * fix web settingslist styles * new SettingsList.Group component * explain how portal magic works * hide pwioptout in old location * Update Settings.tsx Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com> * replace gate with `IS_INTERNAL` * add IS_INTERNAL to app-info.web * fix profile area growing * add close button to switch account --------- Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com> --- src/screens/Settings/components/SettingsList.tsx | 300 +++++++++++++++++++++++ 1 file changed, 300 insertions(+) create mode 100644 src/screens/Settings/components/SettingsList.tsx (limited to 'src/screens/Settings/components/SettingsList.tsx') diff --git a/src/screens/Settings/components/SettingsList.tsx b/src/screens/Settings/components/SettingsList.tsx new file mode 100644 index 000000000..86f8040af --- /dev/null +++ b/src/screens/Settings/components/SettingsList.tsx @@ -0,0 +1,300 @@ +import React, {useContext, useMemo} from 'react' +import {GestureResponderEvent, StyleProp, View, ViewStyle} from 'react-native' + +import {HITSLOP_10} from '#/lib/constants' +import {atoms as a, useTheme} from '#/alf' +import * as Button from '#/components/Button' +import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRightIcon} from '#/components/icons/Chevron' +import {Link, LinkProps} from '#/components/Link' +import {createPortalGroup} from '#/components/Portal' +import {Text} from '#/components/Typography' + +const ItemContext = React.createContext({ + destructive: false, + withinGroup: false, +}) + +const Portal = createPortalGroup() + +export function Container({children}: {children: React.ReactNode}) { + return {children} +} + +/** + * This uses `Portal` magic ✨ to render the icons and title correctly. ItemIcon and ItemText components + * get teleported to the top row, leaving the rest of the children in the bottom row. + */ +export function Group({ + children, + destructive = false, + iconInset = true, + style, + contentContainerStyle, +}: { + children: React.ReactNode + destructive?: boolean + iconInset?: boolean + style?: StyleProp + contentContainerStyle?: StyleProp +}) { + const context = useMemo( + () => ({destructive, withinGroup: true}), + [destructive], + ) + return ( + + + + + + + + {children} + + + + + ) +} + +export function Item({ + children, + destructive, + iconInset = false, + style, +}: { + children?: React.ReactNode + destructive?: boolean + /** + * Adds left padding so that the content will be aligned with other Items that contain icons + * @default false + */ + iconInset?: boolean + style?: StyleProp +}) { + const context = useContext(ItemContext) + const childContext = useMemo(() => { + if (typeof destructive !== 'boolean') return context + return {...context, destructive} + }, [context, destructive]) + return ( + + + {children} + + + ) +} + +export function LinkItem({ + children, + destructive = false, + contentContainerStyle, + chevronColor, + ...props +}: LinkProps & { + contentContainerStyle?: StyleProp + destructive?: boolean + chevronColor?: string +}) { + const t = useTheme() + + return ( + + {args => ( + + {typeof children === 'function' ? children(args) : children} + + + )} + + ) +} + +export function PressableItem({ + children, + destructive = false, + contentContainerStyle, + hoverStyle, + ...props +}: Button.ButtonProps & { + contentContainerStyle?: StyleProp + destructive?: boolean +}) { + const t = useTheme() + return ( + + {args => ( + + {typeof children === 'function' ? children(args) : children} + + )} + + ) +} + +export function ItemIcon({ + icon: Comp, + size = 'xl', + color: colorProp, +}: Omit, 'position'> & { + color?: string +}) { + const t = useTheme() + const {destructive, withinGroup} = useContext(ItemContext) + + /* + * Copied here from icons/common.tsx so we can tweak if we need to, but + * also so that we can calculate transforms. + */ + const iconSize = { + xs: 12, + sm: 16, + md: 20, + lg: 24, + xl: 28, + '2xl': 32, + }[size] + + const color = + colorProp ?? (destructive ? t.palette.negative_500 : t.atoms.text.color) + + const content = ( + + + + ) + + if (withinGroup) { + return {content} + } else { + return content + } +} + +export function ItemText({ + // eslint-disable-next-line react/prop-types + style, + ...props +}: React.ComponentProps) { + const t = useTheme() + const {destructive, withinGroup} = useContext(ItemContext) + + const content = ( + + ) + + if (withinGroup) { + return {content} + } else { + return content + } +} + +export function Divider() { + const t = useTheme() + return ( + + ) +} + +export function Chevron({color: colorProp}: {color?: string}) { + const {destructive} = useContext(ItemContext) + const t = useTheme() + const color = + colorProp ?? (destructive ? t.palette.negative_500 : t.palette.contrast_500) + return +} + +export function BadgeText({children}: {children: React.ReactNode}) { + const t = useTheme() + return ( + + {children} + + ) +} + +export function BadgeButton({ + label, + onPress, +}: { + label: string + onPress: (evt: GestureResponderEvent) => void +}) { + const t = useTheme() + return ( + + {({pressed}) => ( + + {label} + + )} + + ) +} -- cgit 1.4.1