diff options
Diffstat (limited to 'src/view/screens')
-rw-r--r-- | src/view/screens/DebugNew.tsx | 541 | ||||
-rw-r--r-- | src/view/screens/Search/Search.tsx | 54 | ||||
-rw-r--r-- | src/view/screens/Settings.tsx | 2 | ||||
-rw-r--r-- | src/view/screens/Storybook/Breakpoints.tsx | 25 | ||||
-rw-r--r-- | src/view/screens/Storybook/Buttons.tsx | 124 | ||||
-rw-r--r-- | src/view/screens/Storybook/Dialogs.tsx | 90 | ||||
-rw-r--r-- | src/view/screens/Storybook/Forms.tsx | 215 | ||||
-rw-r--r-- | src/view/screens/Storybook/Icons.tsx | 41 | ||||
-rw-r--r-- | src/view/screens/Storybook/Links.tsx | 48 | ||||
-rw-r--r-- | src/view/screens/Storybook/Palette.tsx | 336 | ||||
-rw-r--r-- | src/view/screens/Storybook/Shadows.tsx | 53 | ||||
-rw-r--r-- | src/view/screens/Storybook/Spacing.tsx | 64 | ||||
-rw-r--r-- | src/view/screens/Storybook/Theming.tsx | 56 | ||||
-rw-r--r-- | src/view/screens/Storybook/Typography.tsx | 30 | ||||
-rw-r--r-- | src/view/screens/Storybook/index.tsx | 78 |
15 files changed, 1198 insertions, 559 deletions
diff --git a/src/view/screens/DebugNew.tsx b/src/view/screens/DebugNew.tsx deleted file mode 100644 index 0b7c5f03b..000000000 --- a/src/view/screens/DebugNew.tsx +++ /dev/null @@ -1,541 +0,0 @@ -import React from 'react' -import {View} from 'react-native' -import {CenteredView, ScrollView} from '#/view/com/util/Views' -import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' - -import {useSetColorMode} from '#/state/shell' -import * as tokens from '#/alf/tokens' -import {atoms as a, useTheme, useBreakpoints, ThemeProvider as Alf} from '#/alf' -import {Button, ButtonText} from '#/view/com/Button' -import {Text, H1, H2, H3, H4, H5, H6} from '#/view/com/Typography' - -function ThemeSelector() { - const setColorMode = useSetColorMode() - - return ( - <View style={[a.flex_row, a.gap_md]}> - <Button - type="secondary" - size="small" - onPress={() => setColorMode('system')}> - System - </Button> - <Button - type="secondary" - size="small" - onPress={() => setColorMode('light')}> - Light - </Button> - <Button - type="secondary" - size="small" - onPress={() => setColorMode('dark')}> - Dark - </Button> - </View> - ) -} - -function BreakpointDebugger() { - const t = useTheme() - const breakpoints = useBreakpoints() - - return ( - <View> - <H3 style={[a.pb_md]}>Breakpoint Debugger</H3> - <Text style={[a.pb_md]}> - Current breakpoint: {!breakpoints.gtMobile && <Text>mobile</Text>} - {breakpoints.gtMobile && !breakpoints.gtTablet && <Text>tablet</Text>} - {breakpoints.gtTablet && <Text>desktop</Text>} - </Text> - <Text - style={[a.p_md, t.atoms.bg_contrast_100, {fontFamily: 'monospace'}]}> - {JSON.stringify(breakpoints, null, 2)} - </Text> - </View> - ) -} - -function ThemedSection() { - const t = useTheme() - - return ( - <View style={[t.atoms.bg, a.gap_md, a.p_xl]}> - <H3 style={[a.font_bold]}>theme.atoms.text</H3> - <View style={[a.flex_1, t.atoms.border, a.border_t]} /> - <H3 style={[a.font_bold, t.atoms.text_contrast_700]}> - theme.atoms.text_contrast_700 - </H3> - <View style={[a.flex_1, t.atoms.border, a.border_t]} /> - <H3 style={[a.font_bold, t.atoms.text_contrast_500]}> - theme.atoms.text_contrast_500 - </H3> - <View style={[a.flex_1, t.atoms.border_contrast_500, a.border_t]} /> - - <View style={[a.flex_row, a.gap_md]}> - <View - style={[ - a.flex_1, - t.atoms.bg, - a.align_center, - a.justify_center, - {height: 60}, - ]}> - <Text>theme.bg</Text> - </View> - <View - style={[ - a.flex_1, - t.atoms.bg_contrast_100, - a.align_center, - a.justify_center, - {height: 60}, - ]}> - <Text>theme.bg_contrast_100</Text> - </View> - </View> - <View style={[a.flex_row, a.gap_md]}> - <View - style={[ - a.flex_1, - t.atoms.bg_contrast_200, - a.align_center, - a.justify_center, - {height: 60}, - ]}> - <Text>theme.bg_contrast_200</Text> - </View> - <View - style={[ - a.flex_1, - t.atoms.bg_contrast_300, - a.align_center, - a.justify_center, - {height: 60}, - ]}> - <Text>theme.bg_contrast_300</Text> - </View> - </View> - <View style={[a.flex_row, a.gap_md]}> - <View - style={[ - a.flex_1, - t.atoms.bg_positive, - a.align_center, - a.justify_center, - {height: 60}, - ]}> - <Text>theme.bg_positive</Text> - </View> - <View - style={[ - a.flex_1, - t.atoms.bg_negative, - a.align_center, - a.justify_center, - {height: 60}, - ]}> - <Text>theme.bg_negative</Text> - </View> - </View> - </View> - ) -} - -export function DebugScreen() { - const t = useTheme() - - return ( - <ScrollView> - <CenteredView style={[t.atoms.bg]}> - <View style={[a.p_xl, a.gap_xxl, {paddingBottom: 200}]}> - <ThemeSelector /> - - <Alf theme="light"> - <ThemedSection /> - </Alf> - <Alf theme="dark"> - <ThemedSection /> - </Alf> - - <H1>Heading 1</H1> - <H2>Heading 2</H2> - <H3>Heading 3</H3> - <H4>Heading 4</H4> - <H5>Heading 5</H5> - <H6>Heading 6</H6> - - <Text style={[a.text_xxl]}>atoms.text_xxl</Text> - <Text style={[a.text_xl]}>atoms.text_xl</Text> - <Text style={[a.text_lg]}>atoms.text_lg</Text> - <Text style={[a.text_md]}>atoms.text_md</Text> - <Text style={[a.text_sm]}>atoms.text_sm</Text> - <Text style={[a.text_xs]}>atoms.text_xs</Text> - <Text style={[a.text_xxs]}>atoms.text_xxs</Text> - - <View style={[a.gap_md, a.align_start]}> - <Button> - {({state}) => ( - <View style={[a.p_md, a.rounded_full, t.atoms.bg_contrast_300]}> - <Text>Unstyled button, state: {JSON.stringify(state)}</Text> - </View> - )} - </Button> - - <Button type="primary" size="small"> - Button - </Button> - <Button type="secondary" size="small"> - Button - </Button> - - <Button type="primary" size="large"> - Button - </Button> - <Button type="secondary" size="large"> - Button - </Button> - - <Button type="secondary" size="small"> - {({type, size}) => ( - <> - <FontAwesomeIcon icon={['fas', 'plus']} size={12} /> - <ButtonText type={type} size={size}> - With an icon - </ButtonText> - </> - )} - </Button> - <Button type="primary" size="large"> - {({state: _state, ...rest}) => ( - <> - <FontAwesomeIcon icon={['fas', 'plus']} /> - <ButtonText {...rest}>With an icon</ButtonText> - </> - )} - </Button> - </View> - - <View style={[a.gap_md]}> - <View style={[a.flex_row, a.gap_md]}> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.gray_0}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.gray_100}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.gray_200}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.gray_300}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.gray_400}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.gray_500}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.gray_600}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.gray_700}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.gray_800}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.gray_900}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.gray_1000}, - ]} - /> - </View> - - <View style={[a.flex_row, a.gap_md]}> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.blue_0}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.blue_100}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.blue_200}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.blue_300}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.blue_400}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.blue_500}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.blue_600}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.blue_700}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.blue_800}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.blue_900}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.blue_1000}, - ]} - /> - </View> - <View style={[a.flex_row, a.gap_md]}> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.green_0}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.green_100}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.green_200}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.green_300}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.green_400}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.green_500}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.green_600}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.green_700}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.green_800}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.green_900}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.green_1000}, - ]} - /> - </View> - <View style={[a.flex_row, a.gap_md]}> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.red_0}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.red_100}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.red_200}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.red_300}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.red_400}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.red_500}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.red_600}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.red_700}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.red_800}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.red_900}, - ]} - /> - <View - style={[ - a.flex_1, - {height: 60, backgroundColor: tokens.color.red_1000}, - ]} - /> - </View> - </View> - - <View> - <H3 style={[a.pb_md, a.font_bold]}>Spacing</H3> - - <View style={[a.gap_md]}> - <View style={[a.flex_row, a.align_center]}> - <Text style={{width: 80}}>xxs (2px)</Text> - <View style={[a.flex_1, a.pt_xxs, t.atoms.bg_contrast_300]} /> - </View> - - <View style={[a.flex_row, a.align_center]}> - <Text style={{width: 80}}>xs (4px)</Text> - <View style={[a.flex_1, a.pt_xs, t.atoms.bg_contrast_300]} /> - </View> - - <View style={[a.flex_row, a.align_center]}> - <Text style={{width: 80}}>sm (8px)</Text> - <View style={[a.flex_1, a.pt_sm, t.atoms.bg_contrast_300]} /> - </View> - - <View style={[a.flex_row, a.align_center]}> - <Text style={{width: 80}}>md (12px)</Text> - <View style={[a.flex_1, a.pt_md, t.atoms.bg_contrast_300]} /> - </View> - - <View style={[a.flex_row, a.align_center]}> - <Text style={{width: 80}}>lg (18px)</Text> - <View style={[a.flex_1, a.pt_lg, t.atoms.bg_contrast_300]} /> - </View> - - <View style={[a.flex_row, a.align_center]}> - <Text style={{width: 80}}>xl (24px)</Text> - <View style={[a.flex_1, a.pt_xl, t.atoms.bg_contrast_300]} /> - </View> - - <View style={[a.flex_row, a.align_center]}> - <Text style={{width: 80}}>xxl (32px)</Text> - <View style={[a.flex_1, a.pt_xxl, t.atoms.bg_contrast_300]} /> - </View> - </View> - </View> - - <BreakpointDebugger /> - </View> - </CenteredView> - </ScrollView> - ) -} diff --git a/src/view/screens/Search/Search.tsx b/src/view/screens/Search/Search.tsx index 8e7e204ad..94aab2d96 100644 --- a/src/view/screens/Search/Search.tsx +++ b/src/view/screens/Search/Search.tsx @@ -42,9 +42,13 @@ import {useSetDrawerOpen} from '#/state/shell' import {useAnalytics} from '#/lib/analytics/analytics' import {MagnifyingGlassIcon} from '#/lib/icons' import {useModerationOpts} from '#/state/queries/preferences' -import {SearchResultCard} from '#/view/shell/desktop/Search' +import { + MATCH_HANDLE, + SearchLinkCard, + SearchProfileCard, +} from '#/view/shell/desktop/Search' import {useSetMinimalShellMode, useSetDrawerSwipeDisabled} from '#/state/shell' -import {isWeb} from '#/platform/detection' +import {isNative, isWeb} from '#/platform/detection' import {listenSoftReset} from '#/state/events' import {s} from '#/lib/styles' @@ -83,9 +87,7 @@ function EmptyState({message, error}: {message: string; error?: string}) { }, ]}> <View style={[pal.viewLight, {padding: 18, borderRadius: 8}]}> - <Text style={[pal.text]}> - <Trans>{message}</Trans> - </Text> + <Text style={[pal.text]}>{message}</Text> {error && ( <> @@ -511,6 +513,11 @@ export function SearchScreen( onPressCancelSearch() }, [onPressCancelSearch]) + const queryMaybeHandle = React.useMemo(() => { + const match = MATCH_HANDLE.exec(query) + return match && match[1] + }, [query]) + useFocusEffect( React.useCallback(() => { setMinimalShellMode(false) @@ -617,18 +624,31 @@ export function SearchScreen( dataSet={{stableGutters: '1'}} keyboardShouldPersistTaps="handled" keyboardDismissMode="on-drag"> - {searchResults.length ? ( - searchResults.map((item, i) => ( - <SearchResultCard - key={item.did} - profile={item} - moderation={moderateProfile(item, moderationOpts)} - style={i === 0 ? {borderTopWidth: 0} : {}} - /> - )) - ) : ( - <EmptyState message={_(msg`No results found for ${query}`)} /> - )} + <SearchLinkCard + label={_(msg`Search for "${query}"`)} + onPress={isNative ? onSubmit : undefined} + to={ + isNative + ? undefined + : `/search?q=${encodeURIComponent(query)}` + } + style={{borderBottomWidth: 1}} + /> + + {queryMaybeHandle ? ( + <SearchLinkCard + label={_(msg`Go to @${queryMaybeHandle}`)} + to={`/profile/${queryMaybeHandle}`} + /> + ) : null} + + {searchResults.map(item => ( + <SearchProfileCard + key={item.did} + profile={item} + moderation={moderateProfile(item, moderationOpts)} + /> + ))} <View style={{height: 200}} /> </ScrollView> diff --git a/src/view/screens/Settings.tsx b/src/view/screens/Settings.tsx index 1f117b45b..3b50c5449 100644 --- a/src/view/screens/Settings.tsx +++ b/src/view/screens/Settings.tsx @@ -291,7 +291,7 @@ export function SettingsScreen({}: Props) { ]}> <View style={{flex: 1}}> <Text type="title-lg" style={[pal.text, {fontWeight: 'bold'}]}> - <Trans>{_(msg`Settings`)}</Trans> + <Trans>Settings</Trans> </Text> </View> </SimpleViewHeader> diff --git a/src/view/screens/Storybook/Breakpoints.tsx b/src/view/screens/Storybook/Breakpoints.tsx new file mode 100644 index 000000000..1b846d517 --- /dev/null +++ b/src/view/screens/Storybook/Breakpoints.tsx @@ -0,0 +1,25 @@ +import React from 'react' +import {View} from 'react-native' + +import {atoms as a, useTheme, useBreakpoints} from '#/alf' +import {Text, H3} from '#/components/Typography' + +export function Breakpoints() { + const t = useTheme() + const breakpoints = useBreakpoints() + + return ( + <View> + <H3 style={[a.pb_md]}>Breakpoint Debugger</H3> + <Text style={[a.pb_md]}> + Current breakpoint: {!breakpoints.gtMobile && <Text>mobile</Text>} + {breakpoints.gtMobile && !breakpoints.gtTablet && <Text>tablet</Text>} + {breakpoints.gtTablet && <Text>desktop</Text>} + </Text> + <Text + style={[a.p_md, t.atoms.bg_contrast_100, {fontFamily: 'monospace'}]}> + {JSON.stringify(breakpoints, null, 2)} + </Text> + </View> + ) +} diff --git a/src/view/screens/Storybook/Buttons.tsx b/src/view/screens/Storybook/Buttons.tsx new file mode 100644 index 000000000..fbdc84eb4 --- /dev/null +++ b/src/view/screens/Storybook/Buttons.tsx @@ -0,0 +1,124 @@ +import React from 'react' +import {View} from 'react-native' + +import {atoms as a} from '#/alf' +import { + Button, + ButtonVariant, + ButtonColor, + ButtonIcon, + ButtonText, +} from '#/components/Button' +import {H1} from '#/components/Typography' +import {ArrowTopRight_Stroke2_Corner0_Rounded as ArrowTopRight} from '#/components/icons/ArrowTopRight' +import {Globe_Stroke2_Corner0_Rounded as Globe} from '#/components/icons/Globe' + +export function Buttons() { + return ( + <View style={[a.gap_md]}> + <H1>Buttons</H1> + + <View style={[a.flex_row, a.flex_wrap, a.gap_md, a.align_start]}> + {['primary', 'secondary', 'negative'].map(color => ( + <View key={color} style={[a.gap_md, a.align_start]}> + {['solid', 'outline', 'ghost'].map(variant => ( + <React.Fragment key={variant}> + <Button + variant={variant as ButtonVariant} + color={color as ButtonColor} + size="large" + label="Click here"> + Button + </Button> + <Button + disabled + variant={variant as ButtonVariant} + color={color as ButtonColor} + size="large" + label="Click here"> + Button + </Button> + </React.Fragment> + ))} + </View> + ))} + + <View style={[a.flex_row, a.gap_md, a.align_start]}> + <View style={[a.gap_md, a.align_start]}> + {['gradient_sky', 'gradient_midnight', 'gradient_sunrise'].map( + name => ( + <React.Fragment key={name}> + <Button + variant="gradient" + color={name as ButtonColor} + size="large" + label="Click here"> + Button + </Button> + <Button + disabled + variant="gradient" + color={name as ButtonColor} + size="large" + label="Click here"> + Button + </Button> + </React.Fragment> + ), + )} + </View> + <View style={[a.gap_md, a.align_start]}> + {['gradient_sunset', 'gradient_nordic', 'gradient_bonfire'].map( + name => ( + <React.Fragment key={name}> + <Button + variant="gradient" + color={name as ButtonColor} + size="large" + label="Click here"> + Button + </Button> + <Button + disabled + variant="gradient" + color={name as ButtonColor} + size="large" + label="Click here"> + Button + </Button> + </React.Fragment> + ), + )} + </View> + </View> + + <Button + variant="gradient" + color="gradient_sky" + size="large" + label="Link out"> + <ButtonText>Link out</ButtonText> + <ButtonIcon icon={ArrowTopRight} /> + </Button> + + <Button + variant="gradient" + color="gradient_sky" + size="small" + label="Link out"> + <ButtonText>Link out</ButtonText> + <ButtonIcon icon={ArrowTopRight} /> + </Button> + + <Button + variant="gradient" + color="gradient_sky" + size="small" + label="Link out"> + <ButtonIcon icon={Globe} /> + <ButtonText>See the world</ButtonText> + </Button> + </View> + </View> + ) +} diff --git a/src/view/screens/Storybook/Dialogs.tsx b/src/view/screens/Storybook/Dialogs.tsx new file mode 100644 index 000000000..db568c6bd --- /dev/null +++ b/src/view/screens/Storybook/Dialogs.tsx @@ -0,0 +1,90 @@ +import React from 'react' +import {View} from 'react-native' + +import {atoms as a} from '#/alf' +import {Button} from '#/components/Button' +import {H3, P} from '#/components/Typography' +import * as Dialog from '#/components/Dialog' +import * as Prompt from '#/components/Prompt' +import {useDialogStateControlContext} from '#/state/dialogs' + +export function Dialogs() { + const control = Dialog.useDialogControl() + const prompt = Prompt.usePromptControl() + const {closeAllDialogs} = useDialogStateControlContext() + + return ( + <View style={[a.gap_md]}> + <Button + variant="outline" + color="secondary" + size="small" + onPress={() => { + control.open() + prompt.open() + }} + label="Open basic dialog"> + Open basic dialog + </Button> + + <Button + variant="solid" + color="primary" + size="small" + onPress={() => prompt.open()} + label="Open prompt"> + Open prompt + </Button> + + <Prompt.Outer control={prompt}> + <Prompt.Title>This is a prompt</Prompt.Title> + <Prompt.Description> + This is a generic prompt component. It accepts a title and a + description, as well as two actions. + </Prompt.Description> + <Prompt.Actions> + <Prompt.Cancel>Cancel</Prompt.Cancel> + <Prompt.Action>Confirm</Prompt.Action> + </Prompt.Actions> + </Prompt.Outer> + + <Dialog.Outer + control={control} + nativeOptions={{sheet: {snapPoints: ['90%']}}}> + <Dialog.Handle /> + + <Dialog.ScrollableInner + accessibilityDescribedBy="dialog-description" + accessibilityLabelledBy="dialog-title"> + <View style={[a.relative, a.gap_md, a.w_full]}> + <H3 nativeID="dialog-title">Dialog</H3> + <P nativeID="dialog-description"> + A scrollable dialog with an input within it. + </P> + <Dialog.Input value="" onChangeText={() => {}} label="Type here" /> + + <Button + variant="outline" + color="secondary" + size="small" + onPress={closeAllDialogs} + label="Close all dialogs"> + Close all dialogs + </Button> + <View style={{height: 1000}} /> + <View style={[a.flex_row, a.justify_end]}> + <Button + variant="outline" + color="primary" + size="small" + onPress={() => control.close()} + label="Open basic dialog"> + Close basic dialog + </Button> + </View> + </View> + </Dialog.ScrollableInner> + </Dialog.Outer> + </View> + ) +} diff --git a/src/view/screens/Storybook/Forms.tsx b/src/view/screens/Storybook/Forms.tsx new file mode 100644 index 000000000..9396cca67 --- /dev/null +++ b/src/view/screens/Storybook/Forms.tsx @@ -0,0 +1,215 @@ +import React from 'react' +import {View} from 'react-native' + +import {atoms as a} from '#/alf' +import {H1, H3} from '#/components/Typography' +import * as TextField from '#/components/forms/TextField' +import {DateField, Label} from '#/components/forms/DateField' +import * as Toggle from '#/components/forms/Toggle' +import * as ToggleButton from '#/components/forms/ToggleButton' +import {Button} from '#/components/Button' +import {Globe_Stroke2_Corner0_Rounded as Globe} from '#/components/icons/Globe' + +export function Forms() { + const [toggleGroupAValues, setToggleGroupAValues] = React.useState(['a']) + const [toggleGroupBValues, setToggleGroupBValues] = React.useState(['a', 'b']) + const [toggleGroupCValues, setToggleGroupCValues] = React.useState(['a', 'b']) + const [toggleGroupDValues, setToggleGroupDValues] = React.useState(['warn']) + + const [value, setValue] = React.useState('') + const [date, setDate] = React.useState('2001-01-01') + + return ( + <View style={[a.gap_4xl, a.align_start]}> + <H1>Forms</H1> + + <View style={[a.gap_md, a.align_start, a.w_full]}> + <H3>InputText</H3> + + <TextField.Input + value={value} + onChangeText={setValue} + label="Text field" + /> + + <TextField.Root> + <TextField.Icon icon={Globe} /> + <TextField.Input + value={value} + onChangeText={setValue} + label="Text field" + /> + </TextField.Root> + + <View style={[a.w_full]}> + <TextField.Label>Text field</TextField.Label> + <TextField.Root> + <TextField.Icon icon={Globe} /> + <TextField.Input + value={value} + onChangeText={setValue} + label="Text field" + /> + <TextField.Suffix label="@gmail.com">@gmail.com</TextField.Suffix> + </TextField.Root> + </View> + + <View style={[a.w_full]}> + <TextField.Label>Textarea</TextField.Label> + <TextField.Input + multiline + numberOfLines={4} + value={value} + onChangeText={setValue} + label="Text field" + /> + </View> + + <H3>DateField</H3> + + <View style={[a.w_full]}> + <Label>Date</Label> + <DateField + testID="date" + value={date} + onChangeDate={date => { + console.log(date) + setDate(date) + }} + label="Input" + /> + </View> + </View> + + <View style={[a.gap_md, a.align_start, a.w_full]}> + <H3>Toggles</H3> + + <Toggle.Item name="a" label="Click me"> + <Toggle.Checkbox /> + <Toggle.Label>Uncontrolled toggle</Toggle.Label> + </Toggle.Item> + + <Toggle.Group + label="Toggle" + type="checkbox" + maxSelections={2} + values={toggleGroupAValues} + onChange={setToggleGroupAValues}> + <View style={[a.gap_md]}> + <Toggle.Item name="a" label="Click me"> + <Toggle.Switch /> + <Toggle.Label>Click me</Toggle.Label> + </Toggle.Item> + <Toggle.Item name="b" label="Click me"> + <Toggle.Switch /> + <Toggle.Label>Click me</Toggle.Label> + </Toggle.Item> + <Toggle.Item name="c" label="Click me"> + <Toggle.Switch /> + <Toggle.Label>Click me</Toggle.Label> + </Toggle.Item> + <Toggle.Item name="d" disabled label="Click me"> + <Toggle.Switch /> + <Toggle.Label>Click me</Toggle.Label> + </Toggle.Item> + <Toggle.Item name="e" isInvalid label="Click me"> + <Toggle.Switch /> + <Toggle.Label>Click me</Toggle.Label> + </Toggle.Item> + </View> + </Toggle.Group> + + <Toggle.Group + label="Toggle" + type="checkbox" + maxSelections={2} + values={toggleGroupBValues} + onChange={setToggleGroupBValues}> + <View style={[a.gap_md]}> + <Toggle.Item name="a" label="Click me"> + <Toggle.Checkbox /> + <Toggle.Label>Click me</Toggle.Label> + </Toggle.Item> + <Toggle.Item name="b" label="Click me"> + <Toggle.Checkbox /> + <Toggle.Label>Click me</Toggle.Label> + </Toggle.Item> + <Toggle.Item name="c" label="Click me"> + <Toggle.Checkbox /> + <Toggle.Label>Click me</Toggle.Label> + </Toggle.Item> + <Toggle.Item name="d" disabled label="Click me"> + <Toggle.Checkbox /> + <Toggle.Label>Click me</Toggle.Label> + </Toggle.Item> + <Toggle.Item name="e" isInvalid label="Click me"> + <Toggle.Checkbox /> + <Toggle.Label>Click me</Toggle.Label> + </Toggle.Item> + </View> + </Toggle.Group> + + <Toggle.Group + label="Toggle" + type="radio" + values={toggleGroupCValues} + onChange={setToggleGroupCValues}> + <View style={[a.gap_md]}> + <Toggle.Item name="a" label="Click me"> + <Toggle.Radio /> + <Toggle.Label>Click me</Toggle.Label> + </Toggle.Item> + <Toggle.Item name="b" label="Click me"> + <Toggle.Radio /> + <Toggle.Label>Click me</Toggle.Label> + </Toggle.Item> + <Toggle.Item name="c" label="Click me"> + <Toggle.Radio /> + <Toggle.Label>Click me</Toggle.Label> + </Toggle.Item> + <Toggle.Item name="d" disabled label="Click me"> + <Toggle.Radio /> + <Toggle.Label>Click me</Toggle.Label> + </Toggle.Item> + <Toggle.Item name="e" isInvalid label="Click me"> + <Toggle.Radio /> + <Toggle.Label>Click me</Toggle.Label> + </Toggle.Item> + </View> + </Toggle.Group> + </View> + + <Button + variant="gradient" + color="gradient_nordic" + size="small" + label="Reset all toggles" + onPress={() => { + setToggleGroupAValues(['a']) + setToggleGroupBValues(['a', 'b']) + setToggleGroupCValues(['a']) + }}> + Reset all toggles + </Button> + + <View style={[a.gap_md, a.align_start, a.w_full]}> + <H3>ToggleButton</H3> + + <ToggleButton.Group + label="Preferences" + values={toggleGroupDValues} + onChange={setToggleGroupDValues}> + <ToggleButton.Button name="hide" label="Hide"> + Hide + </ToggleButton.Button> + <ToggleButton.Button name="warn" label="Warn"> + Warn + </ToggleButton.Button> + <ToggleButton.Button name="show" label="Show"> + Show + </ToggleButton.Button> + </ToggleButton.Group> + </View> + </View> + ) +} diff --git a/src/view/screens/Storybook/Icons.tsx b/src/view/screens/Storybook/Icons.tsx new file mode 100644 index 000000000..73466e077 --- /dev/null +++ b/src/view/screens/Storybook/Icons.tsx @@ -0,0 +1,41 @@ +import React from 'react' +import {View} from 'react-native' + +import {atoms as a, useTheme} from '#/alf' +import {H1} from '#/components/Typography' +import {Globe_Stroke2_Corner0_Rounded as Globe} from '#/components/icons/Globe' +import {ArrowTopRight_Stroke2_Corner0_Rounded as ArrowTopRight} from '#/components/icons/ArrowTopRight' +import {CalendarDays_Stroke2_Corner0_Rounded as CalendarDays} from '#/components/icons/CalendarDays' + +export function Icons() { + const t = useTheme() + return ( + <View style={[a.gap_md]}> + <H1>Icons</H1> + + <View style={[a.flex_row, a.gap_xl]}> + <Globe size="xs" fill={t.atoms.text.color} /> + <Globe size="sm" fill={t.atoms.text.color} /> + <Globe size="md" fill={t.atoms.text.color} /> + <Globe size="lg" fill={t.atoms.text.color} /> + <Globe size="xl" fill={t.atoms.text.color} /> + </View> + + <View style={[a.flex_row, a.gap_xl]}> + <ArrowTopRight size="xs" fill={t.atoms.text.color} /> + <ArrowTopRight size="sm" fill={t.atoms.text.color} /> + <ArrowTopRight size="md" fill={t.atoms.text.color} /> + <ArrowTopRight size="lg" fill={t.atoms.text.color} /> + <ArrowTopRight size="xl" fill={t.atoms.text.color} /> + </View> + + <View style={[a.flex_row, a.gap_xl]}> + <CalendarDays size="xs" fill={t.atoms.text.color} /> + <CalendarDays size="sm" fill={t.atoms.text.color} /> + <CalendarDays size="md" fill={t.atoms.text.color} /> + <CalendarDays size="lg" fill={t.atoms.text.color} /> + <CalendarDays size="xl" fill={t.atoms.text.color} /> + </View> + </View> + ) +} diff --git a/src/view/screens/Storybook/Links.tsx b/src/view/screens/Storybook/Links.tsx new file mode 100644 index 000000000..c3b1c0e0f --- /dev/null +++ b/src/view/screens/Storybook/Links.tsx @@ -0,0 +1,48 @@ +import React from 'react' +import {View} from 'react-native' + +import {atoms as a} from '#/alf' +import {ButtonText} from '#/components/Button' +import {Link} from '#/components/Link' +import {H1, H3} from '#/components/Typography' + +export function Links() { + return ( + <View style={[a.gap_md, a.align_start]}> + <H1>Links</H1> + + <View style={[a.gap_md, a.align_start]}> + <Link + to="https://blueskyweb.xyz" + warnOnMismatchingTextChild + style={[a.text_md]}> + External + </Link> + <Link to="https://blueskyweb.xyz" style={[a.text_md]}> + <H3>External with custom children</H3> + </Link> + <Link + to="https://blueskyweb.xyz" + warnOnMismatchingTextChild + style={[a.text_lg]}> + https://blueskyweb.xyz + </Link> + <Link + to="https://bsky.app/profile/bsky.app" + warnOnMismatchingTextChild + style={[a.text_md]}> + Internal + </Link> + + <Link + variant="solid" + color="primary" + size="large" + label="View @bsky.app's profile" + to="https://bsky.app/profile/bsky.app"> + <ButtonText>Link as a button</ButtonText> + </Link> + </View> + </View> + ) +} diff --git a/src/view/screens/Storybook/Palette.tsx b/src/view/screens/Storybook/Palette.tsx new file mode 100644 index 000000000..b521fe860 --- /dev/null +++ b/src/view/screens/Storybook/Palette.tsx @@ -0,0 +1,336 @@ +import React from 'react' +import {View} from 'react-native' + +import * as tokens from '#/alf/tokens' +import {atoms as a} from '#/alf' + +export function Palette() { + return ( + <View style={[a.gap_md]}> + <View style={[a.flex_row, a.gap_md]}> + <View + style={[a.flex_1, {height: 60, backgroundColor: tokens.color.gray_0}]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_25}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_50}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_100}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_200}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_300}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_400}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_500}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_600}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_700}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_800}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_900}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_950}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_975}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_1000}, + ]} + /> + </View> + + <View style={[a.flex_row, a.gap_md]}> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.blue_25}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.blue_50}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.blue_100}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.blue_200}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.blue_300}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.blue_400}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.blue_500}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.blue_600}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.blue_700}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.blue_800}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.blue_900}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.blue_950}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.blue_975}, + ]} + /> + </View> + <View style={[a.flex_row, a.gap_md]}> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.green_25}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.green_50}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.green_100}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.green_200}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.green_300}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.green_400}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.green_500}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.green_600}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.green_700}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.green_800}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.green_900}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.green_950}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.green_975}, + ]} + /> + </View> + <View style={[a.flex_row, a.gap_md]}> + <View + style={[a.flex_1, {height: 60, backgroundColor: tokens.color.red_25}]} + /> + <View + style={[a.flex_1, {height: 60, backgroundColor: tokens.color.red_50}]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.red_100}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.red_200}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.red_300}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.red_400}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.red_500}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.red_600}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.red_700}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.red_800}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.red_900}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.red_950}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.red_975}, + ]} + /> + </View> + </View> + ) +} diff --git a/src/view/screens/Storybook/Shadows.tsx b/src/view/screens/Storybook/Shadows.tsx new file mode 100644 index 000000000..f92112395 --- /dev/null +++ b/src/view/screens/Storybook/Shadows.tsx @@ -0,0 +1,53 @@ +import React from 'react' +import {View} from 'react-native' + +import {atoms as a, useTheme} from '#/alf' +import {H1, Text} from '#/components/Typography' + +export function Shadows() { + const t = useTheme() + + return ( + <View style={[a.gap_md]}> + <H1>Shadows</H1> + + <View style={[a.flex_row, a.gap_5xl]}> + <View + style={[ + a.flex_1, + a.justify_center, + a.px_lg, + a.py_2xl, + t.atoms.bg, + t.atoms.shadow_sm, + ]}> + <Text>shadow_sm</Text> + </View> + + <View + style={[ + a.flex_1, + a.justify_center, + a.px_lg, + a.py_2xl, + t.atoms.bg, + t.atoms.shadow_md, + ]}> + <Text>shadow_md</Text> + </View> + + <View + style={[ + a.flex_1, + a.justify_center, + a.px_lg, + a.py_2xl, + t.atoms.bg, + t.atoms.shadow_lg, + ]}> + <Text>shadow_lg</Text> + </View> + </View> + </View> + ) +} diff --git a/src/view/screens/Storybook/Spacing.tsx b/src/view/screens/Storybook/Spacing.tsx new file mode 100644 index 000000000..d7faf93a8 --- /dev/null +++ b/src/view/screens/Storybook/Spacing.tsx @@ -0,0 +1,64 @@ +import React from 'react' +import {View} from 'react-native' + +import {atoms as a, useTheme} from '#/alf' +import {Text, H1} from '#/components/Typography' + +export function Spacing() { + const t = useTheme() + return ( + <View style={[a.gap_md]}> + <H1>Spacing</H1> + + <View style={[a.flex_row, a.align_center]}> + <Text style={{width: 80}}>2xs (2px)</Text> + <View style={[a.flex_1, a.pt_2xs, t.atoms.bg_contrast_300]} /> + </View> + + <View style={[a.flex_row, a.align_center]}> + <Text style={{width: 80}}>xs (4px)</Text> + <View style={[a.flex_1, a.pt_xs, t.atoms.bg_contrast_300]} /> + </View> + + <View style={[a.flex_row, a.align_center]}> + <Text style={{width: 80}}>sm (8px)</Text> + <View style={[a.flex_1, a.pt_sm, t.atoms.bg_contrast_300]} /> + </View> + + <View style={[a.flex_row, a.align_center]}> + <Text style={{width: 80}}>md (12px)</Text> + <View style={[a.flex_1, a.pt_md, t.atoms.bg_contrast_300]} /> + </View> + + <View style={[a.flex_row, a.align_center]}> + <Text style={{width: 80}}>lg (16px)</Text> + <View style={[a.flex_1, a.pt_lg, t.atoms.bg_contrast_300]} /> + </View> + + <View style={[a.flex_row, a.align_center]}> + <Text style={{width: 80}}>xl (20px)</Text> + <View style={[a.flex_1, a.pt_xl, t.atoms.bg_contrast_300]} /> + </View> + + <View style={[a.flex_row, a.align_center]}> + <Text style={{width: 80}}>2xl (24px)</Text> + <View style={[a.flex_1, a.pt_2xl, t.atoms.bg_contrast_300]} /> + </View> + + <View style={[a.flex_row, a.align_center]}> + <Text style={{width: 80}}>3xl (28px)</Text> + <View style={[a.flex_1, a.pt_3xl, t.atoms.bg_contrast_300]} /> + </View> + + <View style={[a.flex_row, a.align_center]}> + <Text style={{width: 80}}>4xl (32px)</Text> + <View style={[a.flex_1, a.pt_4xl, t.atoms.bg_contrast_300]} /> + </View> + + <View style={[a.flex_row, a.align_center]}> + <Text style={{width: 80}}>5xl (40px)</Text> + <View style={[a.flex_1, a.pt_5xl, t.atoms.bg_contrast_300]} /> + </View> + </View> + ) +} diff --git a/src/view/screens/Storybook/Theming.tsx b/src/view/screens/Storybook/Theming.tsx new file mode 100644 index 000000000..a05443473 --- /dev/null +++ b/src/view/screens/Storybook/Theming.tsx @@ -0,0 +1,56 @@ +import React from 'react' +import {View} from 'react-native' + +import {atoms as a, useTheme} from '#/alf' +import {Text} from '#/components/Typography' +import {Palette} from './Palette' + +export function Theming() { + const t = useTheme() + + return ( + <View style={[t.atoms.bg, a.gap_lg, a.p_xl]}> + <Palette /> + + <Text style={[a.font_bold, a.pt_xl, a.px_md]}>theme.atoms.text</Text> + + <View style={[a.flex_1, t.atoms.border, a.border_t]} /> + <Text style={[a.font_bold, t.atoms.text_contrast_600, a.px_md]}> + theme.atoms.text_contrast_600 + </Text> + + <View style={[a.flex_1, t.atoms.border, a.border_t]} /> + <Text style={[a.font_bold, t.atoms.text_contrast_500, a.px_md]}> + theme.atoms.text_contrast_500 + </Text> + + <View style={[a.flex_1, t.atoms.border, a.border_t]} /> + <Text style={[a.font_bold, t.atoms.text_contrast_400, a.px_md]}> + theme.atoms.text_contrast_400 + </Text> + + <View style={[a.flex_1, t.atoms.border_contrast, a.border_t]} /> + + <View style={[a.w_full, a.gap_md]}> + <View style={[t.atoms.bg, a.justify_center, a.p_md]}> + <Text>theme.atoms.bg</Text> + </View> + <View style={[t.atoms.bg_contrast_25, a.justify_center, a.p_md]}> + <Text>theme.atoms.bg_contrast_25</Text> + </View> + <View style={[t.atoms.bg_contrast_50, a.justify_center, a.p_md]}> + <Text>theme.atoms.bg_contrast_50</Text> + </View> + <View style={[t.atoms.bg_contrast_100, a.justify_center, a.p_md]}> + <Text>theme.atoms.bg_contrast_100</Text> + </View> + <View style={[t.atoms.bg_contrast_200, a.justify_center, a.p_md]}> + <Text>theme.atoms.bg_contrast_200</Text> + </View> + <View style={[t.atoms.bg_contrast_300, a.justify_center, a.p_md]}> + <Text>theme.atoms.bg_contrast_300</Text> + </View> + </View> + </View> + ) +} diff --git a/src/view/screens/Storybook/Typography.tsx b/src/view/screens/Storybook/Typography.tsx new file mode 100644 index 000000000..2e1f04a66 --- /dev/null +++ b/src/view/screens/Storybook/Typography.tsx @@ -0,0 +1,30 @@ +import React from 'react' +import {View} from 'react-native' + +import {atoms as a} from '#/alf' +import {Text, H1, H2, H3, H4, H5, H6, P} from '#/components/Typography' + +export function Typography() { + return ( + <View style={[a.gap_md]}> + <H1>H1 Heading</H1> + <H2>H2 Heading</H2> + <H3>H3 Heading</H3> + <H4>H4 Heading</H4> + <H5>H5 Heading</H5> + <H6>H6 Heading</H6> + <P>P Paragraph</P> + + <Text style={[a.text_5xl]}>atoms.text_5xl</Text> + <Text style={[a.text_4xl]}>atoms.text_4xl</Text> + <Text style={[a.text_3xl]}>atoms.text_3xl</Text> + <Text style={[a.text_2xl]}>atoms.text_2xl</Text> + <Text style={[a.text_xl]}>atoms.text_xl</Text> + <Text style={[a.text_lg]}>atoms.text_lg</Text> + <Text style={[a.text_md]}>atoms.text_md</Text> + <Text style={[a.text_sm]}>atoms.text_sm</Text> + <Text style={[a.text_xs]}>atoms.text_xs</Text> + <Text style={[a.text_2xs]}>atoms.text_2xs</Text> + </View> + ) +} diff --git a/src/view/screens/Storybook/index.tsx b/src/view/screens/Storybook/index.tsx new file mode 100644 index 000000000..d8898f20e --- /dev/null +++ b/src/view/screens/Storybook/index.tsx @@ -0,0 +1,78 @@ +import React from 'react' +import {View} from 'react-native' +import {CenteredView, ScrollView} from '#/view/com/util/Views' + +import {atoms as a, useTheme, ThemeProvider} from '#/alf' +import {useSetColorMode} from '#/state/shell' +import {Button} from '#/components/Button' + +import {Theming} from './Theming' +import {Typography} from './Typography' +import {Spacing} from './Spacing' +import {Buttons} from './Buttons' +import {Links} from './Links' +import {Forms} from './Forms' +import {Dialogs} from './Dialogs' +import {Breakpoints} from './Breakpoints' +import {Shadows} from './Shadows' +import {Icons} from './Icons' + +export function Storybook() { + const t = useTheme() + const setColorMode = useSetColorMode() + + return ( + <ScrollView> + <CenteredView style={[t.atoms.bg]}> + <View style={[a.p_xl, a.gap_5xl, {paddingBottom: 200}]}> + <View style={[a.flex_row, a.align_start, a.gap_md]}> + <Button + variant="outline" + color="primary" + size="small" + label='Set theme to "system"' + onPress={() => setColorMode('system')}> + System + </Button> + <Button + variant="solid" + color="secondary" + size="small" + label='Set theme to "system"' + onPress={() => setColorMode('light')}> + Light + </Button> + <Button + variant="solid" + color="secondary" + size="small" + label='Set theme to "system"' + onPress={() => setColorMode('dark')}> + Dark + </Button> + </View> + + <ThemeProvider theme="light"> + <Theming /> + </ThemeProvider> + <ThemeProvider theme="dim"> + <Theming /> + </ThemeProvider> + <ThemeProvider theme="dark"> + <Theming /> + </ThemeProvider> + + <Typography /> + <Spacing /> + <Shadows /> + <Buttons /> + <Icons /> + <Links /> + <Forms /> + <Dialogs /> + <Breakpoints /> + </View> + </CenteredView> + </ScrollView> + ) +} |