diff options
Diffstat (limited to 'src/view/screens/Storybook')
-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 |
12 files changed, 1160 insertions, 0 deletions
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> + ) +} |