An ATproto social media client -- with an independent Appview.

[ALF] Theme & palette cleanup (#4769)

* Invert primary scale

* Invert negative palette

* Replace theme specific styles in Toggle

* Remove theme specific colors from Button, improves secondary solid on dark mode

* TextField

* Remove from MessageItem

* Threadgate editor

* IconCircle

* Muted words

* Generate themes from hues

* Cleanup

* Deprecate more values, fix circular import

* Invert positive too, hardly use

* Button tweaks, some theme diffs

* Match disabled state for negative button

* Fix unread noty bg

authored by

Eric Bailey and committed by
GitHub
74186950 ea0586cd

+836 -639
+16 -5
src/alf/index.tsx
··· 1 1 import React from 'react' 2 2 import {Dimensions} from 'react-native' 3 3 4 - import * as themes from '#/alf/themes' 4 + import {createThemes, defaultTheme} from '#/alf/themes' 5 + import {Theme, ThemeName} from '#/alf/types' 6 + import {BLUE_HUE, GREEN_HUE, RED_HUE} from '#/alf/util/colorGeneration' 5 7 6 8 export {atoms} from '#/alf/atoms' 7 9 export * as tokens from '#/alf/tokens' ··· 39 41 * Context 40 42 */ 41 43 export const Context = React.createContext<{ 42 - themeName: themes.ThemeName 43 - theme: themes.Theme 44 + themeName: ThemeName 45 + theme: Theme 44 46 breakpoints: { 45 47 active: BreakpointName | undefined 46 48 gtPhone: boolean ··· 49 51 } 50 52 }>({ 51 53 themeName: 'light', 52 - theme: themes.light, 54 + theme: defaultTheme, 53 55 breakpoints: { 54 56 active: undefined, 55 57 gtPhone: false, ··· 61 63 export function ThemeProvider({ 62 64 children, 63 65 theme: themeName, 64 - }: React.PropsWithChildren<{theme: themes.ThemeName}>) { 66 + }: React.PropsWithChildren<{theme: ThemeName}>) { 67 + const themes = React.useMemo(() => { 68 + return createThemes({ 69 + hues: { 70 + primary: BLUE_HUE, 71 + negative: RED_HUE, 72 + positive: GREEN_HUE, 73 + }, 74 + }) 75 + }, []) 65 76 const theme = themes[themeName] 66 77 const [breakpoints, setBreakpoints] = React.useState(() => 67 78 getActiveBreakpoints({width: Dimensions.get('window').width}),
+554 -432
src/alf/themes.ts
··· 1 1 import {atoms} from '#/alf/atoms' 2 - import * as tokens from '#/alf/tokens' 3 - import type {Mutable} from '#/alf/types' 4 - import {BLUE_HUE, GREEN_HUE, RED_HUE} from '#/alf/util/colorGeneration' 2 + import {Palette, Theme} from '#/alf/types' 3 + import { 4 + BLUE_HUE, 5 + defaultScale, 6 + dimScale, 7 + GREEN_HUE, 8 + RED_HUE, 9 + } from '#/alf/util/colorGeneration' 5 10 6 - export type ThemeName = 'light' | 'dim' | 'dark' 7 - export type ReadonlyTheme = typeof light 8 - export type Theme = Mutable<ReadonlyTheme> & {name: ThemeName} 9 - export type ReadonlyPalette = typeof lightPalette 10 - export type Palette = Mutable<ReadonlyPalette> 11 + const themes = createThemes({ 12 + hues: { 13 + primary: BLUE_HUE, 14 + negative: RED_HUE, 15 + positive: GREEN_HUE, 16 + }, 17 + }) 11 18 12 - export const lightPalette = { 13 - white: tokens.color.gray_0, 14 - black: tokens.color.gray_1000, 19 + /** 20 + * @deprecated use ALF and access palette from `useTheme()` 21 + */ 22 + export const lightPalette = themes.lightPalette 23 + /** 24 + * @deprecated use ALF and access palette from `useTheme()` 25 + */ 26 + export const darkPalette = themes.darkPalette 27 + /** 28 + * @deprecated use ALF and access palette from `useTheme()` 29 + */ 30 + export const dimPalette = themes.dimPalette 31 + /** 32 + * @deprecated use ALF and access theme from `useTheme()` 33 + */ 34 + export const light = themes.light 35 + /** 36 + * @deprecated use ALF and access theme from `useTheme()` 37 + */ 38 + export const dark = themes.dark 39 + /** 40 + * @deprecated use ALF and access theme from `useTheme()` 41 + */ 42 + export const dim = themes.dim 15 43 16 - contrast_25: tokens.color.gray_25, 17 - contrast_50: tokens.color.gray_50, 18 - contrast_100: tokens.color.gray_100, 19 - contrast_200: tokens.color.gray_200, 20 - contrast_300: tokens.color.gray_300, 21 - contrast_400: tokens.color.gray_400, 22 - contrast_500: tokens.color.gray_500, 23 - contrast_600: tokens.color.gray_600, 24 - contrast_700: tokens.color.gray_700, 25 - contrast_800: tokens.color.gray_800, 26 - contrast_900: tokens.color.gray_900, 27 - contrast_950: tokens.color.gray_950, 28 - contrast_975: tokens.color.gray_975, 44 + export const defaultTheme = themes.light 29 45 30 - primary_25: tokens.color.blue_25, 31 - primary_50: tokens.color.blue_50, 32 - primary_100: tokens.color.blue_100, 33 - primary_200: tokens.color.blue_200, 34 - primary_300: tokens.color.blue_300, 35 - primary_400: tokens.color.blue_400, 36 - primary_500: tokens.color.blue_500, 37 - primary_600: tokens.color.blue_600, 38 - primary_700: tokens.color.blue_700, 39 - primary_800: tokens.color.blue_800, 40 - primary_900: tokens.color.blue_900, 41 - primary_950: tokens.color.blue_950, 42 - primary_975: tokens.color.blue_975, 46 + export function createThemes({ 47 + hues, 48 + }: { 49 + hues: { 50 + primary: number 51 + negative: number 52 + positive: number 53 + } 54 + }): { 55 + lightPalette: Palette 56 + darkPalette: Palette 57 + dimPalette: Palette 58 + light: Theme 59 + dark: Theme 60 + dim: Theme 61 + } { 62 + const color = { 63 + trueBlack: '#000000', 43 64 44 - positive_25: tokens.color.green_25, 45 - positive_50: tokens.color.green_50, 46 - positive_100: tokens.color.green_100, 47 - positive_200: tokens.color.green_200, 48 - positive_300: tokens.color.green_300, 49 - positive_400: tokens.color.green_400, 50 - positive_500: tokens.color.green_500, 51 - positive_600: tokens.color.green_600, 52 - positive_700: tokens.color.green_700, 53 - positive_800: tokens.color.green_800, 54 - positive_900: tokens.color.green_900, 55 - positive_950: tokens.color.green_950, 56 - positive_975: tokens.color.green_975, 65 + gray_0: `hsl(${hues.primary}, 20%, ${defaultScale[14]}%)`, 66 + gray_25: `hsl(${hues.primary}, 20%, ${defaultScale[13]}%)`, 67 + gray_50: `hsl(${hues.primary}, 20%, ${defaultScale[12]}%)`, 68 + gray_100: `hsl(${hues.primary}, 20%, ${defaultScale[11]}%)`, 69 + gray_200: `hsl(${hues.primary}, 20%, ${defaultScale[10]}%)`, 70 + gray_300: `hsl(${hues.primary}, 20%, ${defaultScale[9]}%)`, 71 + gray_400: `hsl(${hues.primary}, 20%, ${defaultScale[8]}%)`, 72 + gray_500: `hsl(${hues.primary}, 20%, ${defaultScale[7]}%)`, 73 + gray_600: `hsl(${hues.primary}, 24%, ${defaultScale[6]}%)`, 74 + gray_700: `hsl(${hues.primary}, 24%, ${defaultScale[5]}%)`, 75 + gray_800: `hsl(${hues.primary}, 28%, ${defaultScale[4]}%)`, 76 + gray_900: `hsl(${hues.primary}, 28%, ${defaultScale[3]}%)`, 77 + gray_950: `hsl(${hues.primary}, 28%, ${defaultScale[2]}%)`, 78 + gray_975: `hsl(${hues.primary}, 28%, ${defaultScale[1]}%)`, 79 + gray_1000: `hsl(${hues.primary}, 28%, ${defaultScale[0]}%)`, 57 80 58 - negative_25: tokens.color.red_25, 59 - negative_50: tokens.color.red_50, 60 - negative_100: tokens.color.red_100, 61 - negative_200: tokens.color.red_200, 62 - negative_300: tokens.color.red_300, 63 - negative_400: tokens.color.red_400, 64 - negative_500: tokens.color.red_500, 65 - negative_600: tokens.color.red_600, 66 - negative_700: tokens.color.red_700, 67 - negative_800: tokens.color.red_800, 68 - negative_900: tokens.color.red_900, 69 - negative_950: tokens.color.red_950, 70 - negative_975: tokens.color.red_975, 71 - } as const 81 + primary_25: `hsl(${hues.primary}, 99%, 97%)`, 82 + primary_50: `hsl(${hues.primary}, 99%, 95%)`, 83 + primary_100: `hsl(${hues.primary}, 99%, 90%)`, 84 + primary_200: `hsl(${hues.primary}, 99%, 80%)`, 85 + primary_300: `hsl(${hues.primary}, 99%, 70%)`, 86 + primary_400: `hsl(${hues.primary}, 99%, 60%)`, 87 + primary_500: `hsl(${hues.primary}, 99%, 53%)`, 88 + primary_600: `hsl(${hues.primary}, 99%, 42%)`, 89 + primary_700: `hsl(${hues.primary}, 99%, 34%)`, 90 + primary_800: `hsl(${hues.primary}, 99%, 26%)`, 91 + primary_900: `hsl(${hues.primary}, 99%, 18%)`, 92 + primary_950: `hsl(${hues.primary}, 99%, 10%)`, 93 + primary_975: `hsl(${hues.primary}, 99%, 7%)`, 72 94 73 - export const darkPalette: Palette = { 74 - white: tokens.color.gray_0, 75 - black: tokens.color.trueBlack, 95 + green_25: `hsl(${hues.positive}, 82%, 97%)`, 96 + green_50: `hsl(${hues.positive}, 82%, 95%)`, 97 + green_100: `hsl(${hues.positive}, 82%, 90%)`, 98 + green_200: `hsl(${hues.positive}, 82%, 80%)`, 99 + green_300: `hsl(${hues.positive}, 82%, 70%)`, 100 + green_400: `hsl(${hues.positive}, 82%, 60%)`, 101 + green_500: `hsl(${hues.positive}, 82%, 50%)`, 102 + green_600: `hsl(${hues.positive}, 82%, 42%)`, 103 + green_700: `hsl(${hues.positive}, 82%, 34%)`, 104 + green_800: `hsl(${hues.positive}, 82%, 26%)`, 105 + green_900: `hsl(${hues.positive}, 82%, 18%)`, 106 + green_950: `hsl(${hues.positive}, 82%, 10%)`, 107 + green_975: `hsl(${hues.positive}, 82%, 7%)`, 76 108 77 - contrast_25: tokens.color.gray_1000, 78 - contrast_50: tokens.color.gray_975, 79 - contrast_100: tokens.color.gray_950, 80 - contrast_200: tokens.color.gray_900, 81 - contrast_300: tokens.color.gray_800, 82 - contrast_400: tokens.color.gray_700, 83 - contrast_500: tokens.color.gray_600, 84 - contrast_600: tokens.color.gray_500, 85 - contrast_700: tokens.color.gray_400, 86 - contrast_800: tokens.color.gray_300, 87 - contrast_900: tokens.color.gray_200, 88 - contrast_950: tokens.color.gray_100, 89 - contrast_975: tokens.color.gray_50, 109 + red_25: `hsl(${hues.negative}, 91%, 97%)`, 110 + red_50: `hsl(${hues.negative}, 91%, 95%)`, 111 + red_100: `hsl(${hues.negative}, 91%, 90%)`, 112 + red_200: `hsl(${hues.negative}, 91%, 80%)`, 113 + red_300: `hsl(${hues.negative}, 91%, 70%)`, 114 + red_400: `hsl(${hues.negative}, 91%, 60%)`, 115 + red_500: `hsl(${hues.negative}, 91%, 50%)`, 116 + red_600: `hsl(${hues.negative}, 91%, 42%)`, 117 + red_700: `hsl(${hues.negative}, 91%, 34%)`, 118 + red_800: `hsl(${hues.negative}, 91%, 26%)`, 119 + red_900: `hsl(${hues.negative}, 91%, 18%)`, 120 + red_950: `hsl(${hues.negative}, 91%, 10%)`, 121 + red_975: `hsl(${hues.negative}, 91%, 7%)`, 122 + } as const 90 123 91 - primary_25: tokens.color.blue_25, 92 - primary_50: tokens.color.blue_50, 93 - primary_100: tokens.color.blue_100, 94 - primary_200: tokens.color.blue_200, 95 - primary_300: tokens.color.blue_300, 96 - primary_400: tokens.color.blue_400, 97 - primary_500: tokens.color.blue_500, 98 - primary_600: tokens.color.blue_600, 99 - primary_700: tokens.color.blue_700, 100 - primary_800: tokens.color.blue_800, 101 - primary_900: tokens.color.blue_900, 102 - primary_950: tokens.color.blue_950, 103 - primary_975: tokens.color.blue_975, 124 + const lightPalette = { 125 + white: color.gray_0, 126 + black: color.gray_1000, 104 127 105 - positive_25: tokens.color.green_25, 106 - positive_50: tokens.color.green_50, 107 - positive_100: tokens.color.green_100, 108 - positive_200: tokens.color.green_200, 109 - positive_300: tokens.color.green_300, 110 - positive_400: tokens.color.green_400, 111 - positive_500: tokens.color.green_500, 112 - positive_600: tokens.color.green_600, 113 - positive_700: tokens.color.green_700, 114 - positive_800: tokens.color.green_800, 115 - positive_900: tokens.color.green_900, 116 - positive_950: tokens.color.green_950, 117 - positive_975: tokens.color.green_975, 128 + contrast_25: color.gray_25, 129 + contrast_50: color.gray_50, 130 + contrast_100: color.gray_100, 131 + contrast_200: color.gray_200, 132 + contrast_300: color.gray_300, 133 + contrast_400: color.gray_400, 134 + contrast_500: color.gray_500, 135 + contrast_600: color.gray_600, 136 + contrast_700: color.gray_700, 137 + contrast_800: color.gray_800, 138 + contrast_900: color.gray_900, 139 + contrast_950: color.gray_950, 140 + contrast_975: color.gray_975, 118 141 119 - negative_25: tokens.color.red_25, 120 - negative_50: tokens.color.red_50, 121 - negative_100: tokens.color.red_100, 122 - negative_200: tokens.color.red_200, 123 - negative_300: tokens.color.red_300, 124 - negative_400: tokens.color.red_400, 125 - negative_500: tokens.color.red_500, 126 - negative_600: tokens.color.red_600, 127 - negative_700: tokens.color.red_700, 128 - negative_800: tokens.color.red_800, 129 - negative_900: tokens.color.red_900, 130 - negative_950: tokens.color.red_950, 131 - negative_975: tokens.color.red_975, 132 - } as const 142 + primary_25: color.primary_25, 143 + primary_50: color.primary_50, 144 + primary_100: color.primary_100, 145 + primary_200: color.primary_200, 146 + primary_300: color.primary_300, 147 + primary_400: color.primary_400, 148 + primary_500: color.primary_500, 149 + primary_600: color.primary_600, 150 + primary_700: color.primary_700, 151 + primary_800: color.primary_800, 152 + primary_900: color.primary_900, 153 + primary_950: color.primary_950, 154 + primary_975: color.primary_975, 133 155 134 - export const dimPalette: Palette = { 135 - ...darkPalette, 136 - black: `hsl(${BLUE_HUE}, 28%, ${tokens.dimScale[0]}%)`, 156 + positive_25: color.green_25, 157 + positive_50: color.green_50, 158 + positive_100: color.green_100, 159 + positive_200: color.green_200, 160 + positive_300: color.green_300, 161 + positive_400: color.green_400, 162 + positive_500: color.green_500, 163 + positive_600: color.green_600, 164 + positive_700: color.green_700, 165 + positive_800: color.green_800, 166 + positive_900: color.green_900, 167 + positive_950: color.green_950, 168 + positive_975: color.green_975, 137 169 138 - contrast_25: `hsl(${BLUE_HUE}, 28%, ${tokens.dimScale[1]}%)`, 139 - contrast_50: `hsl(${BLUE_HUE}, 28%, ${tokens.dimScale[2]}%)`, 140 - contrast_100: `hsl(${BLUE_HUE}, 28%, ${tokens.dimScale[3]}%)`, 141 - contrast_200: `hsl(${BLUE_HUE}, 28%, ${tokens.dimScale[4]}%)`, 142 - contrast_300: `hsl(${BLUE_HUE}, 24%, ${tokens.dimScale[5]}%)`, 143 - contrast_400: `hsl(${BLUE_HUE}, 24%, ${tokens.dimScale[6]}%)`, 144 - contrast_500: `hsl(${BLUE_HUE}, 20%, ${tokens.dimScale[7]}%)`, 145 - contrast_600: `hsl(${BLUE_HUE}, 20%, ${tokens.dimScale[8]}%)`, 146 - contrast_700: `hsl(${BLUE_HUE}, 20%, ${tokens.dimScale[9]}%)`, 147 - contrast_800: `hsl(${BLUE_HUE}, 20%, ${tokens.dimScale[10]}%)`, 148 - contrast_900: `hsl(${BLUE_HUE}, 20%, ${tokens.dimScale[11]}%)`, 149 - contrast_950: `hsl(${BLUE_HUE}, 20%, ${tokens.dimScale[12]}%)`, 150 - contrast_975: `hsl(${BLUE_HUE}, 20%, ${tokens.dimScale[13]}%)`, 170 + negative_25: color.red_25, 171 + negative_50: color.red_50, 172 + negative_100: color.red_100, 173 + negative_200: color.red_200, 174 + negative_300: color.red_300, 175 + negative_400: color.red_400, 176 + negative_500: color.red_500, 177 + negative_600: color.red_600, 178 + negative_700: color.red_700, 179 + negative_800: color.red_800, 180 + negative_900: color.red_900, 181 + negative_950: color.red_950, 182 + negative_975: color.red_975, 183 + } as const 151 184 152 - primary_25: `hsl(${BLUE_HUE}, 99%, ${tokens.dimScale[13]}%)`, 153 - primary_50: `hsl(${BLUE_HUE}, 99%, ${tokens.dimScale[12]}%)`, 154 - primary_100: `hsl(${BLUE_HUE}, 99%, ${tokens.dimScale[11]}%)`, 155 - primary_200: `hsl(${BLUE_HUE}, 99%, ${tokens.dimScale[10]}%)`, 156 - primary_300: `hsl(${BLUE_HUE}, 99%, ${tokens.dimScale[9]}%)`, 157 - primary_400: `hsl(${BLUE_HUE}, 99%, ${tokens.dimScale[8]}%)`, 158 - primary_500: `hsl(${BLUE_HUE}, 99%, ${tokens.dimScale[7]}%)`, 159 - primary_600: `hsl(${BLUE_HUE}, 95%, ${tokens.dimScale[6]}%)`, 160 - primary_700: `hsl(${BLUE_HUE}, 90%, ${tokens.dimScale[5]}%)`, 161 - primary_800: `hsl(${BLUE_HUE}, 82%, ${tokens.dimScale[4]}%)`, 162 - primary_900: `hsl(${BLUE_HUE}, 70%, ${tokens.dimScale[3]}%)`, 163 - primary_950: `hsl(${BLUE_HUE}, 60%, ${tokens.dimScale[2]}%)`, 164 - primary_975: `hsl(${BLUE_HUE}, 50%, ${tokens.dimScale[1]}%)`, 185 + const darkPalette: Palette = { 186 + white: color.gray_0, 187 + black: color.trueBlack, 165 188 166 - positive_25: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[13]}%)`, 167 - positive_50: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[12]}%)`, 168 - positive_100: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[11]}%)`, 169 - positive_200: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[10]}%)`, 170 - positive_300: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[9]}%)`, 171 - positive_400: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[8]}%)`, 172 - positive_500: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[7]}%)`, 173 - positive_600: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[6]}%)`, 174 - positive_700: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[5]}%)`, 175 - positive_800: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[4]}%)`, 176 - positive_900: `hsl(${GREEN_HUE}, 70%, ${tokens.dimScale[3]}%)`, 177 - positive_950: `hsl(${GREEN_HUE}, 60%, ${tokens.dimScale[2]}%)`, 178 - positive_975: `hsl(${GREEN_HUE}, 50%, ${tokens.dimScale[1]}%)`, 189 + contrast_25: color.gray_1000, 190 + contrast_50: color.gray_975, 191 + contrast_100: color.gray_950, 192 + contrast_200: color.gray_900, 193 + contrast_300: color.gray_800, 194 + contrast_400: color.gray_700, 195 + contrast_500: color.gray_600, 196 + contrast_600: color.gray_500, 197 + contrast_700: color.gray_400, 198 + contrast_800: color.gray_300, 199 + contrast_900: color.gray_200, 200 + contrast_950: color.gray_100, 201 + contrast_975: color.gray_50, 179 202 180 - negative_25: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[13]}%)`, 181 - negative_50: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[12]}%)`, 182 - negative_100: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[11]}%)`, 183 - negative_200: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[10]}%)`, 184 - negative_300: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[9]}%)`, 185 - negative_400: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[8]}%)`, 186 - negative_500: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[7]}%)`, 187 - negative_600: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[6]}%)`, 188 - negative_700: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[5]}%)`, 189 - negative_800: `hsl(${RED_HUE}, 88%, ${tokens.dimScale[4]}%)`, 190 - negative_900: `hsl(${RED_HUE}, 84%, ${tokens.dimScale[3]}%)`, 191 - negative_950: `hsl(${RED_HUE}, 80%, ${tokens.dimScale[2]}%)`, 192 - negative_975: `hsl(${RED_HUE}, 70%, ${tokens.dimScale[1]}%)`, 193 - } as const 203 + primary_25: color.primary_975, 204 + primary_50: color.primary_950, 205 + primary_100: color.primary_900, 206 + primary_200: color.primary_800, 207 + primary_300: color.primary_700, 208 + primary_400: color.primary_600, 209 + primary_500: color.primary_500, 210 + primary_600: color.primary_400, 211 + primary_700: color.primary_300, 212 + primary_800: color.primary_200, 213 + primary_900: color.primary_100, 214 + primary_950: color.primary_50, 215 + primary_975: color.primary_25, 194 216 195 - export const light = { 196 - name: 'light' as ThemeName, 197 - palette: lightPalette, 198 - atoms: { 199 - text: { 200 - color: lightPalette.black, 201 - }, 202 - text_contrast_low: { 203 - color: lightPalette.contrast_400, 204 - }, 205 - text_contrast_medium: { 206 - color: lightPalette.contrast_700, 207 - }, 208 - text_contrast_high: { 209 - color: lightPalette.contrast_900, 210 - }, 211 - text_inverted: { 212 - color: lightPalette.white, 213 - }, 214 - bg: { 215 - backgroundColor: lightPalette.white, 216 - }, 217 - bg_contrast_25: { 218 - backgroundColor: lightPalette.contrast_25, 219 - }, 220 - bg_contrast_50: { 221 - backgroundColor: lightPalette.contrast_50, 222 - }, 223 - bg_contrast_100: { 224 - backgroundColor: lightPalette.contrast_100, 225 - }, 226 - bg_contrast_200: { 227 - backgroundColor: lightPalette.contrast_200, 228 - }, 229 - bg_contrast_300: { 230 - backgroundColor: lightPalette.contrast_300, 231 - }, 232 - bg_contrast_400: { 233 - backgroundColor: lightPalette.contrast_400, 234 - }, 235 - bg_contrast_500: { 236 - backgroundColor: lightPalette.contrast_500, 237 - }, 238 - bg_contrast_600: { 239 - backgroundColor: lightPalette.contrast_600, 240 - }, 241 - bg_contrast_700: { 242 - backgroundColor: lightPalette.contrast_700, 243 - }, 244 - bg_contrast_800: { 245 - backgroundColor: lightPalette.contrast_800, 246 - }, 247 - bg_contrast_900: { 248 - backgroundColor: lightPalette.contrast_900, 249 - }, 250 - bg_contrast_950: { 251 - backgroundColor: lightPalette.contrast_950, 252 - }, 253 - bg_contrast_975: { 254 - backgroundColor: lightPalette.contrast_975, 255 - }, 256 - border_contrast_low: { 257 - borderColor: lightPalette.contrast_100, 258 - }, 259 - border_contrast_medium: { 260 - borderColor: lightPalette.contrast_200, 261 - }, 262 - border_contrast_high: { 263 - borderColor: lightPalette.contrast_300, 264 - }, 265 - shadow_sm: { 266 - ...atoms.shadow_sm, 267 - shadowColor: lightPalette.black, 268 - }, 269 - shadow_md: { 270 - ...atoms.shadow_md, 271 - shadowColor: lightPalette.black, 272 - }, 273 - shadow_lg: { 274 - ...atoms.shadow_lg, 275 - shadowColor: lightPalette.black, 276 - }, 277 - }, 278 - } 217 + positive_25: color.green_975, 218 + positive_50: color.green_950, 219 + positive_100: color.green_900, 220 + positive_200: color.green_800, 221 + positive_300: color.green_700, 222 + positive_400: color.green_600, 223 + positive_500: color.green_500, 224 + positive_600: color.green_400, 225 + positive_700: color.green_300, 226 + positive_800: color.green_200, 227 + positive_900: color.green_100, 228 + positive_950: color.green_50, 229 + positive_975: color.green_25, 279 230 280 - export const dark: Theme = { 281 - name: 'dark' as ThemeName, 282 - palette: darkPalette, 283 - atoms: { 284 - text: { 285 - color: darkPalette.white, 286 - }, 287 - text_contrast_low: { 288 - color: darkPalette.contrast_400, 289 - }, 290 - text_contrast_medium: { 291 - color: darkPalette.contrast_700, 292 - }, 293 - text_contrast_high: { 294 - color: darkPalette.contrast_900, 295 - }, 296 - text_inverted: { 297 - color: darkPalette.black, 298 - }, 299 - bg: { 300 - backgroundColor: darkPalette.black, 301 - }, 302 - bg_contrast_25: { 303 - backgroundColor: darkPalette.contrast_25, 231 + negative_25: color.red_975, 232 + negative_50: color.red_950, 233 + negative_100: color.red_900, 234 + negative_200: color.red_800, 235 + negative_300: color.red_700, 236 + negative_400: color.red_600, 237 + negative_500: color.red_500, 238 + negative_600: color.red_400, 239 + negative_700: color.red_300, 240 + negative_800: color.red_200, 241 + negative_900: color.red_100, 242 + negative_950: color.red_50, 243 + negative_975: color.red_25, 244 + } as const 245 + 246 + const dimPalette: Palette = { 247 + ...darkPalette, 248 + black: `hsl(${hues.primary}, 28%, ${dimScale[0]}%)`, 249 + 250 + contrast_25: `hsl(${hues.primary}, 28%, ${dimScale[1]}%)`, 251 + contrast_50: `hsl(${hues.primary}, 28%, ${dimScale[2]}%)`, 252 + contrast_100: `hsl(${hues.primary}, 28%, ${dimScale[3]}%)`, 253 + contrast_200: `hsl(${hues.primary}, 28%, ${dimScale[4]}%)`, 254 + contrast_300: `hsl(${hues.primary}, 24%, ${dimScale[5]}%)`, 255 + contrast_400: `hsl(${hues.primary}, 24%, ${dimScale[6]}%)`, 256 + contrast_500: `hsl(${hues.primary}, 20%, ${dimScale[7]}%)`, 257 + contrast_600: `hsl(${hues.primary}, 20%, ${dimScale[8]}%)`, 258 + contrast_700: `hsl(${hues.primary}, 20%, ${dimScale[9]}%)`, 259 + contrast_800: `hsl(${hues.primary}, 20%, ${dimScale[10]}%)`, 260 + contrast_900: `hsl(${hues.primary}, 20%, ${dimScale[11]}%)`, 261 + contrast_950: `hsl(${hues.primary}, 20%, ${dimScale[12]}%)`, 262 + contrast_975: `hsl(${hues.primary}, 20%, ${dimScale[13]}%)`, 263 + 264 + primary_25: `hsl(${hues.primary}, 99%, ${dimScale[1]}%)`, 265 + primary_50: `hsl(${hues.primary}, 99%, ${dimScale[2]}%)`, 266 + primary_100: `hsl(${hues.primary}, 99%, ${dimScale[3]}%)`, 267 + primary_200: `hsl(${hues.primary}, 99%, ${dimScale[4]}%)`, 268 + primary_300: `hsl(${hues.primary}, 99%, ${dimScale[5]}%)`, 269 + primary_400: `hsl(${hues.primary}, 99%, ${dimScale[6]}%)`, 270 + primary_500: `hsl(${hues.primary}, 99%, ${dimScale[7]}%)`, 271 + primary_600: `hsl(${hues.primary}, 95%, ${dimScale[8]}%)`, 272 + primary_700: `hsl(${hues.primary}, 90%, ${dimScale[9]}%)`, 273 + primary_800: `hsl(${hues.primary}, 82%, ${dimScale[10]}%)`, 274 + primary_900: `hsl(${hues.primary}, 70%, ${dimScale[11]}%)`, 275 + primary_950: `hsl(${hues.primary}, 60%, ${dimScale[12]}%)`, 276 + primary_975: `hsl(${hues.primary}, 50%, ${dimScale[13]}%)`, 277 + 278 + positive_25: `hsl(${hues.positive}, 82%, ${dimScale[1]}%)`, 279 + positive_50: `hsl(${hues.positive}, 82%, ${dimScale[2]}%)`, 280 + positive_100: `hsl(${hues.positive}, 82%, ${dimScale[3]}%)`, 281 + positive_200: `hsl(${hues.positive}, 82%, ${dimScale[4]}%)`, 282 + positive_300: `hsl(${hues.positive}, 82%, ${dimScale[5]}%)`, 283 + positive_400: `hsl(${hues.positive}, 82%, ${dimScale[6]}%)`, 284 + positive_500: `hsl(${hues.positive}, 82%, ${dimScale[7]}%)`, 285 + positive_600: `hsl(${hues.positive}, 82%, ${dimScale[8]}%)`, 286 + positive_700: `hsl(${hues.positive}, 82%, ${dimScale[9]}%)`, 287 + positive_800: `hsl(${hues.positive}, 82%, ${dimScale[10]}%)`, 288 + positive_900: `hsl(${hues.positive}, 70%, ${dimScale[11]}%)`, 289 + positive_950: `hsl(${hues.positive}, 60%, ${dimScale[12]}%)`, 290 + positive_975: `hsl(${hues.positive}, 50%, ${dimScale[13]}%)`, 291 + 292 + negative_25: `hsl(${hues.negative}, 91%, ${dimScale[1]}%)`, 293 + negative_50: `hsl(${hues.negative}, 91%, ${dimScale[2]}%)`, 294 + negative_100: `hsl(${hues.negative}, 91%, ${dimScale[3]}%)`, 295 + negative_200: `hsl(${hues.negative}, 91%, ${dimScale[4]}%)`, 296 + negative_300: `hsl(${hues.negative}, 91%, ${dimScale[5]}%)`, 297 + negative_400: `hsl(${hues.negative}, 91%, ${dimScale[6]}%)`, 298 + negative_500: `hsl(${hues.negative}, 91%, ${dimScale[7]}%)`, 299 + negative_600: `hsl(${hues.negative}, 91%, ${dimScale[8]}%)`, 300 + negative_700: `hsl(${hues.negative}, 91%, ${dimScale[9]}%)`, 301 + negative_800: `hsl(${hues.negative}, 88%, ${dimScale[10]}%)`, 302 + negative_900: `hsl(${hues.negative}, 84%, ${dimScale[11]}%)`, 303 + negative_950: `hsl(${hues.negative}, 80%, ${dimScale[12]}%)`, 304 + negative_975: `hsl(${hues.negative}, 70%, ${dimScale[13]}%)`, 305 + } as const 306 + 307 + const light: Theme = { 308 + name: 'light', 309 + palette: lightPalette, 310 + atoms: { 311 + text: { 312 + color: lightPalette.black, 313 + }, 314 + text_contrast_low: { 315 + color: lightPalette.contrast_400, 316 + }, 317 + text_contrast_medium: { 318 + color: lightPalette.contrast_700, 319 + }, 320 + text_contrast_high: { 321 + color: lightPalette.contrast_900, 322 + }, 323 + text_inverted: { 324 + color: lightPalette.white, 325 + }, 326 + bg: { 327 + backgroundColor: lightPalette.white, 328 + }, 329 + bg_contrast_25: { 330 + backgroundColor: lightPalette.contrast_25, 331 + }, 332 + bg_contrast_50: { 333 + backgroundColor: lightPalette.contrast_50, 334 + }, 335 + bg_contrast_100: { 336 + backgroundColor: lightPalette.contrast_100, 337 + }, 338 + bg_contrast_200: { 339 + backgroundColor: lightPalette.contrast_200, 340 + }, 341 + bg_contrast_300: { 342 + backgroundColor: lightPalette.contrast_300, 343 + }, 344 + bg_contrast_400: { 345 + backgroundColor: lightPalette.contrast_400, 346 + }, 347 + bg_contrast_500: { 348 + backgroundColor: lightPalette.contrast_500, 349 + }, 350 + bg_contrast_600: { 351 + backgroundColor: lightPalette.contrast_600, 352 + }, 353 + bg_contrast_700: { 354 + backgroundColor: lightPalette.contrast_700, 355 + }, 356 + bg_contrast_800: { 357 + backgroundColor: lightPalette.contrast_800, 358 + }, 359 + bg_contrast_900: { 360 + backgroundColor: lightPalette.contrast_900, 361 + }, 362 + bg_contrast_950: { 363 + backgroundColor: lightPalette.contrast_950, 364 + }, 365 + bg_contrast_975: { 366 + backgroundColor: lightPalette.contrast_975, 367 + }, 368 + border_contrast_low: { 369 + borderColor: lightPalette.contrast_100, 370 + }, 371 + border_contrast_medium: { 372 + borderColor: lightPalette.contrast_200, 373 + }, 374 + border_contrast_high: { 375 + borderColor: lightPalette.contrast_300, 376 + }, 377 + shadow_sm: { 378 + ...atoms.shadow_sm, 379 + shadowColor: lightPalette.black, 380 + }, 381 + shadow_md: { 382 + ...atoms.shadow_md, 383 + shadowColor: lightPalette.black, 384 + }, 385 + shadow_lg: { 386 + ...atoms.shadow_lg, 387 + shadowColor: lightPalette.black, 388 + }, 304 389 }, 305 - bg_contrast_50: { 306 - backgroundColor: darkPalette.contrast_50, 390 + } 391 + 392 + const dark: Theme = { 393 + name: 'dark', 394 + palette: darkPalette, 395 + atoms: { 396 + text: { 397 + color: darkPalette.white, 398 + }, 399 + text_contrast_low: { 400 + color: darkPalette.contrast_400, 401 + }, 402 + text_contrast_medium: { 403 + color: darkPalette.contrast_700, 404 + }, 405 + text_contrast_high: { 406 + color: darkPalette.contrast_900, 407 + }, 408 + text_inverted: { 409 + color: darkPalette.black, 410 + }, 411 + bg: { 412 + backgroundColor: darkPalette.black, 413 + }, 414 + bg_contrast_25: { 415 + backgroundColor: darkPalette.contrast_25, 416 + }, 417 + bg_contrast_50: { 418 + backgroundColor: darkPalette.contrast_50, 419 + }, 420 + bg_contrast_100: { 421 + backgroundColor: darkPalette.contrast_100, 422 + }, 423 + bg_contrast_200: { 424 + backgroundColor: darkPalette.contrast_200, 425 + }, 426 + bg_contrast_300: { 427 + backgroundColor: darkPalette.contrast_300, 428 + }, 429 + bg_contrast_400: { 430 + backgroundColor: darkPalette.contrast_400, 431 + }, 432 + bg_contrast_500: { 433 + backgroundColor: darkPalette.contrast_500, 434 + }, 435 + bg_contrast_600: { 436 + backgroundColor: darkPalette.contrast_600, 437 + }, 438 + bg_contrast_700: { 439 + backgroundColor: darkPalette.contrast_700, 440 + }, 441 + bg_contrast_800: { 442 + backgroundColor: darkPalette.contrast_800, 443 + }, 444 + bg_contrast_900: { 445 + backgroundColor: darkPalette.contrast_900, 446 + }, 447 + bg_contrast_950: { 448 + backgroundColor: darkPalette.contrast_950, 449 + }, 450 + bg_contrast_975: { 451 + backgroundColor: darkPalette.contrast_975, 452 + }, 453 + border_contrast_low: { 454 + borderColor: darkPalette.contrast_100, 455 + }, 456 + border_contrast_medium: { 457 + borderColor: darkPalette.contrast_200, 458 + }, 459 + border_contrast_high: { 460 + borderColor: darkPalette.contrast_300, 461 + }, 462 + shadow_sm: { 463 + ...atoms.shadow_sm, 464 + shadowOpacity: 0.7, 465 + shadowColor: color.trueBlack, 466 + }, 467 + shadow_md: { 468 + ...atoms.shadow_md, 469 + shadowOpacity: 0.7, 470 + shadowColor: color.trueBlack, 471 + }, 472 + shadow_lg: { 473 + ...atoms.shadow_lg, 474 + shadowOpacity: 0.7, 475 + shadowColor: color.trueBlack, 476 + }, 307 477 }, 308 - bg_contrast_100: { 309 - backgroundColor: darkPalette.contrast_100, 310 - }, 311 - bg_contrast_200: { 312 - backgroundColor: darkPalette.contrast_200, 313 - }, 314 - bg_contrast_300: { 315 - backgroundColor: darkPalette.contrast_300, 316 - }, 317 - bg_contrast_400: { 318 - backgroundColor: darkPalette.contrast_400, 319 - }, 320 - bg_contrast_500: { 321 - backgroundColor: darkPalette.contrast_500, 322 - }, 323 - bg_contrast_600: { 324 - backgroundColor: darkPalette.contrast_600, 325 - }, 326 - bg_contrast_700: { 327 - backgroundColor: darkPalette.contrast_700, 328 - }, 329 - bg_contrast_800: { 330 - backgroundColor: darkPalette.contrast_800, 331 - }, 332 - bg_contrast_900: { 333 - backgroundColor: darkPalette.contrast_900, 334 - }, 335 - bg_contrast_950: { 336 - backgroundColor: darkPalette.contrast_950, 337 - }, 338 - bg_contrast_975: { 339 - backgroundColor: darkPalette.contrast_975, 340 - }, 341 - border_contrast_low: { 342 - borderColor: darkPalette.contrast_100, 343 - }, 344 - border_contrast_medium: { 345 - borderColor: darkPalette.contrast_200, 346 - }, 347 - border_contrast_high: { 348 - borderColor: darkPalette.contrast_300, 349 - }, 350 - shadow_sm: { 351 - ...atoms.shadow_sm, 352 - shadowOpacity: 0.7, 353 - shadowColor: tokens.color.trueBlack, 354 - }, 355 - shadow_md: { 356 - ...atoms.shadow_md, 357 - shadowOpacity: 0.7, 358 - shadowColor: tokens.color.trueBlack, 359 - }, 360 - shadow_lg: { 361 - ...atoms.shadow_lg, 362 - shadowOpacity: 0.7, 363 - shadowColor: tokens.color.trueBlack, 364 - }, 365 - }, 366 - } 478 + } 367 479 368 - export const dim: Theme = { 369 - ...dark, 370 - name: 'dim' as ThemeName, 371 - palette: dimPalette, 372 - atoms: { 373 - ...dark.atoms, 374 - text: { 375 - color: dimPalette.white, 376 - }, 377 - text_contrast_low: { 378 - color: dimPalette.contrast_400, 379 - }, 380 - text_contrast_medium: { 381 - color: dimPalette.contrast_700, 382 - }, 383 - text_contrast_high: { 384 - color: dimPalette.contrast_900, 385 - }, 386 - text_inverted: { 387 - color: dimPalette.black, 388 - }, 389 - bg: { 390 - backgroundColor: dimPalette.black, 391 - }, 392 - bg_contrast_25: { 393 - backgroundColor: dimPalette.contrast_25, 394 - }, 395 - bg_contrast_50: { 396 - backgroundColor: dimPalette.contrast_50, 397 - }, 398 - bg_contrast_100: { 399 - backgroundColor: dimPalette.contrast_100, 400 - }, 401 - bg_contrast_200: { 402 - backgroundColor: dimPalette.contrast_200, 403 - }, 404 - bg_contrast_300: { 405 - backgroundColor: dimPalette.contrast_300, 406 - }, 407 - bg_contrast_400: { 408 - backgroundColor: dimPalette.contrast_400, 409 - }, 410 - bg_contrast_500: { 411 - backgroundColor: dimPalette.contrast_500, 412 - }, 413 - bg_contrast_600: { 414 - backgroundColor: dimPalette.contrast_600, 415 - }, 416 - bg_contrast_700: { 417 - backgroundColor: dimPalette.contrast_700, 418 - }, 419 - bg_contrast_800: { 420 - backgroundColor: dimPalette.contrast_800, 421 - }, 422 - bg_contrast_900: { 423 - backgroundColor: dimPalette.contrast_900, 424 - }, 425 - bg_contrast_950: { 426 - backgroundColor: dimPalette.contrast_950, 427 - }, 428 - bg_contrast_975: { 429 - backgroundColor: dimPalette.contrast_975, 480 + const dim: Theme = { 481 + ...dark, 482 + name: 'dim', 483 + palette: dimPalette, 484 + atoms: { 485 + ...dark.atoms, 486 + text: { 487 + color: dimPalette.white, 488 + }, 489 + text_contrast_low: { 490 + color: dimPalette.contrast_400, 491 + }, 492 + text_contrast_medium: { 493 + color: dimPalette.contrast_700, 494 + }, 495 + text_contrast_high: { 496 + color: dimPalette.contrast_900, 497 + }, 498 + text_inverted: { 499 + color: dimPalette.black, 500 + }, 501 + bg: { 502 + backgroundColor: dimPalette.black, 503 + }, 504 + bg_contrast_25: { 505 + backgroundColor: dimPalette.contrast_25, 506 + }, 507 + bg_contrast_50: { 508 + backgroundColor: dimPalette.contrast_50, 509 + }, 510 + bg_contrast_100: { 511 + backgroundColor: dimPalette.contrast_100, 512 + }, 513 + bg_contrast_200: { 514 + backgroundColor: dimPalette.contrast_200, 515 + }, 516 + bg_contrast_300: { 517 + backgroundColor: dimPalette.contrast_300, 518 + }, 519 + bg_contrast_400: { 520 + backgroundColor: dimPalette.contrast_400, 521 + }, 522 + bg_contrast_500: { 523 + backgroundColor: dimPalette.contrast_500, 524 + }, 525 + bg_contrast_600: { 526 + backgroundColor: dimPalette.contrast_600, 527 + }, 528 + bg_contrast_700: { 529 + backgroundColor: dimPalette.contrast_700, 530 + }, 531 + bg_contrast_800: { 532 + backgroundColor: dimPalette.contrast_800, 533 + }, 534 + bg_contrast_900: { 535 + backgroundColor: dimPalette.contrast_900, 536 + }, 537 + bg_contrast_950: { 538 + backgroundColor: dimPalette.contrast_950, 539 + }, 540 + bg_contrast_975: { 541 + backgroundColor: dimPalette.contrast_975, 542 + }, 543 + border_contrast_low: { 544 + borderColor: dimPalette.contrast_100, 545 + }, 546 + border_contrast_medium: { 547 + borderColor: dimPalette.contrast_200, 548 + }, 549 + border_contrast_high: { 550 + borderColor: dimPalette.contrast_300, 551 + }, 552 + shadow_sm: { 553 + ...atoms.shadow_sm, 554 + shadowOpacity: 0.7, 555 + shadowColor: `hsl(${hues.primary}, 28%, 6%)`, 556 + }, 557 + shadow_md: { 558 + ...atoms.shadow_md, 559 + shadowOpacity: 0.7, 560 + shadowColor: `hsl(${hues.primary}, 28%, 6%)`, 561 + }, 562 + shadow_lg: { 563 + ...atoms.shadow_lg, 564 + shadowOpacity: 0.7, 565 + shadowColor: `hsl(${hues.primary}, 28%, 6%)`, 566 + }, 430 567 }, 431 - border_contrast_low: { 432 - borderColor: dimPalette.contrast_100, 433 - }, 434 - border_contrast_medium: { 435 - borderColor: dimPalette.contrast_200, 436 - }, 437 - border_contrast_high: { 438 - borderColor: dimPalette.contrast_300, 439 - }, 440 - shadow_sm: { 441 - ...atoms.shadow_sm, 442 - shadowOpacity: 0.7, 443 - shadowColor: `hsl(${BLUE_HUE}, 28%, 6%)`, 444 - }, 445 - shadow_md: { 446 - ...atoms.shadow_md, 447 - shadowOpacity: 0.7, 448 - shadowColor: `hsl(${BLUE_HUE}, 28%, 6%)`, 449 - }, 450 - shadow_lg: { 451 - ...atoms.shadow_lg, 452 - shadowOpacity: 0.7, 453 - shadowColor: `hsl(${BLUE_HUE}, 28%, 6%)`, 454 - }, 455 - }, 568 + } 569 + 570 + return { 571 + lightPalette, 572 + darkPalette, 573 + dimPalette, 574 + light, 575 + dark, 576 + dim, 577 + } 456 578 }
-78
src/alf/tokens.ts
··· 1 - import { 2 - BLUE_HUE, 3 - generateScale, 4 - GREEN_HUE, 5 - RED_HUE, 6 - } from '#/alf/util/colorGeneration' 7 - 8 - export const scale = generateScale(6, 100) 9 - // dim shifted 6% lighter 10 - export const dimScale = generateScale(12, 100) 11 - 12 1 export const color = { 13 - trueBlack: '#000000', 14 - 15 2 temp_purple: 'rgb(105 0 255)', 16 3 temp_purple_dark: 'rgb(83 0 202)', 17 - 18 - gray_0: `hsl(${BLUE_HUE}, 20%, ${scale[14]}%)`, 19 - gray_25: `hsl(${BLUE_HUE}, 20%, ${scale[13]}%)`, 20 - gray_50: `hsl(${BLUE_HUE}, 20%, ${scale[12]}%)`, 21 - gray_100: `hsl(${BLUE_HUE}, 20%, ${scale[11]}%)`, 22 - gray_200: `hsl(${BLUE_HUE}, 20%, ${scale[10]}%)`, 23 - gray_300: `hsl(${BLUE_HUE}, 20%, ${scale[9]}%)`, 24 - gray_400: `hsl(${BLUE_HUE}, 20%, ${scale[8]}%)`, 25 - gray_500: `hsl(${BLUE_HUE}, 20%, ${scale[7]}%)`, 26 - gray_600: `hsl(${BLUE_HUE}, 24%, ${scale[6]}%)`, 27 - gray_700: `hsl(${BLUE_HUE}, 24%, ${scale[5]}%)`, 28 - gray_800: `hsl(${BLUE_HUE}, 28%, ${scale[4]}%)`, 29 - gray_900: `hsl(${BLUE_HUE}, 28%, ${scale[3]}%)`, 30 - gray_950: `hsl(${BLUE_HUE}, 28%, ${scale[2]}%)`, 31 - gray_975: `hsl(${BLUE_HUE}, 28%, ${scale[1]}%)`, 32 - gray_1000: `hsl(${BLUE_HUE}, 28%, ${scale[0]}%)`, 33 - 34 - blue_25: `hsl(${BLUE_HUE}, 99%, 97%)`, 35 - blue_50: `hsl(${BLUE_HUE}, 99%, 95%)`, 36 - blue_100: `hsl(${BLUE_HUE}, 99%, 90%)`, 37 - blue_200: `hsl(${BLUE_HUE}, 99%, 80%)`, 38 - blue_300: `hsl(${BLUE_HUE}, 99%, 70%)`, 39 - blue_400: `hsl(${BLUE_HUE}, 99%, 60%)`, 40 - blue_500: `hsl(${BLUE_HUE}, 99%, 53%)`, 41 - blue_600: `hsl(${BLUE_HUE}, 99%, 42%)`, 42 - blue_700: `hsl(${BLUE_HUE}, 99%, 34%)`, 43 - blue_800: `hsl(${BLUE_HUE}, 99%, 26%)`, 44 - blue_900: `hsl(${BLUE_HUE}, 99%, 18%)`, 45 - blue_950: `hsl(${BLUE_HUE}, 99%, 10%)`, 46 - blue_975: `hsl(${BLUE_HUE}, 99%, 7%)`, 47 - 48 - green_25: `hsl(${GREEN_HUE}, 82%, 97%)`, 49 - green_50: `hsl(${GREEN_HUE}, 82%, 95%)`, 50 - green_100: `hsl(${GREEN_HUE}, 82%, 90%)`, 51 - green_200: `hsl(${GREEN_HUE}, 82%, 80%)`, 52 - green_300: `hsl(${GREEN_HUE}, 82%, 70%)`, 53 - green_400: `hsl(${GREEN_HUE}, 82%, 60%)`, 54 - green_500: `hsl(${GREEN_HUE}, 82%, 50%)`, 55 - green_600: `hsl(${GREEN_HUE}, 82%, 42%)`, 56 - green_700: `hsl(${GREEN_HUE}, 82%, 34%)`, 57 - green_800: `hsl(${GREEN_HUE}, 82%, 26%)`, 58 - green_900: `hsl(${GREEN_HUE}, 82%, 18%)`, 59 - green_950: `hsl(${GREEN_HUE}, 82%, 10%)`, 60 - green_975: `hsl(${GREEN_HUE}, 82%, 7%)`, 61 - 62 - red_25: `hsl(${RED_HUE}, 91%, 97%)`, 63 - red_50: `hsl(${RED_HUE}, 91%, 95%)`, 64 - red_100: `hsl(${RED_HUE}, 91%, 90%)`, 65 - red_200: `hsl(${RED_HUE}, 91%, 80%)`, 66 - red_300: `hsl(${RED_HUE}, 91%, 70%)`, 67 - red_400: `hsl(${RED_HUE}, 91%, 60%)`, 68 - red_500: `hsl(${RED_HUE}, 91%, 50%)`, 69 - red_600: `hsl(${RED_HUE}, 91%, 42%)`, 70 - red_700: `hsl(${RED_HUE}, 91%, 34%)`, 71 - red_800: `hsl(${RED_HUE}, 91%, 26%)`, 72 - red_900: `hsl(${RED_HUE}, 91%, 18%)`, 73 - red_950: `hsl(${RED_HUE}, 91%, 10%)`, 74 - red_975: `hsl(${RED_HUE}, 91%, 7%)`, 75 4 } as const 76 5 77 6 export const space = { ··· 178 107 hover_value: '#755B62', 179 108 }, 180 109 } as const 181 - 182 - export type Color = keyof typeof color 183 - export type Space = keyof typeof space 184 - export type FontSize = keyof typeof fontSize 185 - export type LineHeight = keyof typeof lineHeight 186 - export type BorderRadius = keyof typeof borderRadius 187 - export type FontWeight = keyof typeof fontWeight
+154 -18
src/alf/types.ts
··· 1 - import {StyleProp, ViewStyle, TextStyle} from 'react-native' 2 - 3 - type LiteralToCommon<T extends PropertyKey> = T extends number 4 - ? number 5 - : T extends string 6 - ? string 7 - : T extends symbol 8 - ? symbol 9 - : never 10 - 11 - /** 12 - * @see https://stackoverflow.com/questions/68249999/use-as-const-in-typescript-without-adding-readonly-modifiers 13 - */ 14 - export type Mutable<T> = { 15 - -readonly [K in keyof T]: T[K] extends PropertyKey 16 - ? LiteralToCommon<T[K]> 17 - : Mutable<T[K]> 18 - } 1 + import {StyleProp, TextStyle, ViewStyle} from 'react-native' 19 2 20 3 export type TextStyleProp = { 21 4 style?: StyleProp<TextStyle> ··· 24 7 export type ViewStyleProp = { 25 8 style?: StyleProp<ViewStyle> 26 9 } 10 + 11 + export type ThemeName = 'light' | 'dim' | 'dark' 12 + export type Palette = { 13 + white: string 14 + black: string 15 + 16 + contrast_25: string 17 + contrast_50: string 18 + contrast_100: string 19 + contrast_200: string 20 + contrast_300: string 21 + contrast_400: string 22 + contrast_500: string 23 + contrast_600: string 24 + contrast_700: string 25 + contrast_800: string 26 + contrast_900: string 27 + contrast_950: string 28 + contrast_975: string 29 + 30 + primary_25: string 31 + primary_50: string 32 + primary_100: string 33 + primary_200: string 34 + primary_300: string 35 + primary_400: string 36 + primary_500: string 37 + primary_600: string 38 + primary_700: string 39 + primary_800: string 40 + primary_900: string 41 + primary_950: string 42 + primary_975: string 43 + 44 + positive_25: string 45 + positive_50: string 46 + positive_100: string 47 + positive_200: string 48 + positive_300: string 49 + positive_400: string 50 + positive_500: string 51 + positive_600: string 52 + positive_700: string 53 + positive_800: string 54 + positive_900: string 55 + positive_950: string 56 + positive_975: string 57 + 58 + negative_25: string 59 + negative_50: string 60 + negative_100: string 61 + negative_200: string 62 + negative_300: string 63 + negative_400: string 64 + negative_500: string 65 + negative_600: string 66 + negative_700: string 67 + negative_800: string 68 + negative_900: string 69 + negative_950: string 70 + negative_975: string 71 + } 72 + export type ThemedAtoms = { 73 + text: { 74 + color: string 75 + } 76 + text_contrast_low: { 77 + color: string 78 + } 79 + text_contrast_medium: { 80 + color: string 81 + } 82 + text_contrast_high: { 83 + color: string 84 + } 85 + text_inverted: { 86 + color: string 87 + } 88 + bg: { 89 + backgroundColor: string 90 + } 91 + bg_contrast_25: { 92 + backgroundColor: string 93 + } 94 + bg_contrast_50: { 95 + backgroundColor: string 96 + } 97 + bg_contrast_100: { 98 + backgroundColor: string 99 + } 100 + bg_contrast_200: { 101 + backgroundColor: string 102 + } 103 + bg_contrast_300: { 104 + backgroundColor: string 105 + } 106 + bg_contrast_400: { 107 + backgroundColor: string 108 + } 109 + bg_contrast_500: { 110 + backgroundColor: string 111 + } 112 + bg_contrast_600: { 113 + backgroundColor: string 114 + } 115 + bg_contrast_700: { 116 + backgroundColor: string 117 + } 118 + bg_contrast_800: { 119 + backgroundColor: string 120 + } 121 + bg_contrast_900: { 122 + backgroundColor: string 123 + } 124 + bg_contrast_950: { 125 + backgroundColor: string 126 + } 127 + bg_contrast_975: { 128 + backgroundColor: string 129 + } 130 + border_contrast_low: { 131 + borderColor: string 132 + } 133 + border_contrast_medium: { 134 + borderColor: string 135 + } 136 + border_contrast_high: { 137 + borderColor: string 138 + } 139 + shadow_sm: { 140 + shadowRadius: number 141 + shadowOpacity: number 142 + elevation: number 143 + shadowColor: string 144 + } 145 + shadow_md: { 146 + shadowRadius: number 147 + shadowOpacity: number 148 + elevation: number 149 + shadowColor: string 150 + } 151 + shadow_lg: { 152 + shadowRadius: number 153 + shadowOpacity: number 154 + elevation: number 155 + shadowColor: string 156 + } 157 + } 158 + export type Theme = { 159 + name: ThemeName 160 + palette: Palette 161 + atoms: ThemedAtoms 162 + }
+4
src/alf/util/colorGeneration.ts
··· 15 15 return start + range * stop 16 16 }) 17 17 } 18 + 19 + export const defaultScale = generateScale(6, 100) 20 + // dim shifted 6% lighter 21 + export const dimScale = generateScale(12, 100)
+1 -1
src/alf/util/themeSelector.ts
··· 1 - import {ThemeName} from '#/alf/themes' 1 + import {ThemeName} from '#/alf/types' 2 2 3 3 export function select<T>(name: ThemeName, options: Record<ThemeName, T>) { 4 4 switch (name) {
+2 -1
src/alf/util/useColorModeTheme.ts
··· 4 4 5 5 import {isWeb} from 'platform/detection' 6 6 import {useThemePrefs} from 'state/shell' 7 - import {dark, dim, light, ThemeName} from '#/alf/themes' 7 + import {dark, dim, light} from '#/alf/themes' 8 + import {ThemeName} from '#/alf/types' 8 9 9 10 export function useColorModeTheme(): ThemeName { 10 11 const theme = useThemeName()
+34 -28
src/components/Button.tsx
··· 13 13 } from 'react-native' 14 14 import {LinearGradient} from 'expo-linear-gradient' 15 15 16 - import {android, atoms as a, flatten, tokens, useTheme} from '#/alf' 16 + import {android, atoms as a, flatten, select, tokens, useTheme} from '#/alf' 17 17 import {Props as SVGIconProps} from '#/components/icons/common' 18 18 import {normalizeTextStyles} from '#/components/Typography' 19 19 ··· 152 152 const {baseStyles, hoverStyles} = React.useMemo(() => { 153 153 const baseStyles: ViewStyle[] = [] 154 154 const hoverStyles: ViewStyle[] = [] 155 - const light = t.name === 'light' 156 155 157 156 if (color === 'primary') { 158 157 if (variant === 'solid') { ··· 165 164 }) 166 165 } else { 167 166 baseStyles.push({ 168 - backgroundColor: t.palette.primary_700, 167 + backgroundColor: select(t.name, { 168 + light: t.palette.primary_700, 169 + dim: t.palette.primary_300, 170 + dark: t.palette.primary_300, 171 + }), 169 172 }) 170 173 } 171 174 } else if (variant === 'outline') { ··· 178 181 borderColor: t.palette.primary_500, 179 182 }) 180 183 hoverStyles.push(a.border, { 181 - backgroundColor: light 182 - ? t.palette.primary_50 183 - : t.palette.primary_950, 184 + backgroundColor: t.palette.primary_50, 184 185 }) 185 186 } else { 186 187 baseStyles.push(a.border, { 187 - borderColor: light 188 - ? t.palette.primary_200 189 - : t.palette.primary_900, 188 + borderColor: t.palette.primary_200, 190 189 }) 191 190 } 192 191 } else if (variant === 'ghost') { 193 192 if (!disabled) { 194 193 baseStyles.push(t.atoms.bg) 195 194 hoverStyles.push({ 196 - backgroundColor: light 197 - ? t.palette.primary_100 198 - : t.palette.primary_900, 195 + backgroundColor: t.palette.primary_100, 199 196 }) 200 197 } 201 198 } ··· 203 200 if (variant === 'solid') { 204 201 if (!disabled) { 205 202 baseStyles.push({ 206 - backgroundColor: t.palette.contrast_25, 203 + backgroundColor: select(t.name, { 204 + light: t.palette.contrast_25, 205 + dim: t.palette.contrast_100, 206 + dark: t.palette.contrast_100, 207 + }), 207 208 }) 208 209 hoverStyles.push({ 209 - backgroundColor: t.palette.contrast_50, 210 + backgroundColor: select(t.name, { 211 + light: t.palette.contrast_50, 212 + dim: t.palette.contrast_200, 213 + dark: t.palette.contrast_200, 214 + }), 210 215 }) 211 216 } else { 212 217 baseStyles.push({ 213 - backgroundColor: t.palette.contrast_100, 218 + backgroundColor: select(t.name, { 219 + light: t.palette.contrast_100, 220 + dim: t.palette.contrast_25, 221 + dark: t.palette.contrast_25, 222 + }), 214 223 }) 215 224 } 216 225 } else if (variant === 'outline') { ··· 247 256 }) 248 257 } else { 249 258 baseStyles.push({ 250 - backgroundColor: t.palette.contrast_700, 259 + backgroundColor: t.palette.contrast_600, 251 260 }) 252 261 } 253 262 } else if (variant === 'outline') { ··· 284 293 }) 285 294 } else { 286 295 baseStyles.push({ 287 - backgroundColor: t.palette.negative_700, 296 + backgroundColor: select(t.name, { 297 + light: t.palette.negative_700, 298 + dim: t.palette.negative_300, 299 + dark: t.palette.negative_300, 300 + }), 288 301 }) 289 302 } 290 303 } else if (variant === 'outline') { ··· 297 310 borderColor: t.palette.negative_500, 298 311 }) 299 312 hoverStyles.push(a.border, { 300 - backgroundColor: light 301 - ? t.palette.negative_50 302 - : t.palette.negative_975, 313 + backgroundColor: t.palette.negative_50, 303 314 }) 304 315 } else { 305 316 baseStyles.push(a.border, { 306 - borderColor: light 307 - ? t.palette.negative_200 308 - : t.palette.negative_900, 317 + borderColor: t.palette.negative_200, 309 318 }) 310 319 } 311 320 } else if (variant === 'ghost') { 312 321 if (!disabled) { 313 322 baseStyles.push(t.atoms.bg) 314 323 hoverStyles.push({ 315 - backgroundColor: light 316 - ? t.palette.negative_100 317 - : t.palette.negative_975, 324 + backgroundColor: t.palette.negative_100, 318 325 }) 319 326 } 320 327 } ··· 482 489 const {color, variant, disabled, size} = useButtonContext() 483 490 return React.useMemo(() => { 484 491 const baseStyles: TextStyle[] = [] 485 - const light = t.name === 'light' 486 492 487 493 if (color === 'primary') { 488 494 if (variant === 'solid') { ··· 494 500 } else if (variant === 'outline') { 495 501 if (!disabled) { 496 502 baseStyles.push({ 497 - color: light ? t.palette.primary_600 : t.palette.primary_500, 503 + color: t.palette.primary_600, 498 504 }) 499 505 } else { 500 506 baseStyles.push({color: t.palette.primary_600, opacity: 0.5})
+5 -6
src/components/IconCircle.tsx
··· 2 2 import {View} from 'react-native' 3 3 4 4 import { 5 - useTheme, 6 5 atoms as a, 7 - ViewStyleProp, 8 - TextStyleProp, 9 6 flatten, 7 + TextStyleProp, 8 + useTheme, 9 + ViewStyleProp, 10 10 } from '#/alf' 11 - import {Growth_Stroke2_Corner0_Rounded as Growth} from '#/components/icons/Growth' 12 11 import {Props} from '#/components/icons/common' 12 + import {Growth_Stroke2_Corner0_Rounded as Growth} from '#/components/icons/Growth' 13 13 14 14 export function IconCircle({ 15 15 icon: Icon, ··· 32 32 { 33 33 width: size === 'lg' ? 52 : 64, 34 34 height: size === 'lg' ? 52 : 64, 35 - backgroundColor: 36 - t.name === 'light' ? t.palette.primary_50 : t.palette.primary_950, 35 + backgroundColor: t.palette.primary_50, 37 36 }, 38 37 flatten(style), 39 38 ]}>
+3 -4
src/components/dialogs/MutedWords.tsx
··· 357 357 a.px_sm, 358 358 gtMobile && a.px_md, 359 359 a.rounded_sm, 360 - t.atoms.bg_contrast_50, 361 - (ctx.hovered || ctx.focused) && t.atoms.bg_contrast_100, 360 + t.atoms.bg_contrast_25, 361 + (ctx.hovered || ctx.focused) && t.atoms.bg_contrast_50, 362 362 ctx.selected && [ 363 363 { 364 - backgroundColor: 365 - t.name === 'light' ? t.palette.primary_50 : t.palette.primary_975, 364 + backgroundColor: t.palette.primary_50, 366 365 }, 367 366 ], 368 367 ctx.disabled && {
+1 -4
src/components/dialogs/ThreadgateEditor.tsx
··· 196 196 t.atoms.bg_contrast_50, 197 197 (hovered || focused) && t.atoms.bg_contrast_100, 198 198 isSelected && { 199 - backgroundColor: 200 - t.name === 'light' 201 - ? t.palette.primary_50 202 - : t.palette.primary_975, 199 + backgroundColor: t.palette.primary_100, 203 200 }, 204 201 style, 205 202 ]}>
+2 -8
src/components/dms/MessageItem.tsx
··· 72 72 lastInGroupRef.current = isLastInGroup 73 73 } 74 74 75 - const pendingColor = 76 - t.name === 'light' ? t.palette.primary_200 : t.palette.primary_800 75 + const pendingColor = t.palette.primary_200 77 76 78 77 const rt = useMemo(() => { 79 78 return new RichTextAPI({text: message.text, facets: message.facets}) ··· 110 109 }> 111 110 <RichText 112 111 value={rt} 113 - style={[ 114 - a.text_md, 115 - isFromSelf && {color: t.palette.white}, 116 - isPending && 117 - t.name !== 'light' && {color: t.palette.primary_300}, 118 - ]} 112 + style={[a.text_md, isFromSelf && {color: t.palette.white}]} 119 113 interactiveStyle={a.underline} 120 114 enableTags 121 115 emojiMultiplier={3}
+3 -6
src/components/forms/TextField.tsx
··· 101 101 ] 102 102 const error: ViewStyle[] = [ 103 103 { 104 - backgroundColor: 105 - t.name === 'light' ? t.palette.negative_25 : t.palette.negative_900, 106 - borderColor: 107 - t.name === 'light' ? t.palette.negative_300 : t.palette.negative_800, 104 + backgroundColor: t.palette.negative_25, 105 + borderColor: t.palette.negative_300, 108 106 }, 109 107 ] 110 108 const errorHover: ViewStyle[] = [ 111 109 { 112 - backgroundColor: 113 - t.name === 'light' ? t.palette.negative_25 : t.palette.negative_900, 110 + backgroundColor: t.palette.negative_25, 114 111 borderColor: t.palette.negative_500, 115 112 }, 116 113 ]
+7 -14
src/components/forms/Toggle.tsx
··· 281 281 282 282 if (selected) { 283 283 base.push({ 284 - backgroundColor: 285 - t.name === 'light' ? t.palette.primary_25 : t.palette.primary_900, 284 + backgroundColor: t.palette.primary_25, 286 285 borderColor: t.palette.primary_500, 287 286 }) 288 287 289 288 if (hovered) { 290 289 baseHover.push({ 291 - backgroundColor: 292 - t.name === 'light' ? t.palette.primary_100 : t.palette.primary_800, 293 - borderColor: 294 - t.name === 'light' ? t.palette.primary_600 : t.palette.primary_400, 290 + backgroundColor: t.palette.primary_100, 291 + borderColor: t.palette.primary_600, 295 292 }) 296 293 } 297 294 } else { 298 295 if (hovered) { 299 296 baseHover.push({ 300 - backgroundColor: 301 - t.name === 'light' ? t.palette.contrast_50 : t.palette.contrast_100, 297 + backgroundColor: t.palette.contrast_50, 302 298 borderColor: t.palette.contrast_500, 303 299 }) 304 300 } ··· 306 302 307 303 if (isInvalid) { 308 304 base.push({ 309 - backgroundColor: 310 - t.name === 'light' ? t.palette.negative_25 : t.palette.negative_975, 311 - borderColor: 312 - t.name === 'light' ? t.palette.negative_300 : t.palette.negative_800, 305 + backgroundColor: t.palette.negative_25, 306 + borderColor: t.palette.negative_300, 313 307 }) 314 308 315 309 if (hovered) { 316 310 baseHover.push({ 317 - backgroundColor: 318 - t.name === 'light' ? t.palette.negative_25 : t.palette.negative_900, 311 + backgroundColor: t.palette.negative_25, 319 312 borderColor: t.palette.negative_600, 320 313 }) 321 314 }
+3 -2
src/components/icons/common.tsx
··· 4 4 import {Defs, LinearGradient, Stop} from 'react-native-svg' 5 5 import {nanoid} from 'nanoid/non-secure' 6 6 7 - import {tokens} from '#/alf' 7 + import {tokens, useTheme} from '#/alf' 8 8 9 9 export type Props = { 10 10 fill?: PathProps['fill'] ··· 22 22 } 23 23 24 24 export function useCommonSVGProps(props: Props) { 25 + const t = useTheme() 25 26 const {fill, size, gradient, ...rest} = props 26 27 const style = StyleSheet.flatten(rest.style) 27 28 const _size = Number(size ? sizes[size] : rest.width || sizes.md) 28 - let _fill = fill || style?.color || tokens.color.blue_500 29 + let _fill = fill || style?.color || t.palette.primary_500 29 30 let gradientDef = null 30 31 31 32 if (gradient && tokens.gradients[gradient]) {
+3 -2
src/lib/ThemeContext.tsx
··· 1 - import React, {ReactNode, createContext, useContext} from 'react' 1 + import React, {createContext, ReactNode, useContext} from 'react' 2 2 import {TextStyle, ViewStyle} from 'react-native' 3 + 4 + import {ThemeName} from '#/alf/types' 3 5 import {darkTheme, defaultTheme, dimTheme} from './themes' 4 - import {ThemeName} from '#/alf/themes' 5 6 6 7 export type ColorScheme = 'light' | 'dark' 7 8
+7 -7
src/lib/themes.ts
··· 1 1 import {Platform} from 'react-native' 2 - import type {Theme} from './ThemeContext' 3 - import {colors} from './styles' 4 2 5 - import {darkPalette, lightPalette, dimPalette} from '#/alf/themes' 3 + import {darkPalette, dimPalette, lightPalette} from '#/alf/themes' 4 + import {colors} from './styles' 5 + import type {Theme} from './ThemeContext' 6 6 7 7 export const defaultTheme: Theme = { 8 8 colorScheme: 'light', ··· 308 308 textVeryLight: darkPalette.contrast_400, 309 309 replyLine: darkPalette.contrast_200, 310 310 replyLineDot: darkPalette.contrast_200, 311 - unreadNotifBg: darkPalette.primary_975, 312 - unreadNotifBorder: darkPalette.primary_900, 311 + unreadNotifBg: darkPalette.primary_25, 312 + unreadNotifBorder: darkPalette.primary_100, 313 313 postCtrl: darkPalette.contrast_500, 314 314 brandText: darkPalette.primary_500, 315 315 emptyStateIcon: darkPalette.contrast_300, ··· 357 357 textVeryLight: dimPalette.contrast_400, 358 358 replyLine: dimPalette.contrast_200, 359 359 replyLineDot: dimPalette.contrast_200, 360 - unreadNotifBg: dimPalette.primary_975, 361 - unreadNotifBorder: dimPalette.primary_900, 360 + unreadNotifBg: dimPalette.primary_25, 361 + unreadNotifBorder: dimPalette.primary_100, 362 362 postCtrl: dimPalette.contrast_500, 363 363 brandText: dimPalette.primary_500, 364 364 emptyStateIcon: dimPalette.contrast_300,
+27 -23
src/view/screens/Storybook/Buttons.tsx
··· 20 20 <H1>Buttons</H1> 21 21 22 22 <View style={[a.flex_row, a.flex_wrap, a.gap_md, a.align_start]}> 23 - {['primary', 'secondary', 'secondary_inverted'].map(color => ( 24 - <View key={color} style={[a.gap_md, a.align_start]}> 25 - {['solid', 'outline', 'ghost'].map(variant => ( 26 - <React.Fragment key={variant}> 27 - <Button 28 - variant={variant as ButtonVariant} 29 - color={color as ButtonColor} 30 - size="large" 31 - label="Click here"> 32 - <ButtonText>Button</ButtonText> 33 - </Button> 34 - <Button 35 - disabled 36 - variant={variant as ButtonVariant} 37 - color={color as ButtonColor} 38 - size="large" 39 - label="Click here"> 40 - <ButtonText>Button</ButtonText> 41 - </Button> 42 - </React.Fragment> 43 - ))} 44 - </View> 45 - ))} 23 + {['primary', 'secondary', 'secondary_inverted', 'negative'].map( 24 + color => ( 25 + <View key={color} style={[a.gap_md, a.align_start]}> 26 + {['solid', 'outline', 'ghost'].map(variant => ( 27 + <React.Fragment key={variant}> 28 + <Button 29 + variant={variant as ButtonVariant} 30 + color={color as ButtonColor} 31 + size="large" 32 + label="Click here"> 33 + <ButtonText>Button</ButtonText> 34 + </Button> 35 + <Button 36 + disabled 37 + variant={variant as ButtonVariant} 38 + color={color as ButtonColor} 39 + size="large" 40 + label="Click here"> 41 + <ButtonText>Button</ButtonText> 42 + </Button> 43 + </React.Fragment> 44 + ))} 45 + </View> 46 + ), 47 + )} 46 48 47 49 <View style={[a.flex_row, a.gap_md, a.align_start]}> 48 50 <View style={[a.gap_md, a.align_start]}> ··· 68 70 ), 69 71 )} 70 72 </View> 73 + {/* 71 74 <View style={[a.gap_md, a.align_start]}> 72 75 {['gradient_sunset', 'gradient_nordic', 'gradient_bonfire'].map( 73 76 name => ( ··· 91 94 ), 92 95 )} 93 96 </View> 97 + */} 94 98 </View> 95 99 </View> 96 100
+10
src/view/screens/Storybook/Forms.tsx
··· 41 41 /> 42 42 </TextField.Root> 43 43 44 + <TextField.Root> 45 + <TextField.Icon icon={Globe} /> 46 + <TextField.Input 47 + value={value} 48 + onChangeText={setValue} 49 + label="Text field" 50 + isInvalid 51 + /> 52 + </TextField.Root> 53 + 44 54 <View style={[a.w_full]}> 45 55 <TextField.LabelText>Text field</TextField.LabelText> 46 56 <TextField.Root>