about summary refs log tree commit diff
path: root/src/components/Admonition.tsx
blob: 7c8682119d17b836b788eaa71fa0ba9d42d162f6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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>
  )
}