Add Admonition component (#5680)
* Add Admonition component * Tweak mobile padding * Format
This commit is contained in:
+10
-1
@@ -23,7 +23,16 @@ module.exports = {
|
|||||||
'bsky-internal/avoid-unwrapped-text': [
|
'bsky-internal/avoid-unwrapped-text': [
|
||||||
'error',
|
'error',
|
||||||
{
|
{
|
||||||
impliedTextComponents: ['H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'P'],
|
impliedTextComponents: [
|
||||||
|
'H1',
|
||||||
|
'H2',
|
||||||
|
'H3',
|
||||||
|
'H4',
|
||||||
|
'H5',
|
||||||
|
'H6',
|
||||||
|
'P',
|
||||||
|
'Admonition',
|
||||||
|
],
|
||||||
impliedTextProps: [],
|
impliedTextProps: [],
|
||||||
suggestedTextWrappers: {
|
suggestedTextWrappers: {
|
||||||
Button: 'ButtonText',
|
Button: 'ButtonText',
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import {View} from 'react-native'
|
||||||
|
|
||||||
|
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
||||||
|
import {CircleInfo_Stroke2_Corner0_Rounded as ErrorIcon} from '#/components/icons/CircleInfo'
|
||||||
|
import {Eye_Stroke2_Corner0_Rounded as InfoIcon} from '#/components/icons/Eye'
|
||||||
|
import {Leaf_Stroke2_Corner0_Rounded as TipIcon} from '#/components/icons/Leaf'
|
||||||
|
import {Warning_Stroke2_Corner0_Rounded as WarningIcon} from '#/components/icons/Warning'
|
||||||
|
import {Text as BaseText, TextProps} from '#/components/Typography'
|
||||||
|
|
||||||
|
const colors = {
|
||||||
|
warning: {
|
||||||
|
light: '#DFBC00',
|
||||||
|
dark: '#BFAF1F',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
type Context = {
|
||||||
|
type: 'info' | 'tip' | 'warning' | 'error'
|
||||||
|
}
|
||||||
|
|
||||||
|
const Context = React.createContext<Context>({
|
||||||
|
type: 'info',
|
||||||
|
})
|
||||||
|
|
||||||
|
export function Icon() {
|
||||||
|
const t = useTheme()
|
||||||
|
const {type} = React.useContext(Context)
|
||||||
|
const Icon = {
|
||||||
|
info: InfoIcon,
|
||||||
|
tip: TipIcon,
|
||||||
|
warning: WarningIcon,
|
||||||
|
error: ErrorIcon,
|
||||||
|
}[type]
|
||||||
|
const fill = {
|
||||||
|
info: t.atoms.text_contrast_medium.color,
|
||||||
|
tip: t.palette.primary_500,
|
||||||
|
warning: colors.warning.light,
|
||||||
|
error: t.palette.negative_500,
|
||||||
|
}[type]
|
||||||
|
return <Icon fill={fill} size="md" />
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Text({
|
||||||
|
children,
|
||||||
|
style,
|
||||||
|
...rest
|
||||||
|
}: Pick<TextProps, 'children' | 'style'>) {
|
||||||
|
return (
|
||||||
|
<BaseText
|
||||||
|
{...rest}
|
||||||
|
style={[
|
||||||
|
a.flex_1,
|
||||||
|
a.text_sm,
|
||||||
|
a.leading_snug,
|
||||||
|
{
|
||||||
|
paddingTop: 1,
|
||||||
|
},
|
||||||
|
style,
|
||||||
|
]}>
|
||||||
|
{children}
|
||||||
|
</BaseText>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Row({children}: {children: React.ReactNode}) {
|
||||||
|
return <View style={[a.flex_row, a.gap_sm]}>{children}</View>
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Outer({
|
||||||
|
children,
|
||||||
|
type = 'info',
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode
|
||||||
|
type?: Context['type']
|
||||||
|
}) {
|
||||||
|
const t = useTheme()
|
||||||
|
const {gtMobile} = useBreakpoints()
|
||||||
|
const borderColor = {
|
||||||
|
info: t.atoms.border_contrast_low.borderColor,
|
||||||
|
tip: t.atoms.border_contrast_low.borderColor,
|
||||||
|
warning: t.atoms.border_contrast_low.borderColor,
|
||||||
|
error: t.atoms.border_contrast_low.borderColor,
|
||||||
|
}[type]
|
||||||
|
return (
|
||||||
|
<Context.Provider value={{type}}>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
gtMobile ? a.p_md : a.p_sm,
|
||||||
|
a.rounded_sm,
|
||||||
|
a.border,
|
||||||
|
t.atoms.bg_contrast_25,
|
||||||
|
{
|
||||||
|
borderColor,
|
||||||
|
},
|
||||||
|
]}>
|
||||||
|
{children}
|
||||||
|
</View>
|
||||||
|
</Context.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Admonition({
|
||||||
|
children,
|
||||||
|
type,
|
||||||
|
}: {
|
||||||
|
children: TextProps['children']
|
||||||
|
type?: Context['type']
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Outer type={type}>
|
||||||
|
<Row>
|
||||||
|
<Icon />
|
||||||
|
<Text>{children}</Text>
|
||||||
|
</Row>
|
||||||
|
</Outer>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import {View} from 'react-native'
|
||||||
|
|
||||||
|
import {atoms as a} from '#/alf'
|
||||||
|
import {Admonition} from '#/components/Admonition'
|
||||||
|
import {InlineLinkText} from '#/components/Link'
|
||||||
|
import {H1} from '#/components/Typography'
|
||||||
|
|
||||||
|
export function Admonitions() {
|
||||||
|
return (
|
||||||
|
<View style={[a.gap_md]}>
|
||||||
|
<H1>Admonitions</H1>
|
||||||
|
|
||||||
|
<Admonition>The quick brown fox jumps over the lazy dog.</Admonition>
|
||||||
|
<Admonition type="info">
|
||||||
|
How happy the blameless vestal's lot, the world forgetting by the world
|
||||||
|
forgot.{' '}
|
||||||
|
<InlineLinkText
|
||||||
|
label="test"
|
||||||
|
to="https://letterboxd.com/film/eternal-sunshine-of-the-spotless-mind/">
|
||||||
|
Eternal sunshine of the spotless mind
|
||||||
|
</InlineLinkText>
|
||||||
|
! Each pray'r accepted, and each wish resign'd.
|
||||||
|
</Admonition>
|
||||||
|
<Admonition type="tip">
|
||||||
|
The quick brown fox jumps over the lazy dog.
|
||||||
|
</Admonition>
|
||||||
|
<Admonition type="warning">
|
||||||
|
The quick brown fox jumps over the lazy dog.
|
||||||
|
</Admonition>
|
||||||
|
<Admonition type="error">
|
||||||
|
The quick brown fox jumps over the lazy dog.
|
||||||
|
</Admonition>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import {CenteredView} from '#/view/com/util/Views'
|
|||||||
import {ListContained} from '#/view/screens/Storybook/ListContained'
|
import {ListContained} from '#/view/screens/Storybook/ListContained'
|
||||||
import {atoms as a, ThemeProvider, useTheme} from '#/alf'
|
import {atoms as a, ThemeProvider, useTheme} from '#/alf'
|
||||||
import {Button, ButtonText} from '#/components/Button'
|
import {Button, ButtonText} from '#/components/Button'
|
||||||
|
import {Admonitions} from './Admonitions'
|
||||||
import {Breakpoints} from './Breakpoints'
|
import {Breakpoints} from './Breakpoints'
|
||||||
import {Buttons} from './Buttons'
|
import {Buttons} from './Buttons'
|
||||||
import {Dialogs} from './Dialogs'
|
import {Dialogs} from './Dialogs'
|
||||||
@@ -80,7 +81,7 @@ function StorybookInner() {
|
|||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<Forms />
|
<Admonitions />
|
||||||
|
|
||||||
<ThemeProvider theme="light">
|
<ThemeProvider theme="light">
|
||||||
<Theming />
|
<Theming />
|
||||||
@@ -92,6 +93,7 @@ function StorybookInner() {
|
|||||||
<Theming />
|
<Theming />
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
|
|
||||||
|
<Forms />
|
||||||
<Buttons />
|
<Buttons />
|
||||||
<Typography />
|
<Typography />
|
||||||
<Spacing />
|
<Spacing />
|
||||||
|
|||||||
Reference in New Issue
Block a user