[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 bgzio/stable
parent
ea0586cd67
commit
74186950b2
|
@ -1,7 +1,9 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {Dimensions} from 'react-native'
|
import {Dimensions} from 'react-native'
|
||||||
|
|
||||||
import * as themes from '#/alf/themes'
|
import {createThemes, defaultTheme} from '#/alf/themes'
|
||||||
|
import {Theme, ThemeName} from '#/alf/types'
|
||||||
|
import {BLUE_HUE, GREEN_HUE, RED_HUE} from '#/alf/util/colorGeneration'
|
||||||
|
|
||||||
export {atoms} from '#/alf/atoms'
|
export {atoms} from '#/alf/atoms'
|
||||||
export * as tokens from '#/alf/tokens'
|
export * as tokens from '#/alf/tokens'
|
||||||
|
@ -39,8 +41,8 @@ function getActiveBreakpoints({width}: {width: number}) {
|
||||||
* Context
|
* Context
|
||||||
*/
|
*/
|
||||||
export const Context = React.createContext<{
|
export const Context = React.createContext<{
|
||||||
themeName: themes.ThemeName
|
themeName: ThemeName
|
||||||
theme: themes.Theme
|
theme: Theme
|
||||||
breakpoints: {
|
breakpoints: {
|
||||||
active: BreakpointName | undefined
|
active: BreakpointName | undefined
|
||||||
gtPhone: boolean
|
gtPhone: boolean
|
||||||
|
@ -49,7 +51,7 @@ export const Context = React.createContext<{
|
||||||
}
|
}
|
||||||
}>({
|
}>({
|
||||||
themeName: 'light',
|
themeName: 'light',
|
||||||
theme: themes.light,
|
theme: defaultTheme,
|
||||||
breakpoints: {
|
breakpoints: {
|
||||||
active: undefined,
|
active: undefined,
|
||||||
gtPhone: false,
|
gtPhone: false,
|
||||||
|
@ -61,7 +63,16 @@ export const Context = React.createContext<{
|
||||||
export function ThemeProvider({
|
export function ThemeProvider({
|
||||||
children,
|
children,
|
||||||
theme: themeName,
|
theme: themeName,
|
||||||
}: React.PropsWithChildren<{theme: themes.ThemeName}>) {
|
}: React.PropsWithChildren<{theme: ThemeName}>) {
|
||||||
|
const themes = React.useMemo(() => {
|
||||||
|
return createThemes({
|
||||||
|
hues: {
|
||||||
|
primary: BLUE_HUE,
|
||||||
|
negative: RED_HUE,
|
||||||
|
positive: GREEN_HUE,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}, [])
|
||||||
const theme = themes[themeName]
|
const theme = themes[themeName]
|
||||||
const [breakpoints, setBreakpoints] = React.useState(() =>
|
const [breakpoints, setBreakpoints] = React.useState(() =>
|
||||||
getActiveBreakpoints({width: Dimensions.get('window').width}),
|
getActiveBreakpoints({width: Dimensions.get('window').width}),
|
||||||
|
|
1016
src/alf/themes.ts
1016
src/alf/themes.ts
File diff suppressed because it is too large
Load Diff
|
@ -1,77 +1,6 @@
|
||||||
import {
|
|
||||||
BLUE_HUE,
|
|
||||||
generateScale,
|
|
||||||
GREEN_HUE,
|
|
||||||
RED_HUE,
|
|
||||||
} from '#/alf/util/colorGeneration'
|
|
||||||
|
|
||||||
export const scale = generateScale(6, 100)
|
|
||||||
// dim shifted 6% lighter
|
|
||||||
export const dimScale = generateScale(12, 100)
|
|
||||||
|
|
||||||
export const color = {
|
export const color = {
|
||||||
trueBlack: '#000000',
|
|
||||||
|
|
||||||
temp_purple: 'rgb(105 0 255)',
|
temp_purple: 'rgb(105 0 255)',
|
||||||
temp_purple_dark: 'rgb(83 0 202)',
|
temp_purple_dark: 'rgb(83 0 202)',
|
||||||
|
|
||||||
gray_0: `hsl(${BLUE_HUE}, 20%, ${scale[14]}%)`,
|
|
||||||
gray_25: `hsl(${BLUE_HUE}, 20%, ${scale[13]}%)`,
|
|
||||||
gray_50: `hsl(${BLUE_HUE}, 20%, ${scale[12]}%)`,
|
|
||||||
gray_100: `hsl(${BLUE_HUE}, 20%, ${scale[11]}%)`,
|
|
||||||
gray_200: `hsl(${BLUE_HUE}, 20%, ${scale[10]}%)`,
|
|
||||||
gray_300: `hsl(${BLUE_HUE}, 20%, ${scale[9]}%)`,
|
|
||||||
gray_400: `hsl(${BLUE_HUE}, 20%, ${scale[8]}%)`,
|
|
||||||
gray_500: `hsl(${BLUE_HUE}, 20%, ${scale[7]}%)`,
|
|
||||||
gray_600: `hsl(${BLUE_HUE}, 24%, ${scale[6]}%)`,
|
|
||||||
gray_700: `hsl(${BLUE_HUE}, 24%, ${scale[5]}%)`,
|
|
||||||
gray_800: `hsl(${BLUE_HUE}, 28%, ${scale[4]}%)`,
|
|
||||||
gray_900: `hsl(${BLUE_HUE}, 28%, ${scale[3]}%)`,
|
|
||||||
gray_950: `hsl(${BLUE_HUE}, 28%, ${scale[2]}%)`,
|
|
||||||
gray_975: `hsl(${BLUE_HUE}, 28%, ${scale[1]}%)`,
|
|
||||||
gray_1000: `hsl(${BLUE_HUE}, 28%, ${scale[0]}%)`,
|
|
||||||
|
|
||||||
blue_25: `hsl(${BLUE_HUE}, 99%, 97%)`,
|
|
||||||
blue_50: `hsl(${BLUE_HUE}, 99%, 95%)`,
|
|
||||||
blue_100: `hsl(${BLUE_HUE}, 99%, 90%)`,
|
|
||||||
blue_200: `hsl(${BLUE_HUE}, 99%, 80%)`,
|
|
||||||
blue_300: `hsl(${BLUE_HUE}, 99%, 70%)`,
|
|
||||||
blue_400: `hsl(${BLUE_HUE}, 99%, 60%)`,
|
|
||||||
blue_500: `hsl(${BLUE_HUE}, 99%, 53%)`,
|
|
||||||
blue_600: `hsl(${BLUE_HUE}, 99%, 42%)`,
|
|
||||||
blue_700: `hsl(${BLUE_HUE}, 99%, 34%)`,
|
|
||||||
blue_800: `hsl(${BLUE_HUE}, 99%, 26%)`,
|
|
||||||
blue_900: `hsl(${BLUE_HUE}, 99%, 18%)`,
|
|
||||||
blue_950: `hsl(${BLUE_HUE}, 99%, 10%)`,
|
|
||||||
blue_975: `hsl(${BLUE_HUE}, 99%, 7%)`,
|
|
||||||
|
|
||||||
green_25: `hsl(${GREEN_HUE}, 82%, 97%)`,
|
|
||||||
green_50: `hsl(${GREEN_HUE}, 82%, 95%)`,
|
|
||||||
green_100: `hsl(${GREEN_HUE}, 82%, 90%)`,
|
|
||||||
green_200: `hsl(${GREEN_HUE}, 82%, 80%)`,
|
|
||||||
green_300: `hsl(${GREEN_HUE}, 82%, 70%)`,
|
|
||||||
green_400: `hsl(${GREEN_HUE}, 82%, 60%)`,
|
|
||||||
green_500: `hsl(${GREEN_HUE}, 82%, 50%)`,
|
|
||||||
green_600: `hsl(${GREEN_HUE}, 82%, 42%)`,
|
|
||||||
green_700: `hsl(${GREEN_HUE}, 82%, 34%)`,
|
|
||||||
green_800: `hsl(${GREEN_HUE}, 82%, 26%)`,
|
|
||||||
green_900: `hsl(${GREEN_HUE}, 82%, 18%)`,
|
|
||||||
green_950: `hsl(${GREEN_HUE}, 82%, 10%)`,
|
|
||||||
green_975: `hsl(${GREEN_HUE}, 82%, 7%)`,
|
|
||||||
|
|
||||||
red_25: `hsl(${RED_HUE}, 91%, 97%)`,
|
|
||||||
red_50: `hsl(${RED_HUE}, 91%, 95%)`,
|
|
||||||
red_100: `hsl(${RED_HUE}, 91%, 90%)`,
|
|
||||||
red_200: `hsl(${RED_HUE}, 91%, 80%)`,
|
|
||||||
red_300: `hsl(${RED_HUE}, 91%, 70%)`,
|
|
||||||
red_400: `hsl(${RED_HUE}, 91%, 60%)`,
|
|
||||||
red_500: `hsl(${RED_HUE}, 91%, 50%)`,
|
|
||||||
red_600: `hsl(${RED_HUE}, 91%, 42%)`,
|
|
||||||
red_700: `hsl(${RED_HUE}, 91%, 34%)`,
|
|
||||||
red_800: `hsl(${RED_HUE}, 91%, 26%)`,
|
|
||||||
red_900: `hsl(${RED_HUE}, 91%, 18%)`,
|
|
||||||
red_950: `hsl(${RED_HUE}, 91%, 10%)`,
|
|
||||||
red_975: `hsl(${RED_HUE}, 91%, 7%)`,
|
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
export const space = {
|
export const space = {
|
||||||
|
@ -178,10 +107,3 @@ export const gradients = {
|
||||||
hover_value: '#755B62',
|
hover_value: '#755B62',
|
||||||
},
|
},
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
export type Color = keyof typeof color
|
|
||||||
export type Space = keyof typeof space
|
|
||||||
export type FontSize = keyof typeof fontSize
|
|
||||||
export type LineHeight = keyof typeof lineHeight
|
|
||||||
export type BorderRadius = keyof typeof borderRadius
|
|
||||||
export type FontWeight = keyof typeof fontWeight
|
|
||||||
|
|
172
src/alf/types.ts
172
src/alf/types.ts
|
@ -1,21 +1,4 @@
|
||||||
import {StyleProp, ViewStyle, TextStyle} from 'react-native'
|
import {StyleProp, TextStyle, ViewStyle} from 'react-native'
|
||||||
|
|
||||||
type LiteralToCommon<T extends PropertyKey> = T extends number
|
|
||||||
? number
|
|
||||||
: T extends string
|
|
||||||
? string
|
|
||||||
: T extends symbol
|
|
||||||
? symbol
|
|
||||||
: never
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://stackoverflow.com/questions/68249999/use-as-const-in-typescript-without-adding-readonly-modifiers
|
|
||||||
*/
|
|
||||||
export type Mutable<T> = {
|
|
||||||
-readonly [K in keyof T]: T[K] extends PropertyKey
|
|
||||||
? LiteralToCommon<T[K]>
|
|
||||||
: Mutable<T[K]>
|
|
||||||
}
|
|
||||||
|
|
||||||
export type TextStyleProp = {
|
export type TextStyleProp = {
|
||||||
style?: StyleProp<TextStyle>
|
style?: StyleProp<TextStyle>
|
||||||
|
@ -24,3 +7,156 @@ export type TextStyleProp = {
|
||||||
export type ViewStyleProp = {
|
export type ViewStyleProp = {
|
||||||
style?: StyleProp<ViewStyle>
|
style?: StyleProp<ViewStyle>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ThemeName = 'light' | 'dim' | 'dark'
|
||||||
|
export type Palette = {
|
||||||
|
white: string
|
||||||
|
black: string
|
||||||
|
|
||||||
|
contrast_25: string
|
||||||
|
contrast_50: string
|
||||||
|
contrast_100: string
|
||||||
|
contrast_200: string
|
||||||
|
contrast_300: string
|
||||||
|
contrast_400: string
|
||||||
|
contrast_500: string
|
||||||
|
contrast_600: string
|
||||||
|
contrast_700: string
|
||||||
|
contrast_800: string
|
||||||
|
contrast_900: string
|
||||||
|
contrast_950: string
|
||||||
|
contrast_975: string
|
||||||
|
|
||||||
|
primary_25: string
|
||||||
|
primary_50: string
|
||||||
|
primary_100: string
|
||||||
|
primary_200: string
|
||||||
|
primary_300: string
|
||||||
|
primary_400: string
|
||||||
|
primary_500: string
|
||||||
|
primary_600: string
|
||||||
|
primary_700: string
|
||||||
|
primary_800: string
|
||||||
|
primary_900: string
|
||||||
|
primary_950: string
|
||||||
|
primary_975: string
|
||||||
|
|
||||||
|
positive_25: string
|
||||||
|
positive_50: string
|
||||||
|
positive_100: string
|
||||||
|
positive_200: string
|
||||||
|
positive_300: string
|
||||||
|
positive_400: string
|
||||||
|
positive_500: string
|
||||||
|
positive_600: string
|
||||||
|
positive_700: string
|
||||||
|
positive_800: string
|
||||||
|
positive_900: string
|
||||||
|
positive_950: string
|
||||||
|
positive_975: string
|
||||||
|
|
||||||
|
negative_25: string
|
||||||
|
negative_50: string
|
||||||
|
negative_100: string
|
||||||
|
negative_200: string
|
||||||
|
negative_300: string
|
||||||
|
negative_400: string
|
||||||
|
negative_500: string
|
||||||
|
negative_600: string
|
||||||
|
negative_700: string
|
||||||
|
negative_800: string
|
||||||
|
negative_900: string
|
||||||
|
negative_950: string
|
||||||
|
negative_975: string
|
||||||
|
}
|
||||||
|
export type ThemedAtoms = {
|
||||||
|
text: {
|
||||||
|
color: string
|
||||||
|
}
|
||||||
|
text_contrast_low: {
|
||||||
|
color: string
|
||||||
|
}
|
||||||
|
text_contrast_medium: {
|
||||||
|
color: string
|
||||||
|
}
|
||||||
|
text_contrast_high: {
|
||||||
|
color: string
|
||||||
|
}
|
||||||
|
text_inverted: {
|
||||||
|
color: string
|
||||||
|
}
|
||||||
|
bg: {
|
||||||
|
backgroundColor: string
|
||||||
|
}
|
||||||
|
bg_contrast_25: {
|
||||||
|
backgroundColor: string
|
||||||
|
}
|
||||||
|
bg_contrast_50: {
|
||||||
|
backgroundColor: string
|
||||||
|
}
|
||||||
|
bg_contrast_100: {
|
||||||
|
backgroundColor: string
|
||||||
|
}
|
||||||
|
bg_contrast_200: {
|
||||||
|
backgroundColor: string
|
||||||
|
}
|
||||||
|
bg_contrast_300: {
|
||||||
|
backgroundColor: string
|
||||||
|
}
|
||||||
|
bg_contrast_400: {
|
||||||
|
backgroundColor: string
|
||||||
|
}
|
||||||
|
bg_contrast_500: {
|
||||||
|
backgroundColor: string
|
||||||
|
}
|
||||||
|
bg_contrast_600: {
|
||||||
|
backgroundColor: string
|
||||||
|
}
|
||||||
|
bg_contrast_700: {
|
||||||
|
backgroundColor: string
|
||||||
|
}
|
||||||
|
bg_contrast_800: {
|
||||||
|
backgroundColor: string
|
||||||
|
}
|
||||||
|
bg_contrast_900: {
|
||||||
|
backgroundColor: string
|
||||||
|
}
|
||||||
|
bg_contrast_950: {
|
||||||
|
backgroundColor: string
|
||||||
|
}
|
||||||
|
bg_contrast_975: {
|
||||||
|
backgroundColor: string
|
||||||
|
}
|
||||||
|
border_contrast_low: {
|
||||||
|
borderColor: string
|
||||||
|
}
|
||||||
|
border_contrast_medium: {
|
||||||
|
borderColor: string
|
||||||
|
}
|
||||||
|
border_contrast_high: {
|
||||||
|
borderColor: string
|
||||||
|
}
|
||||||
|
shadow_sm: {
|
||||||
|
shadowRadius: number
|
||||||
|
shadowOpacity: number
|
||||||
|
elevation: number
|
||||||
|
shadowColor: string
|
||||||
|
}
|
||||||
|
shadow_md: {
|
||||||
|
shadowRadius: number
|
||||||
|
shadowOpacity: number
|
||||||
|
elevation: number
|
||||||
|
shadowColor: string
|
||||||
|
}
|
||||||
|
shadow_lg: {
|
||||||
|
shadowRadius: number
|
||||||
|
shadowOpacity: number
|
||||||
|
elevation: number
|
||||||
|
shadowColor: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export type Theme = {
|
||||||
|
name: ThemeName
|
||||||
|
palette: Palette
|
||||||
|
atoms: ThemedAtoms
|
||||||
|
}
|
||||||
|
|
|
@ -15,3 +15,7 @@ export function generateScale(start: number, end: number) {
|
||||||
return start + range * stop
|
return start + range * stop
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const defaultScale = generateScale(6, 100)
|
||||||
|
// dim shifted 6% lighter
|
||||||
|
export const dimScale = generateScale(12, 100)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {ThemeName} from '#/alf/themes'
|
import {ThemeName} from '#/alf/types'
|
||||||
|
|
||||||
export function select<T>(name: ThemeName, options: Record<ThemeName, T>) {
|
export function select<T>(name: ThemeName, options: Record<ThemeName, T>) {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
|
|
|
@ -4,7 +4,8 @@ import * as SystemUI from 'expo-system-ui'
|
||||||
|
|
||||||
import {isWeb} from 'platform/detection'
|
import {isWeb} from 'platform/detection'
|
||||||
import {useThemePrefs} from 'state/shell'
|
import {useThemePrefs} from 'state/shell'
|
||||||
import {dark, dim, light, ThemeName} from '#/alf/themes'
|
import {dark, dim, light} from '#/alf/themes'
|
||||||
|
import {ThemeName} from '#/alf/types'
|
||||||
|
|
||||||
export function useColorModeTheme(): ThemeName {
|
export function useColorModeTheme(): ThemeName {
|
||||||
const theme = useThemeName()
|
const theme = useThemeName()
|
||||||
|
|
|
@ -13,7 +13,7 @@ import {
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import {LinearGradient} from 'expo-linear-gradient'
|
import {LinearGradient} from 'expo-linear-gradient'
|
||||||
|
|
||||||
import {android, atoms as a, flatten, tokens, useTheme} from '#/alf'
|
import {android, atoms as a, flatten, select, tokens, useTheme} from '#/alf'
|
||||||
import {Props as SVGIconProps} from '#/components/icons/common'
|
import {Props as SVGIconProps} from '#/components/icons/common'
|
||||||
import {normalizeTextStyles} from '#/components/Typography'
|
import {normalizeTextStyles} from '#/components/Typography'
|
||||||
|
|
||||||
|
@ -152,7 +152,6 @@ export const Button = React.forwardRef<View, ButtonProps>(
|
||||||
const {baseStyles, hoverStyles} = React.useMemo(() => {
|
const {baseStyles, hoverStyles} = React.useMemo(() => {
|
||||||
const baseStyles: ViewStyle[] = []
|
const baseStyles: ViewStyle[] = []
|
||||||
const hoverStyles: ViewStyle[] = []
|
const hoverStyles: ViewStyle[] = []
|
||||||
const light = t.name === 'light'
|
|
||||||
|
|
||||||
if (color === 'primary') {
|
if (color === 'primary') {
|
||||||
if (variant === 'solid') {
|
if (variant === 'solid') {
|
||||||
|
@ -165,7 +164,11 @@ export const Button = React.forwardRef<View, ButtonProps>(
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
baseStyles.push({
|
baseStyles.push({
|
||||||
backgroundColor: t.palette.primary_700,
|
backgroundColor: select(t.name, {
|
||||||
|
light: t.palette.primary_700,
|
||||||
|
dim: t.palette.primary_300,
|
||||||
|
dark: t.palette.primary_300,
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else if (variant === 'outline') {
|
} else if (variant === 'outline') {
|
||||||
|
@ -178,24 +181,18 @@ export const Button = React.forwardRef<View, ButtonProps>(
|
||||||
borderColor: t.palette.primary_500,
|
borderColor: t.palette.primary_500,
|
||||||
})
|
})
|
||||||
hoverStyles.push(a.border, {
|
hoverStyles.push(a.border, {
|
||||||
backgroundColor: light
|
backgroundColor: t.palette.primary_50,
|
||||||
? t.palette.primary_50
|
|
||||||
: t.palette.primary_950,
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
baseStyles.push(a.border, {
|
baseStyles.push(a.border, {
|
||||||
borderColor: light
|
borderColor: t.palette.primary_200,
|
||||||
? t.palette.primary_200
|
|
||||||
: t.palette.primary_900,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else if (variant === 'ghost') {
|
} else if (variant === 'ghost') {
|
||||||
if (!disabled) {
|
if (!disabled) {
|
||||||
baseStyles.push(t.atoms.bg)
|
baseStyles.push(t.atoms.bg)
|
||||||
hoverStyles.push({
|
hoverStyles.push({
|
||||||
backgroundColor: light
|
backgroundColor: t.palette.primary_100,
|
||||||
? t.palette.primary_100
|
|
||||||
: t.palette.primary_900,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -203,14 +200,26 @@ export const Button = React.forwardRef<View, ButtonProps>(
|
||||||
if (variant === 'solid') {
|
if (variant === 'solid') {
|
||||||
if (!disabled) {
|
if (!disabled) {
|
||||||
baseStyles.push({
|
baseStyles.push({
|
||||||
backgroundColor: t.palette.contrast_25,
|
backgroundColor: select(t.name, {
|
||||||
|
light: t.palette.contrast_25,
|
||||||
|
dim: t.palette.contrast_100,
|
||||||
|
dark: t.palette.contrast_100,
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
hoverStyles.push({
|
hoverStyles.push({
|
||||||
backgroundColor: t.palette.contrast_50,
|
backgroundColor: select(t.name, {
|
||||||
|
light: t.palette.contrast_50,
|
||||||
|
dim: t.palette.contrast_200,
|
||||||
|
dark: t.palette.contrast_200,
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
baseStyles.push({
|
baseStyles.push({
|
||||||
backgroundColor: t.palette.contrast_100,
|
backgroundColor: select(t.name, {
|
||||||
|
light: t.palette.contrast_100,
|
||||||
|
dim: t.palette.contrast_25,
|
||||||
|
dark: t.palette.contrast_25,
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else if (variant === 'outline') {
|
} else if (variant === 'outline') {
|
||||||
|
@ -247,7 +256,7 @@ export const Button = React.forwardRef<View, ButtonProps>(
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
baseStyles.push({
|
baseStyles.push({
|
||||||
backgroundColor: t.palette.contrast_700,
|
backgroundColor: t.palette.contrast_600,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else if (variant === 'outline') {
|
} else if (variant === 'outline') {
|
||||||
|
@ -284,7 +293,11 @@ export const Button = React.forwardRef<View, ButtonProps>(
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
baseStyles.push({
|
baseStyles.push({
|
||||||
backgroundColor: t.palette.negative_700,
|
backgroundColor: select(t.name, {
|
||||||
|
light: t.palette.negative_700,
|
||||||
|
dim: t.palette.negative_300,
|
||||||
|
dark: t.palette.negative_300,
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else if (variant === 'outline') {
|
} else if (variant === 'outline') {
|
||||||
|
@ -297,24 +310,18 @@ export const Button = React.forwardRef<View, ButtonProps>(
|
||||||
borderColor: t.palette.negative_500,
|
borderColor: t.palette.negative_500,
|
||||||
})
|
})
|
||||||
hoverStyles.push(a.border, {
|
hoverStyles.push(a.border, {
|
||||||
backgroundColor: light
|
backgroundColor: t.palette.negative_50,
|
||||||
? t.palette.negative_50
|
|
||||||
: t.palette.negative_975,
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
baseStyles.push(a.border, {
|
baseStyles.push(a.border, {
|
||||||
borderColor: light
|
borderColor: t.palette.negative_200,
|
||||||
? t.palette.negative_200
|
|
||||||
: t.palette.negative_900,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else if (variant === 'ghost') {
|
} else if (variant === 'ghost') {
|
||||||
if (!disabled) {
|
if (!disabled) {
|
||||||
baseStyles.push(t.atoms.bg)
|
baseStyles.push(t.atoms.bg)
|
||||||
hoverStyles.push({
|
hoverStyles.push({
|
||||||
backgroundColor: light
|
backgroundColor: t.palette.negative_100,
|
||||||
? t.palette.negative_100
|
|
||||||
: t.palette.negative_975,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -482,7 +489,6 @@ export function useSharedButtonTextStyles() {
|
||||||
const {color, variant, disabled, size} = useButtonContext()
|
const {color, variant, disabled, size} = useButtonContext()
|
||||||
return React.useMemo(() => {
|
return React.useMemo(() => {
|
||||||
const baseStyles: TextStyle[] = []
|
const baseStyles: TextStyle[] = []
|
||||||
const light = t.name === 'light'
|
|
||||||
|
|
||||||
if (color === 'primary') {
|
if (color === 'primary') {
|
||||||
if (variant === 'solid') {
|
if (variant === 'solid') {
|
||||||
|
@ -494,7 +500,7 @@ export function useSharedButtonTextStyles() {
|
||||||
} else if (variant === 'outline') {
|
} else if (variant === 'outline') {
|
||||||
if (!disabled) {
|
if (!disabled) {
|
||||||
baseStyles.push({
|
baseStyles.push({
|
||||||
color: light ? t.palette.primary_600 : t.palette.primary_500,
|
color: t.palette.primary_600,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
baseStyles.push({color: t.palette.primary_600, opacity: 0.5})
|
baseStyles.push({color: t.palette.primary_600, opacity: 0.5})
|
||||||
|
|
|
@ -2,14 +2,14 @@ import React from 'react'
|
||||||
import {View} from 'react-native'
|
import {View} from 'react-native'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
useTheme,
|
|
||||||
atoms as a,
|
atoms as a,
|
||||||
ViewStyleProp,
|
|
||||||
TextStyleProp,
|
|
||||||
flatten,
|
flatten,
|
||||||
|
TextStyleProp,
|
||||||
|
useTheme,
|
||||||
|
ViewStyleProp,
|
||||||
} from '#/alf'
|
} from '#/alf'
|
||||||
import {Growth_Stroke2_Corner0_Rounded as Growth} from '#/components/icons/Growth'
|
|
||||||
import {Props} from '#/components/icons/common'
|
import {Props} from '#/components/icons/common'
|
||||||
|
import {Growth_Stroke2_Corner0_Rounded as Growth} from '#/components/icons/Growth'
|
||||||
|
|
||||||
export function IconCircle({
|
export function IconCircle({
|
||||||
icon: Icon,
|
icon: Icon,
|
||||||
|
@ -32,8 +32,7 @@ export function IconCircle({
|
||||||
{
|
{
|
||||||
width: size === 'lg' ? 52 : 64,
|
width: size === 'lg' ? 52 : 64,
|
||||||
height: size === 'lg' ? 52 : 64,
|
height: size === 'lg' ? 52 : 64,
|
||||||
backgroundColor:
|
backgroundColor: t.palette.primary_50,
|
||||||
t.name === 'light' ? t.palette.primary_50 : t.palette.primary_950,
|
|
||||||
},
|
},
|
||||||
flatten(style),
|
flatten(style),
|
||||||
]}>
|
]}>
|
||||||
|
|
|
@ -357,12 +357,11 @@ function TargetToggle({children}: React.PropsWithChildren<{}>) {
|
||||||
a.px_sm,
|
a.px_sm,
|
||||||
gtMobile && a.px_md,
|
gtMobile && a.px_md,
|
||||||
a.rounded_sm,
|
a.rounded_sm,
|
||||||
t.atoms.bg_contrast_50,
|
t.atoms.bg_contrast_25,
|
||||||
(ctx.hovered || ctx.focused) && t.atoms.bg_contrast_100,
|
(ctx.hovered || ctx.focused) && t.atoms.bg_contrast_50,
|
||||||
ctx.selected && [
|
ctx.selected && [
|
||||||
{
|
{
|
||||||
backgroundColor:
|
backgroundColor: t.palette.primary_50,
|
||||||
t.name === 'light' ? t.palette.primary_50 : t.palette.primary_975,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
ctx.disabled && {
|
ctx.disabled && {
|
||||||
|
|
|
@ -196,10 +196,7 @@ function Selectable({
|
||||||
t.atoms.bg_contrast_50,
|
t.atoms.bg_contrast_50,
|
||||||
(hovered || focused) && t.atoms.bg_contrast_100,
|
(hovered || focused) && t.atoms.bg_contrast_100,
|
||||||
isSelected && {
|
isSelected && {
|
||||||
backgroundColor:
|
backgroundColor: t.palette.primary_100,
|
||||||
t.name === 'light'
|
|
||||||
? t.palette.primary_50
|
|
||||||
: t.palette.primary_975,
|
|
||||||
},
|
},
|
||||||
style,
|
style,
|
||||||
]}>
|
]}>
|
||||||
|
|
|
@ -72,8 +72,7 @@ let MessageItem = ({
|
||||||
lastInGroupRef.current = isLastInGroup
|
lastInGroupRef.current = isLastInGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
const pendingColor =
|
const pendingColor = t.palette.primary_200
|
||||||
t.name === 'light' ? t.palette.primary_200 : t.palette.primary_800
|
|
||||||
|
|
||||||
const rt = useMemo(() => {
|
const rt = useMemo(() => {
|
||||||
return new RichTextAPI({text: message.text, facets: message.facets})
|
return new RichTextAPI({text: message.text, facets: message.facets})
|
||||||
|
@ -110,12 +109,7 @@ let MessageItem = ({
|
||||||
}>
|
}>
|
||||||
<RichText
|
<RichText
|
||||||
value={rt}
|
value={rt}
|
||||||
style={[
|
style={[a.text_md, isFromSelf && {color: t.palette.white}]}
|
||||||
a.text_md,
|
|
||||||
isFromSelf && {color: t.palette.white},
|
|
||||||
isPending &&
|
|
||||||
t.name !== 'light' && {color: t.palette.primary_300},
|
|
||||||
]}
|
|
||||||
interactiveStyle={a.underline}
|
interactiveStyle={a.underline}
|
||||||
enableTags
|
enableTags
|
||||||
emojiMultiplier={3}
|
emojiMultiplier={3}
|
||||||
|
|
|
@ -101,16 +101,13 @@ export function useSharedInputStyles() {
|
||||||
]
|
]
|
||||||
const error: ViewStyle[] = [
|
const error: ViewStyle[] = [
|
||||||
{
|
{
|
||||||
backgroundColor:
|
backgroundColor: t.palette.negative_25,
|
||||||
t.name === 'light' ? t.palette.negative_25 : t.palette.negative_900,
|
borderColor: t.palette.negative_300,
|
||||||
borderColor:
|
|
||||||
t.name === 'light' ? t.palette.negative_300 : t.palette.negative_800,
|
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
const errorHover: ViewStyle[] = [
|
const errorHover: ViewStyle[] = [
|
||||||
{
|
{
|
||||||
backgroundColor:
|
backgroundColor: t.palette.negative_25,
|
||||||
t.name === 'light' ? t.palette.negative_25 : t.palette.negative_900,
|
|
||||||
borderColor: t.palette.negative_500,
|
borderColor: t.palette.negative_500,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
|
@ -281,24 +281,20 @@ export function createSharedToggleStyles({
|
||||||
|
|
||||||
if (selected) {
|
if (selected) {
|
||||||
base.push({
|
base.push({
|
||||||
backgroundColor:
|
backgroundColor: t.palette.primary_25,
|
||||||
t.name === 'light' ? t.palette.primary_25 : t.palette.primary_900,
|
|
||||||
borderColor: t.palette.primary_500,
|
borderColor: t.palette.primary_500,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (hovered) {
|
if (hovered) {
|
||||||
baseHover.push({
|
baseHover.push({
|
||||||
backgroundColor:
|
backgroundColor: t.palette.primary_100,
|
||||||
t.name === 'light' ? t.palette.primary_100 : t.palette.primary_800,
|
borderColor: t.palette.primary_600,
|
||||||
borderColor:
|
|
||||||
t.name === 'light' ? t.palette.primary_600 : t.palette.primary_400,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (hovered) {
|
if (hovered) {
|
||||||
baseHover.push({
|
baseHover.push({
|
||||||
backgroundColor:
|
backgroundColor: t.palette.contrast_50,
|
||||||
t.name === 'light' ? t.palette.contrast_50 : t.palette.contrast_100,
|
|
||||||
borderColor: t.palette.contrast_500,
|
borderColor: t.palette.contrast_500,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -306,16 +302,13 @@ export function createSharedToggleStyles({
|
||||||
|
|
||||||
if (isInvalid) {
|
if (isInvalid) {
|
||||||
base.push({
|
base.push({
|
||||||
backgroundColor:
|
backgroundColor: t.palette.negative_25,
|
||||||
t.name === 'light' ? t.palette.negative_25 : t.palette.negative_975,
|
borderColor: t.palette.negative_300,
|
||||||
borderColor:
|
|
||||||
t.name === 'light' ? t.palette.negative_300 : t.palette.negative_800,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if (hovered) {
|
if (hovered) {
|
||||||
baseHover.push({
|
baseHover.push({
|
||||||
backgroundColor:
|
backgroundColor: t.palette.negative_25,
|
||||||
t.name === 'light' ? t.palette.negative_25 : t.palette.negative_900,
|
|
||||||
borderColor: t.palette.negative_600,
|
borderColor: t.palette.negative_600,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import type {PathProps, SvgProps} from 'react-native-svg'
|
||||||
import {Defs, LinearGradient, Stop} from 'react-native-svg'
|
import {Defs, LinearGradient, Stop} from 'react-native-svg'
|
||||||
import {nanoid} from 'nanoid/non-secure'
|
import {nanoid} from 'nanoid/non-secure'
|
||||||
|
|
||||||
import {tokens} from '#/alf'
|
import {tokens, useTheme} from '#/alf'
|
||||||
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
fill?: PathProps['fill']
|
fill?: PathProps['fill']
|
||||||
|
@ -22,10 +22,11 @@ export const sizes = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useCommonSVGProps(props: Props) {
|
export function useCommonSVGProps(props: Props) {
|
||||||
|
const t = useTheme()
|
||||||
const {fill, size, gradient, ...rest} = props
|
const {fill, size, gradient, ...rest} = props
|
||||||
const style = StyleSheet.flatten(rest.style)
|
const style = StyleSheet.flatten(rest.style)
|
||||||
const _size = Number(size ? sizes[size] : rest.width || sizes.md)
|
const _size = Number(size ? sizes[size] : rest.width || sizes.md)
|
||||||
let _fill = fill || style?.color || tokens.color.blue_500
|
let _fill = fill || style?.color || t.palette.primary_500
|
||||||
let gradientDef = null
|
let gradientDef = null
|
||||||
|
|
||||||
if (gradient && tokens.gradients[gradient]) {
|
if (gradient && tokens.gradients[gradient]) {
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import React, {ReactNode, createContext, useContext} from 'react'
|
import React, {createContext, ReactNode, useContext} from 'react'
|
||||||
import {TextStyle, ViewStyle} from 'react-native'
|
import {TextStyle, ViewStyle} from 'react-native'
|
||||||
|
|
||||||
|
import {ThemeName} from '#/alf/types'
|
||||||
import {darkTheme, defaultTheme, dimTheme} from './themes'
|
import {darkTheme, defaultTheme, dimTheme} from './themes'
|
||||||
import {ThemeName} from '#/alf/themes'
|
|
||||||
|
|
||||||
export type ColorScheme = 'light' | 'dark'
|
export type ColorScheme = 'light' | 'dark'
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import {Platform} from 'react-native'
|
import {Platform} from 'react-native'
|
||||||
import type {Theme} from './ThemeContext'
|
|
||||||
import {colors} from './styles'
|
|
||||||
|
|
||||||
import {darkPalette, lightPalette, dimPalette} from '#/alf/themes'
|
import {darkPalette, dimPalette, lightPalette} from '#/alf/themes'
|
||||||
|
import {colors} from './styles'
|
||||||
|
import type {Theme} from './ThemeContext'
|
||||||
|
|
||||||
export const defaultTheme: Theme = {
|
export const defaultTheme: Theme = {
|
||||||
colorScheme: 'light',
|
colorScheme: 'light',
|
||||||
|
@ -308,8 +308,8 @@ export const darkTheme: Theme = {
|
||||||
textVeryLight: darkPalette.contrast_400,
|
textVeryLight: darkPalette.contrast_400,
|
||||||
replyLine: darkPalette.contrast_200,
|
replyLine: darkPalette.contrast_200,
|
||||||
replyLineDot: darkPalette.contrast_200,
|
replyLineDot: darkPalette.contrast_200,
|
||||||
unreadNotifBg: darkPalette.primary_975,
|
unreadNotifBg: darkPalette.primary_25,
|
||||||
unreadNotifBorder: darkPalette.primary_900,
|
unreadNotifBorder: darkPalette.primary_100,
|
||||||
postCtrl: darkPalette.contrast_500,
|
postCtrl: darkPalette.contrast_500,
|
||||||
brandText: darkPalette.primary_500,
|
brandText: darkPalette.primary_500,
|
||||||
emptyStateIcon: darkPalette.contrast_300,
|
emptyStateIcon: darkPalette.contrast_300,
|
||||||
|
@ -357,8 +357,8 @@ export const dimTheme: Theme = {
|
||||||
textVeryLight: dimPalette.contrast_400,
|
textVeryLight: dimPalette.contrast_400,
|
||||||
replyLine: dimPalette.contrast_200,
|
replyLine: dimPalette.contrast_200,
|
||||||
replyLineDot: dimPalette.contrast_200,
|
replyLineDot: dimPalette.contrast_200,
|
||||||
unreadNotifBg: dimPalette.primary_975,
|
unreadNotifBg: dimPalette.primary_25,
|
||||||
unreadNotifBorder: dimPalette.primary_900,
|
unreadNotifBorder: dimPalette.primary_100,
|
||||||
postCtrl: dimPalette.contrast_500,
|
postCtrl: dimPalette.contrast_500,
|
||||||
brandText: dimPalette.primary_500,
|
brandText: dimPalette.primary_500,
|
||||||
emptyStateIcon: dimPalette.contrast_300,
|
emptyStateIcon: dimPalette.contrast_300,
|
||||||
|
|
|
@ -20,29 +20,31 @@ export function Buttons() {
|
||||||
<H1>Buttons</H1>
|
<H1>Buttons</H1>
|
||||||
|
|
||||||
<View style={[a.flex_row, a.flex_wrap, a.gap_md, a.align_start]}>
|
<View style={[a.flex_row, a.flex_wrap, a.gap_md, a.align_start]}>
|
||||||
{['primary', 'secondary', 'secondary_inverted'].map(color => (
|
{['primary', 'secondary', 'secondary_inverted', 'negative'].map(
|
||||||
<View key={color} style={[a.gap_md, a.align_start]}>
|
color => (
|
||||||
{['solid', 'outline', 'ghost'].map(variant => (
|
<View key={color} style={[a.gap_md, a.align_start]}>
|
||||||
<React.Fragment key={variant}>
|
{['solid', 'outline', 'ghost'].map(variant => (
|
||||||
<Button
|
<React.Fragment key={variant}>
|
||||||
variant={variant as ButtonVariant}
|
<Button
|
||||||
color={color as ButtonColor}
|
variant={variant as ButtonVariant}
|
||||||
size="large"
|
color={color as ButtonColor}
|
||||||
label="Click here">
|
size="large"
|
||||||
<ButtonText>Button</ButtonText>
|
label="Click here">
|
||||||
</Button>
|
<ButtonText>Button</ButtonText>
|
||||||
<Button
|
</Button>
|
||||||
disabled
|
<Button
|
||||||
variant={variant as ButtonVariant}
|
disabled
|
||||||
color={color as ButtonColor}
|
variant={variant as ButtonVariant}
|
||||||
size="large"
|
color={color as ButtonColor}
|
||||||
label="Click here">
|
size="large"
|
||||||
<ButtonText>Button</ButtonText>
|
label="Click here">
|
||||||
</Button>
|
<ButtonText>Button</ButtonText>
|
||||||
</React.Fragment>
|
</Button>
|
||||||
))}
|
</React.Fragment>
|
||||||
</View>
|
))}
|
||||||
))}
|
</View>
|
||||||
|
),
|
||||||
|
)}
|
||||||
|
|
||||||
<View style={[a.flex_row, a.gap_md, a.align_start]}>
|
<View style={[a.flex_row, a.gap_md, a.align_start]}>
|
||||||
<View style={[a.gap_md, a.align_start]}>
|
<View style={[a.gap_md, a.align_start]}>
|
||||||
|
@ -68,6 +70,7 @@ export function Buttons() {
|
||||||
),
|
),
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
{/*
|
||||||
<View style={[a.gap_md, a.align_start]}>
|
<View style={[a.gap_md, a.align_start]}>
|
||||||
{['gradient_sunset', 'gradient_nordic', 'gradient_bonfire'].map(
|
{['gradient_sunset', 'gradient_nordic', 'gradient_bonfire'].map(
|
||||||
name => (
|
name => (
|
||||||
|
@ -91,6 +94,7 @@ export function Buttons() {
|
||||||
),
|
),
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
*/}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,16 @@ export function Forms() {
|
||||||
/>
|
/>
|
||||||
</TextField.Root>
|
</TextField.Root>
|
||||||
|
|
||||||
|
<TextField.Root>
|
||||||
|
<TextField.Icon icon={Globe} />
|
||||||
|
<TextField.Input
|
||||||
|
value={value}
|
||||||
|
onChangeText={setValue}
|
||||||
|
label="Text field"
|
||||||
|
isInvalid
|
||||||
|
/>
|
||||||
|
</TextField.Root>
|
||||||
|
|
||||||
<View style={[a.w_full]}>
|
<View style={[a.w_full]}>
|
||||||
<TextField.LabelText>Text field</TextField.LabelText>
|
<TextField.LabelText>Text field</TextField.LabelText>
|
||||||
<TextField.Root>
|
<TextField.Root>
|
||||||
|
|
Loading…
Reference in New Issue