diff --git a/package.json b/package.json index 71c28fe0a..df8155d0c 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,6 @@ "@atproto/api": "^0.16.7", "@bitdrift/react-native": "^0.6.8", "@braintree/sanitize-url": "^6.0.2", - "@bsky.app/alf": "^0.1.2", "@discord/bottom-sheet": "bluesky-social/react-native-bottom-sheet", "@emoji-mart/react": "^1.1.1", "@expo/html-elements": "^0.12.5", diff --git a/src/alf/atoms.ts b/src/alf/atoms.ts index 3168b1da1..dc5d9f59c 100644 --- a/src/alf/atoms.ts +++ b/src/alf/atoms.ts @@ -1,15 +1,115 @@ -import {type StyleProp, type ViewStyle} from 'react-native' -import {atoms as baseAtoms} from '@bsky.app/alf' +import { + Platform, + type StyleProp, + StyleSheet, + type ViewStyle, +} from 'react-native' -import {native, platform, web} from '#/alf/util/platform' +import * as tokens from '#/alf/tokens' +import {ios, native, platform, web} from '#/alf/util/platform' import * as Layout from '#/components/Layout' export const atoms = { - ...baseAtoms, + debug: { + borderColor: 'red', + borderWidth: 1, + }, + /* + * Positioning + */ + fixed: { + position: Platform.select({web: 'fixed', native: 'absolute'}) as 'absolute', + }, + absolute: { + position: 'absolute', + }, + relative: { + position: 'relative', + }, + static: { + position: 'static', + }, + sticky: web({ + position: 'sticky', + }), + inset_0: { + top: 0, + left: 0, + right: 0, + bottom: 0, + }, + top_0: { + top: 0, + }, + right_0: { + right: 0, + }, + bottom_0: { + bottom: 0, + }, + left_0: { + left: 0, + }, + z_10: { + zIndex: 10, + }, + z_20: { + zIndex: 20, + }, + z_30: { + zIndex: 30, + }, + z_40: { + zIndex: 40, + }, + z_50: { + zIndex: 50, + }, + + overflow_visible: { + overflow: 'visible', + }, + overflow_x_visible: { + overflowX: 'visible', + }, + overflow_y_visible: { + overflowY: 'visible', + }, + overflow_hidden: { + overflow: 'hidden', + }, + overflow_x_hidden: { + overflowX: 'hidden', + }, + overflow_y_hidden: { + overflowY: 'hidden', + }, + /** + * @platform web + */ + overflow_auto: web({ + overflow: 'auto', + }), + + /* + * Width & Height + */ + w_full: { + width: '100%', + }, + h_full: { + height: '100%', + }, h_full_vh: web({ height: '100vh', }), + max_w_full: { + maxWidth: '100%', + }, + max_h_full: { + maxHeight: '100%', + }, /** * Used for the outermost components on screens, to ensure that they can fill @@ -31,6 +131,895 @@ export const atoms = { backgroundColor: 'transparent', }, + /* + * Border radius + */ + rounded_0: { + borderRadius: 0, + }, + rounded_2xs: { + borderRadius: tokens.borderRadius._2xs, + }, + rounded_xs: { + borderRadius: tokens.borderRadius.xs, + }, + rounded_sm: { + borderRadius: tokens.borderRadius.sm, + }, + rounded_md: { + borderRadius: tokens.borderRadius.md, + }, + rounded_lg: { + borderRadius: tokens.borderRadius.lg, + }, + rounded_full: { + borderRadius: tokens.borderRadius.full, + }, + + /* + * Flex + */ + gap_0: { + gap: 0, + }, + gap_2xs: { + gap: tokens.space._2xs, + }, + gap_xs: { + gap: tokens.space.xs, + }, + gap_sm: { + gap: tokens.space.sm, + }, + gap_md: { + gap: tokens.space.md, + }, + gap_lg: { + gap: tokens.space.lg, + }, + gap_xl: { + gap: tokens.space.xl, + }, + gap_2xl: { + gap: tokens.space._2xl, + }, + gap_3xl: { + gap: tokens.space._3xl, + }, + gap_4xl: { + gap: tokens.space._4xl, + }, + gap_5xl: { + gap: tokens.space._5xl, + }, + flex: { + display: 'flex', + }, + flex_col: { + flexDirection: 'column', + }, + flex_row: { + flexDirection: 'row', + }, + flex_col_reverse: { + flexDirection: 'column-reverse', + }, + flex_row_reverse: { + flexDirection: 'row-reverse', + }, + flex_wrap: { + flexWrap: 'wrap', + }, + flex_nowrap: { + flexWrap: 'nowrap', + }, + flex_0: { + flex: web('0 0 auto') || (native(0) as number), + }, + flex_1: { + flex: 1, + }, + flex_grow: { + flexGrow: 1, + }, + flex_grow_0: { + flexGrow: 0, + }, + flex_shrink: { + flexShrink: 1, + }, + flex_shrink_0: { + flexShrink: 0, + }, + justify_start: { + justifyContent: 'flex-start', + }, + justify_center: { + justifyContent: 'center', + }, + justify_between: { + justifyContent: 'space-between', + }, + justify_end: { + justifyContent: 'flex-end', + }, + align_center: { + alignItems: 'center', + }, + align_start: { + alignItems: 'flex-start', + }, + align_end: { + alignItems: 'flex-end', + }, + align_baseline: { + alignItems: 'baseline', + }, + align_stretch: { + alignItems: 'stretch', + }, + self_auto: { + alignSelf: 'auto', + }, + self_start: { + alignSelf: 'flex-start', + }, + self_end: { + alignSelf: 'flex-end', + }, + self_center: { + alignSelf: 'center', + }, + self_stretch: { + alignSelf: 'stretch', + }, + self_baseline: { + alignSelf: 'baseline', + }, + + /* + * Text + */ + text_left: { + textAlign: 'left', + }, + text_center: { + textAlign: 'center', + }, + text_right: { + textAlign: 'right', + }, + text_2xs: { + fontSize: tokens.fontSize._2xs, + letterSpacing: tokens.TRACKING, + }, + text_xs: { + fontSize: tokens.fontSize.xs, + letterSpacing: tokens.TRACKING, + }, + text_sm: { + fontSize: tokens.fontSize.sm, + letterSpacing: tokens.TRACKING, + }, + text_md: { + fontSize: tokens.fontSize.md, + letterSpacing: tokens.TRACKING, + }, + text_lg: { + fontSize: tokens.fontSize.lg, + letterSpacing: tokens.TRACKING, + }, + text_xl: { + fontSize: tokens.fontSize.xl, + letterSpacing: tokens.TRACKING, + }, + text_2xl: { + fontSize: tokens.fontSize._2xl, + letterSpacing: tokens.TRACKING, + }, + text_3xl: { + fontSize: tokens.fontSize._3xl, + letterSpacing: tokens.TRACKING, + }, + text_4xl: { + fontSize: tokens.fontSize._4xl, + letterSpacing: tokens.TRACKING, + }, + text_5xl: { + fontSize: tokens.fontSize._5xl, + letterSpacing: tokens.TRACKING, + }, + leading_tight: { + lineHeight: 1.15, + }, + leading_snug: { + lineHeight: 1.3, + }, + leading_normal: { + lineHeight: 1.5, + }, + tracking_normal: { + letterSpacing: tokens.TRACKING, + }, + font_normal: { + fontWeight: tokens.fontWeight.normal, + }, + font_medium: { + fontWeight: tokens.fontWeight.medium, + }, + font_bold: { + fontWeight: tokens.fontWeight.bold, + }, + font_heavy: { + fontWeight: tokens.fontWeight.heavy, + }, + italic: { + fontStyle: 'italic', + }, + + /* + * Border + */ + border_0: { + borderWidth: 0, + }, + border_t_0: { + borderTopWidth: 0, + }, + border_b_0: { + borderBottomWidth: 0, + }, + border_l_0: { + borderLeftWidth: 0, + }, + border_r_0: { + borderRightWidth: 0, + }, + border_x_0: { + borderLeftWidth: 0, + borderRightWidth: 0, + }, + border_y_0: { + borderTopWidth: 0, + borderBottomWidth: 0, + }, + border: { + borderWidth: StyleSheet.hairlineWidth, + }, + border_t: { + borderTopWidth: StyleSheet.hairlineWidth, + }, + border_b: { + borderBottomWidth: StyleSheet.hairlineWidth, + }, + border_l: { + borderLeftWidth: StyleSheet.hairlineWidth, + }, + border_r: { + borderRightWidth: StyleSheet.hairlineWidth, + }, + border_x: { + borderLeftWidth: StyleSheet.hairlineWidth, + borderRightWidth: StyleSheet.hairlineWidth, + }, + border_y: { + borderTopWidth: StyleSheet.hairlineWidth, + borderBottomWidth: StyleSheet.hairlineWidth, + }, + border_transparent: { + borderColor: 'transparent', + }, + curve_circular: ios({ + borderCurve: 'circular', + }), + curve_continuous: ios({ + borderCurve: 'continuous', + }), + + /* + * Shadow + */ + shadow_sm: { + shadowRadius: 8, + shadowOpacity: 0.1, + elevation: 8, + }, + shadow_md: { + shadowRadius: 16, + shadowOpacity: 0.1, + elevation: 16, + }, + shadow_lg: { + shadowRadius: 32, + shadowOpacity: 0.1, + elevation: 24, + }, + + /* + * Padding + */ + p_0: { + padding: 0, + }, + p_2xs: { + padding: tokens.space._2xs, + }, + p_xs: { + padding: tokens.space.xs, + }, + p_sm: { + padding: tokens.space.sm, + }, + p_md: { + padding: tokens.space.md, + }, + p_lg: { + padding: tokens.space.lg, + }, + p_xl: { + padding: tokens.space.xl, + }, + p_2xl: { + padding: tokens.space._2xl, + }, + p_3xl: { + padding: tokens.space._3xl, + }, + p_4xl: { + padding: tokens.space._4xl, + }, + p_5xl: { + padding: tokens.space._5xl, + }, + px_0: { + paddingLeft: 0, + paddingRight: 0, + }, + px_2xs: { + paddingLeft: tokens.space._2xs, + paddingRight: tokens.space._2xs, + }, + px_xs: { + paddingLeft: tokens.space.xs, + paddingRight: tokens.space.xs, + }, + px_sm: { + paddingLeft: tokens.space.sm, + paddingRight: tokens.space.sm, + }, + px_md: { + paddingLeft: tokens.space.md, + paddingRight: tokens.space.md, + }, + px_lg: { + paddingLeft: tokens.space.lg, + paddingRight: tokens.space.lg, + }, + px_xl: { + paddingLeft: tokens.space.xl, + paddingRight: tokens.space.xl, + }, + px_2xl: { + paddingLeft: tokens.space._2xl, + paddingRight: tokens.space._2xl, + }, + px_3xl: { + paddingLeft: tokens.space._3xl, + paddingRight: tokens.space._3xl, + }, + px_4xl: { + paddingLeft: tokens.space._4xl, + paddingRight: tokens.space._4xl, + }, + px_5xl: { + paddingLeft: tokens.space._5xl, + paddingRight: tokens.space._5xl, + }, + py_0: { + paddingTop: 0, + paddingBottom: 0, + }, + py_2xs: { + paddingTop: tokens.space._2xs, + paddingBottom: tokens.space._2xs, + }, + py_xs: { + paddingTop: tokens.space.xs, + paddingBottom: tokens.space.xs, + }, + py_sm: { + paddingTop: tokens.space.sm, + paddingBottom: tokens.space.sm, + }, + py_md: { + paddingTop: tokens.space.md, + paddingBottom: tokens.space.md, + }, + py_lg: { + paddingTop: tokens.space.lg, + paddingBottom: tokens.space.lg, + }, + py_xl: { + paddingTop: tokens.space.xl, + paddingBottom: tokens.space.xl, + }, + py_2xl: { + paddingTop: tokens.space._2xl, + paddingBottom: tokens.space._2xl, + }, + py_3xl: { + paddingTop: tokens.space._3xl, + paddingBottom: tokens.space._3xl, + }, + py_4xl: { + paddingTop: tokens.space._4xl, + paddingBottom: tokens.space._4xl, + }, + py_5xl: { + paddingTop: tokens.space._5xl, + paddingBottom: tokens.space._5xl, + }, + pt_0: { + paddingTop: 0, + }, + pt_2xs: { + paddingTop: tokens.space._2xs, + }, + pt_xs: { + paddingTop: tokens.space.xs, + }, + pt_sm: { + paddingTop: tokens.space.sm, + }, + pt_md: { + paddingTop: tokens.space.md, + }, + pt_lg: { + paddingTop: tokens.space.lg, + }, + pt_xl: { + paddingTop: tokens.space.xl, + }, + pt_2xl: { + paddingTop: tokens.space._2xl, + }, + pt_3xl: { + paddingTop: tokens.space._3xl, + }, + pt_4xl: { + paddingTop: tokens.space._4xl, + }, + pt_5xl: { + paddingTop: tokens.space._5xl, + }, + pb_0: { + paddingBottom: 0, + }, + pb_2xs: { + paddingBottom: tokens.space._2xs, + }, + pb_xs: { + paddingBottom: tokens.space.xs, + }, + pb_sm: { + paddingBottom: tokens.space.sm, + }, + pb_md: { + paddingBottom: tokens.space.md, + }, + pb_lg: { + paddingBottom: tokens.space.lg, + }, + pb_xl: { + paddingBottom: tokens.space.xl, + }, + pb_2xl: { + paddingBottom: tokens.space._2xl, + }, + pb_3xl: { + paddingBottom: tokens.space._3xl, + }, + pb_4xl: { + paddingBottom: tokens.space._4xl, + }, + pb_5xl: { + paddingBottom: tokens.space._5xl, + }, + pl_0: { + paddingLeft: 0, + }, + pl_2xs: { + paddingLeft: tokens.space._2xs, + }, + pl_xs: { + paddingLeft: tokens.space.xs, + }, + pl_sm: { + paddingLeft: tokens.space.sm, + }, + pl_md: { + paddingLeft: tokens.space.md, + }, + pl_lg: { + paddingLeft: tokens.space.lg, + }, + pl_xl: { + paddingLeft: tokens.space.xl, + }, + pl_2xl: { + paddingLeft: tokens.space._2xl, + }, + pl_3xl: { + paddingLeft: tokens.space._3xl, + }, + pl_4xl: { + paddingLeft: tokens.space._4xl, + }, + pl_5xl: { + paddingLeft: tokens.space._5xl, + }, + pr_0: { + paddingRight: 0, + }, + pr_2xs: { + paddingRight: tokens.space._2xs, + }, + pr_xs: { + paddingRight: tokens.space.xs, + }, + pr_sm: { + paddingRight: tokens.space.sm, + }, + pr_md: { + paddingRight: tokens.space.md, + }, + pr_lg: { + paddingRight: tokens.space.lg, + }, + pr_xl: { + paddingRight: tokens.space.xl, + }, + pr_2xl: { + paddingRight: tokens.space._2xl, + }, + pr_3xl: { + paddingRight: tokens.space._3xl, + }, + pr_4xl: { + paddingRight: tokens.space._4xl, + }, + pr_5xl: { + paddingRight: tokens.space._5xl, + }, + + /* + * Margin + */ + m_0: { + margin: 0, + }, + m_2xs: { + margin: tokens.space._2xs, + }, + m_xs: { + margin: tokens.space.xs, + }, + m_sm: { + margin: tokens.space.sm, + }, + m_md: { + margin: tokens.space.md, + }, + m_lg: { + margin: tokens.space.lg, + }, + m_xl: { + margin: tokens.space.xl, + }, + m_2xl: { + margin: tokens.space._2xl, + }, + m_3xl: { + margin: tokens.space._3xl, + }, + m_4xl: { + margin: tokens.space._4xl, + }, + m_5xl: { + margin: tokens.space._5xl, + }, + m_auto: { + margin: 'auto', + }, + mx_0: { + marginLeft: 0, + marginRight: 0, + }, + mx_2xs: { + marginLeft: tokens.space._2xs, + marginRight: tokens.space._2xs, + }, + mx_xs: { + marginLeft: tokens.space.xs, + marginRight: tokens.space.xs, + }, + mx_sm: { + marginLeft: tokens.space.sm, + marginRight: tokens.space.sm, + }, + mx_md: { + marginLeft: tokens.space.md, + marginRight: tokens.space.md, + }, + mx_lg: { + marginLeft: tokens.space.lg, + marginRight: tokens.space.lg, + }, + mx_xl: { + marginLeft: tokens.space.xl, + marginRight: tokens.space.xl, + }, + mx_2xl: { + marginLeft: tokens.space._2xl, + marginRight: tokens.space._2xl, + }, + mx_3xl: { + marginLeft: tokens.space._3xl, + marginRight: tokens.space._3xl, + }, + mx_4xl: { + marginLeft: tokens.space._4xl, + marginRight: tokens.space._4xl, + }, + mx_5xl: { + marginLeft: tokens.space._5xl, + marginRight: tokens.space._5xl, + }, + mx_auto: { + marginLeft: 'auto', + marginRight: 'auto', + }, + my_0: { + marginTop: 0, + marginBottom: 0, + }, + my_2xs: { + marginTop: tokens.space._2xs, + marginBottom: tokens.space._2xs, + }, + my_xs: { + marginTop: tokens.space.xs, + marginBottom: tokens.space.xs, + }, + my_sm: { + marginTop: tokens.space.sm, + marginBottom: tokens.space.sm, + }, + my_md: { + marginTop: tokens.space.md, + marginBottom: tokens.space.md, + }, + my_lg: { + marginTop: tokens.space.lg, + marginBottom: tokens.space.lg, + }, + my_xl: { + marginTop: tokens.space.xl, + marginBottom: tokens.space.xl, + }, + my_2xl: { + marginTop: tokens.space._2xl, + marginBottom: tokens.space._2xl, + }, + my_3xl: { + marginTop: tokens.space._3xl, + marginBottom: tokens.space._3xl, + }, + my_4xl: { + marginTop: tokens.space._4xl, + marginBottom: tokens.space._4xl, + }, + my_5xl: { + marginTop: tokens.space._5xl, + marginBottom: tokens.space._5xl, + }, + my_auto: { + marginTop: 'auto', + marginBottom: 'auto', + }, + mt_0: { + marginTop: 0, + }, + mt_2xs: { + marginTop: tokens.space._2xs, + }, + mt_xs: { + marginTop: tokens.space.xs, + }, + mt_sm: { + marginTop: tokens.space.sm, + }, + mt_md: { + marginTop: tokens.space.md, + }, + mt_lg: { + marginTop: tokens.space.lg, + }, + mt_xl: { + marginTop: tokens.space.xl, + }, + mt_2xl: { + marginTop: tokens.space._2xl, + }, + mt_3xl: { + marginTop: tokens.space._3xl, + }, + mt_4xl: { + marginTop: tokens.space._4xl, + }, + mt_5xl: { + marginTop: tokens.space._5xl, + }, + mt_auto: { + marginTop: 'auto', + }, + mb_0: { + marginBottom: 0, + }, + mb_2xs: { + marginBottom: tokens.space._2xs, + }, + mb_xs: { + marginBottom: tokens.space.xs, + }, + mb_sm: { + marginBottom: tokens.space.sm, + }, + mb_md: { + marginBottom: tokens.space.md, + }, + mb_lg: { + marginBottom: tokens.space.lg, + }, + mb_xl: { + marginBottom: tokens.space.xl, + }, + mb_2xl: { + marginBottom: tokens.space._2xl, + }, + mb_3xl: { + marginBottom: tokens.space._3xl, + }, + mb_4xl: { + marginBottom: tokens.space._4xl, + }, + mb_5xl: { + marginBottom: tokens.space._5xl, + }, + mb_auto: { + marginBottom: 'auto', + }, + ml_0: { + marginLeft: 0, + }, + ml_2xs: { + marginLeft: tokens.space._2xs, + }, + ml_xs: { + marginLeft: tokens.space.xs, + }, + ml_sm: { + marginLeft: tokens.space.sm, + }, + ml_md: { + marginLeft: tokens.space.md, + }, + ml_lg: { + marginLeft: tokens.space.lg, + }, + ml_xl: { + marginLeft: tokens.space.xl, + }, + ml_2xl: { + marginLeft: tokens.space._2xl, + }, + ml_3xl: { + marginLeft: tokens.space._3xl, + }, + ml_4xl: { + marginLeft: tokens.space._4xl, + }, + ml_5xl: { + marginLeft: tokens.space._5xl, + }, + ml_auto: { + marginLeft: 'auto', + }, + mr_0: { + marginRight: 0, + }, + mr_2xs: { + marginRight: tokens.space._2xs, + }, + mr_xs: { + marginRight: tokens.space.xs, + }, + mr_sm: { + marginRight: tokens.space.sm, + }, + mr_md: { + marginRight: tokens.space.md, + }, + mr_lg: { + marginRight: tokens.space.lg, + }, + mr_xl: { + marginRight: tokens.space.xl, + }, + mr_2xl: { + marginRight: tokens.space._2xl, + }, + mr_3xl: { + marginRight: tokens.space._3xl, + }, + mr_4xl: { + marginRight: tokens.space._4xl, + }, + mr_5xl: { + marginRight: tokens.space._5xl, + }, + mr_auto: { + marginRight: 'auto', + }, + + /* + * Pointer events & user select + */ + pointer_events_none: { + pointerEvents: 'none', + }, + pointer_events_auto: { + pointerEvents: 'auto', + }, + user_select_none: { + userSelect: 'none', + }, + user_select_text: { + userSelect: 'text', + }, + user_select_all: { + userSelect: 'all', + }, + outline_inset_1: { + outlineOffset: -1, + }, + + /* + * Text decoration + */ + underline: { + textDecorationLine: 'underline', + }, + strike_through: { + textDecorationLine: 'line-through', + }, + + /* + * Display + */ + hidden: { + display: 'none', + }, + inline: web({ + display: 'inline', + }), + block: web({ + display: 'block', + }), + contents: web({ + display: 'contents', + }), + /* * Transition */ @@ -110,4 +1099,8 @@ export const atoms = { transform: [], }, }) as {transform: Exclude}, + + pointer: web({ + cursor: 'pointer', + }), } as const diff --git a/src/alf/fonts.ts b/src/alf/fonts.ts index ddf4c0b18..7366edef2 100644 --- a/src/alf/fonts.ts +++ b/src/alf/fonts.ts @@ -7,11 +7,11 @@ const WEB_FONT_FAMILIES = `system-ui, -apple-system, BlinkMacSystemFont, "Segoe const factor = 0.0625 // 1 - (15/16) const fontScaleMultipliers: Record = { - '-2': 1 - factor * 1, // unused - '-1': 1 - factor * 1, - '0': 1, // default - '1': 1 + factor * 1, - '2': 1 + factor * 1, // unused + '-2': 1 - factor * 3, + '-1': 1 - factor * 2, + '0': 1 - factor * 1, // default + '1': 1, + '2': 1 + factor * 1, } export function computeFontScaleMultiplier(scale: Device['fontScale']) { diff --git a/src/alf/index.tsx b/src/alf/index.tsx index eed3fcbeb..bee8ed78c 100644 --- a/src/alf/index.tsx +++ b/src/alf/index.tsx @@ -1,5 +1,4 @@ import React from 'react' -import {type Theme, type ThemeName} from '@bsky.app/alf' import { computeFontScaleMultiplier, @@ -8,14 +7,16 @@ import { setFontFamily as persistFontFamily, setFontScale as persistFontScale, } from '#/alf/fonts' -import {themes} from '#/alf/themes' +import {createThemes, defaultTheme} from '#/alf/themes' +import {type Theme, type ThemeName} from '#/alf/types' +import {BLUE_HUE, GREEN_HUE, RED_HUE} from '#/alf/util/colorGeneration' import {type Device} from '#/storage' -export {type TextStyleProp, type Theme, type ViewStyleProp} from '@bsky.app/alf' export {atoms} from '#/alf/atoms' export * from '#/alf/breakpoints' export * from '#/alf/fonts' export * as tokens from '#/alf/tokens' +export * from '#/alf/types' export * from '#/alf/util/flatten' export * from '#/alf/util/platform' export * from '#/alf/util/themeSelector' @@ -24,7 +25,7 @@ export * from '#/alf/util/useGutters' export type Alf = { themeName: ThemeName theme: Theme - themes: typeof themes + themes: ReturnType fonts: { scale: Exclude scaleMultiplier: number @@ -43,8 +44,14 @@ export type Alf = { */ export const Context = React.createContext({ themeName: 'light', - theme: themes.light, - themes, + theme: defaultTheme, + themes: createThemes({ + hues: { + primary: BLUE_HUE, + negative: RED_HUE, + positive: GREEN_HUE, + }, + }), fonts: { scale: getFontScale(), scaleMultiplier: computeFontScaleMultiplier(getFontScale()), @@ -69,10 +76,10 @@ export function ThemeProvider({ const setFontScaleAndPersist = React.useCallback< Alf['fonts']['setFontScale'] >( - fs => { - setFontScale(fs) - persistFontScale(fs) - setFontScaleMultiplier(computeFontScaleMultiplier(fs)) + fontScale => { + setFontScale(fontScale) + persistFontScale(fontScale) + setFontScaleMultiplier(computeFontScaleMultiplier(fontScale)) }, [setFontScale], ) @@ -82,12 +89,21 @@ export function ThemeProvider({ const setFontFamilyAndPersist = React.useCallback< Alf['fonts']['setFontFamily'] >( - ff => { - setFontFamily(ff) - persistFontFamily(ff) + fontFamily => { + setFontFamily(fontFamily) + persistFontFamily(fontFamily) }, [setFontFamily], ) + const themes = React.useMemo(() => { + return createThemes({ + hues: { + primary: BLUE_HUE, + negative: RED_HUE, + positive: GREEN_HUE, + }, + }) + }, []) const value = React.useMemo( () => ({ @@ -105,6 +121,7 @@ export function ThemeProvider({ }), [ themeName, + themes, fontScale, setFontScaleAndPersist, fontFamily, diff --git a/src/alf/themes.ts b/src/alf/themes.ts index 5aa86a4a5..59bd4544a 100644 --- a/src/alf/themes.ts +++ b/src/alf/themes.ts @@ -1,12 +1,23 @@ import {atoms} from '#/alf/atoms' import {mocha} from '#/alf/catppuccin/palette' import {type Palette, type Theme} from '#/alf/types' +import {type Palette, type Theme} from '#/alf/types' import {defaultScale, dimScale} from '#/alf/util/colorGeneration' +import { + BLUE_HUE, + defaultScale, + dimScale, + GREEN_HUE, + RED_HUE, +} from '#/alf/util/colorGeneration' import {fade} from '#/alf/util/colors' -const DEFAULT_THEMES = createThemes({ - defaultPalette: DEFAULT_PALETTE, - subduedPalette: DEFAULT_SUBDUED_PALETTE, +const themes = createThemes({ + hues: { + primary: BLUE_HUE, + negative: RED_HUE, + positive: GREEN_HUE, + }, }) /** @@ -603,27 +614,545 @@ export function createThemes({ } } -/** - * @deprecated use ALF and access palette from `useTheme()` - */ -export const lightPalette = DEFAULT_THEMES.light.palette -/** - * @deprecated use ALF and access palette from `useTheme()` - */ -export const darkPalette = DEFAULT_THEMES.dark.palette -/** - * @deprecated use ALF and access palette from `useTheme()` - */ -export const dimPalette = DEFAULT_THEMES.dim.palette -/** - * @deprecated use ALF and access theme from `useTheme()` - */ -export const light = DEFAULT_THEMES.light -/** - * @deprecated use ALF and access theme from `useTheme()` - */ -export const dark = DEFAULT_THEMES.dark -/** - * @deprecated use ALF and access theme from `useTheme()` - */ -export const dim = DEFAULT_THEMES.dim +export const defaultTheme = themes.light + +export function createThemes({ + hues, +}: { + hues: { + primary: number + negative: number + positive: number + } +}): { + lightPalette: Palette + darkPalette: Palette + dimPalette: Palette + light: Theme + dark: Theme + dim: Theme +} { + const color = { + like: '#ec4899', + trueBlack: '#000000', + + gray_0: `hsl(${hues.primary}, 20%, ${defaultScale[14]}%)`, + gray_25: `hsl(${hues.primary}, 20%, ${defaultScale[13]}%)`, + gray_50: `hsl(${hues.primary}, 20%, ${defaultScale[12]}%)`, + gray_100: `hsl(${hues.primary}, 20%, ${defaultScale[11]}%)`, + gray_200: `hsl(${hues.primary}, 20%, ${defaultScale[10]}%)`, + gray_300: `hsl(${hues.primary}, 20%, ${defaultScale[9]}%)`, + gray_400: `hsl(${hues.primary}, 20%, ${defaultScale[8]}%)`, + gray_500: `hsl(${hues.primary}, 20%, ${defaultScale[7]}%)`, + gray_600: `hsl(${hues.primary}, 24%, ${defaultScale[6]}%)`, + gray_700: `hsl(${hues.primary}, 24%, ${defaultScale[5]}%)`, + gray_800: `hsl(${hues.primary}, 28%, ${defaultScale[4]}%)`, + gray_900: `hsl(${hues.primary}, 28%, ${defaultScale[3]}%)`, + gray_950: `hsl(${hues.primary}, 28%, ${defaultScale[2]}%)`, + gray_975: `hsl(${hues.primary}, 28%, ${defaultScale[1]}%)`, + gray_1000: `hsl(${hues.primary}, 28%, ${defaultScale[0]}%)`, + + primary_25: `hsl(${hues.primary}, 99%, 97%)`, + primary_50: `hsl(${hues.primary}, 99%, 95%)`, + primary_100: `hsl(${hues.primary}, 99%, 90%)`, + primary_200: `hsl(${hues.primary}, 99%, 80%)`, + primary_300: `hsl(${hues.primary}, 99%, 70%)`, + primary_400: `hsl(${hues.primary}, 99%, 60%)`, + primary_500: `hsl(${hues.primary}, 99%, 53%)`, + primary_600: `hsl(${hues.primary}, 99%, 42%)`, + primary_700: `hsl(${hues.primary}, 99%, 34%)`, + primary_800: `hsl(${hues.primary}, 99%, 26%)`, + primary_900: `hsl(${hues.primary}, 99%, 18%)`, + primary_950: `hsl(${hues.primary}, 99%, 10%)`, + primary_975: `hsl(${hues.primary}, 99%, 7%)`, + + green_25: `hsl(${hues.positive}, 82%, 97%)`, + green_50: `hsl(${hues.positive}, 82%, 95%)`, + green_100: `hsl(${hues.positive}, 82%, 90%)`, + green_200: `hsl(${hues.positive}, 82%, 80%)`, + green_300: `hsl(${hues.positive}, 82%, 70%)`, + green_400: `hsl(${hues.positive}, 82%, 60%)`, + green_500: `hsl(${hues.positive}, 82%, 50%)`, + green_600: `hsl(${hues.positive}, 82%, 42%)`, + green_700: `hsl(${hues.positive}, 82%, 34%)`, + green_800: `hsl(${hues.positive}, 82%, 26%)`, + green_900: `hsl(${hues.positive}, 82%, 18%)`, + green_950: `hsl(${hues.positive}, 82%, 10%)`, + green_975: `hsl(${hues.positive}, 82%, 7%)`, + + red_25: `hsl(${hues.negative}, 91%, 97%)`, + red_50: `hsl(${hues.negative}, 91%, 95%)`, + red_100: `hsl(${hues.negative}, 91%, 90%)`, + red_200: `hsl(${hues.negative}, 91%, 80%)`, + red_300: `hsl(${hues.negative}, 91%, 70%)`, + red_400: `hsl(${hues.negative}, 91%, 60%)`, + red_500: `hsl(${hues.negative}, 91%, 50%)`, + red_600: `hsl(${hues.negative}, 91%, 42%)`, + red_700: `hsl(${hues.negative}, 91%, 34%)`, + red_800: `hsl(${hues.negative}, 91%, 26%)`, + red_900: `hsl(${hues.negative}, 91%, 18%)`, + red_950: `hsl(${hues.negative}, 91%, 10%)`, + red_975: `hsl(${hues.negative}, 91%, 7%)`, + } as const + + const lightPalette = { + white: color.gray_0, + black: color.gray_1000, + like: color.like, + + contrast_25: color.gray_25, + contrast_50: color.gray_50, + contrast_100: color.gray_100, + contrast_200: color.gray_200, + contrast_300: color.gray_300, + contrast_400: color.gray_400, + contrast_500: color.gray_500, + contrast_600: color.gray_600, + contrast_700: color.gray_700, + contrast_800: color.gray_800, + contrast_900: color.gray_900, + contrast_950: color.gray_950, + contrast_975: color.gray_975, + + primary_25: color.primary_25, + primary_50: color.primary_50, + primary_100: color.primary_100, + primary_200: color.primary_200, + primary_300: color.primary_300, + primary_400: color.primary_400, + primary_500: color.primary_500, + primary_600: color.primary_600, + primary_700: color.primary_700, + primary_800: color.primary_800, + primary_900: color.primary_900, + primary_950: color.primary_950, + primary_975: color.primary_975, + + positive_25: color.green_25, + positive_50: color.green_50, + positive_100: color.green_100, + positive_200: color.green_200, + positive_300: color.green_300, + positive_400: color.green_400, + positive_500: color.green_500, + positive_600: color.green_600, + positive_700: color.green_700, + positive_800: color.green_800, + positive_900: color.green_900, + positive_950: color.green_950, + positive_975: color.green_975, + + negative_25: color.red_25, + negative_50: color.red_50, + negative_100: color.red_100, + negative_200: color.red_200, + negative_300: color.red_300, + negative_400: color.red_400, + negative_500: color.red_500, + negative_600: color.red_600, + negative_700: color.red_700, + negative_800: color.red_800, + negative_900: color.red_900, + negative_950: color.red_950, + negative_975: color.red_975, + } as const + + const darkPalette: Palette = { + white: color.gray_25, + black: color.trueBlack, + like: color.like, + + contrast_25: color.gray_975, + contrast_50: color.gray_950, + contrast_100: color.gray_900, + contrast_200: color.gray_800, + contrast_300: color.gray_700, + contrast_400: color.gray_600, + contrast_500: color.gray_500, + contrast_600: color.gray_400, + contrast_700: color.gray_300, + contrast_800: color.gray_200, + contrast_900: color.gray_100, + contrast_950: color.gray_50, + contrast_975: color.gray_25, + + primary_25: color.primary_975, + primary_50: color.primary_950, + primary_100: color.primary_900, + primary_200: color.primary_800, + primary_300: color.primary_700, + primary_400: color.primary_600, + primary_500: color.primary_500, + primary_600: color.primary_400, + primary_700: color.primary_300, + primary_800: color.primary_200, + primary_900: color.primary_100, + primary_950: color.primary_50, + primary_975: color.primary_25, + + positive_25: color.green_975, + positive_50: color.green_950, + positive_100: color.green_900, + positive_200: color.green_800, + positive_300: color.green_700, + positive_400: color.green_600, + positive_500: color.green_500, + positive_600: color.green_400, + positive_700: color.green_300, + positive_800: color.green_200, + positive_900: color.green_100, + positive_950: color.green_50, + positive_975: color.green_25, + + negative_25: color.red_975, + negative_50: color.red_950, + negative_100: color.red_900, + negative_200: color.red_800, + negative_300: color.red_700, + negative_400: color.red_600, + negative_500: color.red_500, + negative_600: color.red_400, + negative_700: color.red_300, + negative_800: color.red_200, + negative_900: color.red_100, + negative_950: color.red_50, + negative_975: color.red_25, + } as const + + const dimPalette: Palette = { + ...darkPalette, + black: `hsl(${hues.primary}, 28%, ${dimScale[0]}%)`, + like: color.like, + + contrast_25: `hsl(${hues.primary}, 28%, ${dimScale[1]}%)`, + contrast_50: `hsl(${hues.primary}, 28%, ${dimScale[2]}%)`, + contrast_100: `hsl(${hues.primary}, 28%, ${dimScale[3]}%)`, + contrast_200: `hsl(${hues.primary}, 28%, ${dimScale[4]}%)`, + contrast_300: `hsl(${hues.primary}, 24%, ${dimScale[5]}%)`, + contrast_400: `hsl(${hues.primary}, 24%, ${dimScale[6]}%)`, + contrast_500: `hsl(${hues.primary}, 20%, ${dimScale[7]}%)`, + contrast_600: `hsl(${hues.primary}, 20%, ${dimScale[8]}%)`, + contrast_700: `hsl(${hues.primary}, 20%, ${dimScale[9]}%)`, + contrast_800: `hsl(${hues.primary}, 20%, ${dimScale[10]}%)`, + contrast_900: `hsl(${hues.primary}, 20%, ${dimScale[11]}%)`, + contrast_950: `hsl(${hues.primary}, 20%, ${dimScale[12]}%)`, + contrast_975: `hsl(${hues.primary}, 20%, ${dimScale[13]}%)`, + + primary_25: `hsl(${hues.primary}, 50%, ${dimScale[1]}%)`, + primary_50: `hsl(${hues.primary}, 60%, ${dimScale[2]}%)`, + primary_100: `hsl(${hues.primary}, 70%, ${dimScale[3]}%)`, + primary_200: `hsl(${hues.primary}, 82%, ${dimScale[4]}%)`, + primary_300: `hsl(${hues.primary}, 90%, ${dimScale[5]}%)`, + primary_400: `hsl(${hues.primary}, 95%, ${dimScale[6]}%)`, + primary_500: `hsl(${hues.primary}, 99%, ${dimScale[7]}%)`, + primary_600: `hsl(${hues.primary}, 99%, ${dimScale[8]}%)`, + primary_700: `hsl(${hues.primary}, 99%, ${dimScale[9]}%)`, + primary_800: `hsl(${hues.primary}, 99%, ${dimScale[10]}%)`, + primary_900: `hsl(${hues.primary}, 99%, ${dimScale[11]}%)`, + primary_950: `hsl(${hues.primary}, 99%, ${dimScale[12]}%)`, + primary_975: `hsl(${hues.primary}, 99%, ${dimScale[13]}%)`, + + positive_25: `hsl(${hues.positive}, 50%, ${dimScale[1]}%)`, + positive_50: `hsl(${hues.positive}, 60%, ${dimScale[2]}%)`, + positive_100: `hsl(${hues.positive}, 70%, ${dimScale[3]}%)`, + positive_200: `hsl(${hues.positive}, 82%, ${dimScale[4]}%)`, + positive_300: `hsl(${hues.positive}, 82%, ${dimScale[5]}%)`, + positive_400: `hsl(${hues.positive}, 82%, ${dimScale[6]}%)`, + positive_500: `hsl(${hues.positive}, 82%, ${dimScale[7]}%)`, + positive_600: `hsl(${hues.positive}, 82%, ${dimScale[8]}%)`, + positive_700: `hsl(${hues.positive}, 82%, ${dimScale[9]}%)`, + positive_800: `hsl(${hues.positive}, 82%, ${dimScale[10]}%)`, + positive_900: `hsl(${hues.positive}, 82%, ${dimScale[11]}%)`, + positive_950: `hsl(${hues.positive}, 82%, ${dimScale[12]}%)`, + positive_975: `hsl(${hues.positive}, 82%, ${dimScale[13]}%)`, + + negative_25: `hsl(${hues.negative}, 70%, ${dimScale[1]}%)`, + negative_50: `hsl(${hues.negative}, 80%, ${dimScale[2]}%)`, + negative_100: `hsl(${hues.negative}, 84%, ${dimScale[3]}%)`, + negative_200: `hsl(${hues.negative}, 88%, ${dimScale[4]}%)`, + negative_300: `hsl(${hues.negative}, 91%, ${dimScale[5]}%)`, + negative_400: `hsl(${hues.negative}, 91%, ${dimScale[6]}%)`, + negative_500: `hsl(${hues.negative}, 91%, ${dimScale[7]}%)`, + negative_600: `hsl(${hues.negative}, 91%, ${dimScale[8]}%)`, + negative_700: `hsl(${hues.negative}, 91%, ${dimScale[9]}%)`, + negative_800: `hsl(${hues.negative}, 91%, ${dimScale[10]}%)`, + negative_900: `hsl(${hues.negative}, 91%, ${dimScale[11]}%)`, + negative_950: `hsl(${hues.negative}, 91%, ${dimScale[12]}%)`, + negative_975: `hsl(${hues.negative}, 91%, ${dimScale[13]}%)`, + } as const + + const light: Theme = { + scheme: 'light', + name: 'light', + palette: lightPalette, + atoms: { + text: { + color: lightPalette.black, + }, + text_contrast_low: { + color: lightPalette.contrast_400, + }, + text_contrast_medium: { + color: lightPalette.contrast_700, + }, + text_contrast_high: { + color: lightPalette.contrast_900, + }, + text_inverted: { + color: lightPalette.white, + }, + bg: { + backgroundColor: lightPalette.white, + }, + bg_contrast_25: { + backgroundColor: lightPalette.contrast_25, + }, + bg_contrast_50: { + backgroundColor: lightPalette.contrast_50, + }, + bg_contrast_100: { + backgroundColor: lightPalette.contrast_100, + }, + bg_contrast_200: { + backgroundColor: lightPalette.contrast_200, + }, + bg_contrast_300: { + backgroundColor: lightPalette.contrast_300, + }, + bg_contrast_400: { + backgroundColor: lightPalette.contrast_400, + }, + bg_contrast_500: { + backgroundColor: lightPalette.contrast_500, + }, + bg_contrast_600: { + backgroundColor: lightPalette.contrast_600, + }, + bg_contrast_700: { + backgroundColor: lightPalette.contrast_700, + }, + bg_contrast_800: { + backgroundColor: lightPalette.contrast_800, + }, + bg_contrast_900: { + backgroundColor: lightPalette.contrast_900, + }, + bg_contrast_950: { + backgroundColor: lightPalette.contrast_950, + }, + bg_contrast_975: { + backgroundColor: lightPalette.contrast_975, + }, + border_contrast_low: { + borderColor: lightPalette.contrast_100, + }, + border_contrast_medium: { + borderColor: lightPalette.contrast_200, + }, + border_contrast_high: { + borderColor: lightPalette.contrast_300, + }, + shadow_sm: { + ...atoms.shadow_sm, + shadowColor: lightPalette.black, + }, + shadow_md: { + ...atoms.shadow_md, + shadowColor: lightPalette.black, + }, + shadow_lg: { + ...atoms.shadow_lg, + shadowColor: lightPalette.black, + }, + }, + } + + const dark: Theme = { + scheme: 'dark', + name: 'dark', + palette: darkPalette, + atoms: { + text: { + color: darkPalette.white, + }, + text_contrast_low: { + color: darkPalette.contrast_400, + }, + text_contrast_medium: { + color: darkPalette.contrast_600, + }, + text_contrast_high: { + color: darkPalette.contrast_900, + }, + text_inverted: { + color: darkPalette.black, + }, + bg: { + backgroundColor: darkPalette.black, + }, + bg_contrast_25: { + backgroundColor: darkPalette.contrast_25, + }, + bg_contrast_50: { + backgroundColor: darkPalette.contrast_50, + }, + bg_contrast_100: { + backgroundColor: darkPalette.contrast_100, + }, + bg_contrast_200: { + backgroundColor: darkPalette.contrast_200, + }, + bg_contrast_300: { + backgroundColor: darkPalette.contrast_300, + }, + bg_contrast_400: { + backgroundColor: darkPalette.contrast_400, + }, + bg_contrast_500: { + backgroundColor: darkPalette.contrast_500, + }, + bg_contrast_600: { + backgroundColor: darkPalette.contrast_600, + }, + bg_contrast_700: { + backgroundColor: darkPalette.contrast_700, + }, + bg_contrast_800: { + backgroundColor: darkPalette.contrast_800, + }, + bg_contrast_900: { + backgroundColor: darkPalette.contrast_900, + }, + bg_contrast_950: { + backgroundColor: darkPalette.contrast_950, + }, + bg_contrast_975: { + backgroundColor: darkPalette.contrast_975, + }, + border_contrast_low: { + borderColor: darkPalette.contrast_100, + }, + border_contrast_medium: { + borderColor: darkPalette.contrast_200, + }, + border_contrast_high: { + borderColor: darkPalette.contrast_300, + }, + shadow_sm: { + ...atoms.shadow_sm, + shadowOpacity: 0.7, + shadowColor: color.trueBlack, + }, + shadow_md: { + ...atoms.shadow_md, + shadowOpacity: 0.7, + shadowColor: color.trueBlack, + }, + shadow_lg: { + ...atoms.shadow_lg, + shadowOpacity: 0.7, + shadowColor: color.trueBlack, + }, + }, + } + + const dim: Theme = { + ...dark, + scheme: 'dark', + name: 'dim', + palette: dimPalette, + atoms: { + ...dark.atoms, + text: { + color: dimPalette.white, + }, + text_contrast_low: { + color: dimPalette.contrast_400, + }, + text_contrast_medium: { + color: dimPalette.contrast_600, + }, + text_contrast_high: { + color: dimPalette.contrast_900, + }, + text_inverted: { + color: dimPalette.black, + }, + bg: { + backgroundColor: dimPalette.black, + }, + bg_contrast_25: { + backgroundColor: dimPalette.contrast_25, + }, + bg_contrast_50: { + backgroundColor: dimPalette.contrast_50, + }, + bg_contrast_100: { + backgroundColor: dimPalette.contrast_100, + }, + bg_contrast_200: { + backgroundColor: dimPalette.contrast_200, + }, + bg_contrast_300: { + backgroundColor: dimPalette.contrast_300, + }, + bg_contrast_400: { + backgroundColor: dimPalette.contrast_400, + }, + bg_contrast_500: { + backgroundColor: dimPalette.contrast_500, + }, + bg_contrast_600: { + backgroundColor: dimPalette.contrast_600, + }, + bg_contrast_700: { + backgroundColor: dimPalette.contrast_700, + }, + bg_contrast_800: { + backgroundColor: dimPalette.contrast_800, + }, + bg_contrast_900: { + backgroundColor: dimPalette.contrast_900, + }, + bg_contrast_950: { + backgroundColor: dimPalette.contrast_950, + }, + bg_contrast_975: { + backgroundColor: dimPalette.contrast_975, + }, + border_contrast_low: { + borderColor: dimPalette.contrast_100, + }, + border_contrast_medium: { + borderColor: dimPalette.contrast_200, + }, + border_contrast_high: { + borderColor: dimPalette.contrast_300, + }, + shadow_sm: { + ...atoms.shadow_sm, + shadowOpacity: 0.7, + shadowColor: `hsl(${hues.primary}, 28%, 6%)`, + }, + shadow_md: { + ...atoms.shadow_md, + shadowOpacity: 0.7, + shadowColor: `hsl(${hues.primary}, 28%, 6%)`, + }, + shadow_lg: { + ...atoms.shadow_lg, + shadowOpacity: 0.7, + shadowColor: `hsl(${hues.primary}, 28%, 6%)`, + }, + }, + } + + return { + lightPalette, + darkPalette, + dimPalette, + light, + dark, + dim, + } +} diff --git a/src/alf/tokens.ts b/src/alf/tokens.ts index ac48bc788..74cc160fc 100644 --- a/src/alf/tokens.ts +++ b/src/alf/tokens.ts @@ -1,10 +1,61 @@ -import {tokens} from '@bsky.app/alf' +import {isAndroid} from '#/platform/detection' -export * from '@bsky.app/alf/dist/tokens' +export const TRACKING = isAndroid ? 0.1 : 0 export const color = { - temp_purple: tokens.labelerColor.purple, - temp_purple_dark: tokens.labelerColor.purple_dark, + temp_purple: 'rgb(105 0 255)', + temp_purple_dark: 'rgb(83 0 202)', +} as const + +export const space = { + _2xs: 2, + xs: 4, + sm: 8, + md: 12, + lg: 16, + xl: 20, + _2xl: 24, + _3xl: 28, + _4xl: 32, + _5xl: 40, +} as const + +export const fontSize = { + _2xs: 10, + xs: 12, + sm: 14, + md: 16, + lg: 18, + xl: 20, + _2xl: 22, + _3xl: 26, + _4xl: 32, + _5xl: 40, +} as const + +export const lineHeight = { + none: 1, + normal: 1.5, + relaxed: 1.625, +} as const + +export const borderRadius = { + _2xs: 2, + xs: 4, + sm: 8, + md: 12, + lg: 16, + full: 999, +} as const + +/** + * These correspond to Inter font files we actually load. + */ +export const fontWeight = { + normal: '400', + medium: '500', + bold: '600', + heavy: '800', } as const export const gradients = { diff --git a/src/alf/typography.tsx b/src/alf/typography.tsx index 3c3bb9548..c229ab443 100644 --- a/src/alf/typography.tsx +++ b/src/alf/typography.tsx @@ -8,6 +8,21 @@ import {isNative} from '#/platform/detection' import {isIOS} from '#/platform/detection' import {type Alf, applyFonts, atoms, flatten} from '#/alf' +/** + * Util to calculate lineHeight from a text size atom and a leading atom + * + * Example: + * `leading(atoms.text_md, atoms.leading_normal)` // => 24 + */ +export function leading< + Size extends {fontSize?: number}, + Leading extends {lineHeight?: number}, +>(textSize: Size, leading: Leading) { + const size = textSize?.fontSize || atoms.text_md.fontSize + const lineHeight = leading?.lineHeight || atoms.leading_normal.lineHeight + return Math.round(size * lineHeight) +} + /** * Ensures that `lineHeight` defaults to a relative value of `1`, or applies * other relative leading atoms. diff --git a/src/alf/util/__tests__/colors.test.ts b/src/alf/util/__tests__/colors.test.ts index 1ecb7394b..350b6ff4a 100644 --- a/src/alf/util/__tests__/colors.test.ts +++ b/src/alf/util/__tests__/colors.test.ts @@ -1,7 +1,12 @@ import {jest} from '@jest/globals' +import {logger} from '#/logger' import {transparentifyColor} from '../colorGeneration' +jest.mock('#/logger', () => ({ + logger: {warn: jest.fn()}, +})) + describe('transparentifyColor', () => { beforeEach(() => { jest.clearAllMocks() @@ -36,5 +41,8 @@ describe('transparentifyColor', () => { const unsupported = 'blue' const result = transparentifyColor(unsupported, 0.5) expect(result).toBe(unsupported) + expect(logger.warn).toHaveBeenCalledWith( + `Could not make '${unsupported}' transparent`, + ) }) }) diff --git a/src/alf/util/platform.ts b/src/alf/util/platform.ts index 2f66c76c1..947f2bd16 100644 --- a/src/alf/util/platform.ts +++ b/src/alf/util/platform.ts @@ -1 +1,62 @@ -export {android, ios, native, platform, web} from '@bsky.app/alf' +import {Platform} from 'react-native' + +import {isAndroid, isIOS, isNative, isWeb} from '#/platform/detection' + +/** + * Identity function on web. Returns nothing on other platforms. + * + * Note: Platform splitting does not tree-shake away the other platforms, + * so don't do stuff like e.g. rely on platform-specific imports. Use + * platform-split files instead. + */ +export function web(value: any) { + if (isWeb) { + return value + } +} + +/** + * Identity function on iOS. Returns nothing on other platforms. + * + * Note: Platform splitting does not tree-shake away the other platforms, + * so don't do stuff like e.g. rely on platform-specific imports. Use + * platform-split files instead. + */ +export function ios(value: any) { + if (isIOS) { + return value + } +} + +/** + * Identity function on Android. Returns nothing on other platforms.. + * + * Note: Platform splitting does not tree-shake away the other platforms, + * so don't do stuff like e.g. rely on platform-specific imports. Use + * platform-split files instead. + */ +export function android(value: any) { + if (isAndroid) { + return value + } +} + +/** + * Identity function on iOS and Android. Returns nothing on web. + * + * Note: Platform splitting does not tree-shake away the other platforms, + * so don't do stuff like e.g. rely on platform-specific imports. Use + * platform-split files instead. + */ +export function native(value: any) { + if (isNative) { + return value + } +} + +/** + * Note: Platform splitting does not tree-shake away the other platforms, + * so don't do stuff like e.g. rely on platform-specific imports. Use + * platform-split files instead. + */ +export const platform = Platform.select diff --git a/src/alf/util/systemUI.ts b/src/alf/util/systemUI.ts index 02b5363ff..9e5769c4c 100644 --- a/src/alf/util/systemUI.ts +++ b/src/alf/util/systemUI.ts @@ -1,7 +1,7 @@ import * as SystemUI from 'expo-system-ui' -import {type Theme} from '@bsky.app/alf' import {isAndroid} from '#/platform/detection' +import {type Theme} from '../types' export function setSystemUITheme(themeType: 'theme' | 'lightbox', t: Theme) { if (isAndroid) { diff --git a/src/alf/util/themeSelector.ts b/src/alf/util/themeSelector.ts index b0827342a..c118b6506 100644 --- a/src/alf/util/themeSelector.ts +++ b/src/alf/util/themeSelector.ts @@ -1,3 +1,14 @@ -import {utils} from '@bsky.app/alf' +import {type ThemeName} from '#/alf/types' -export const select = utils.select +export function select(name: ThemeName, options: Record) { + switch (name) { + case 'light': + return options.light + case 'dark': + return options.dark || options.dim + case 'dim': + return options.dim || options.dark + default: + throw new Error(`select(theme, options) received unknown theme ${name}`) + } +} diff --git a/src/alf/util/useColorModeTheme.ts b/src/alf/util/useColorModeTheme.ts index 45bd137ee..f05205314 100644 --- a/src/alf/util/useColorModeTheme.ts +++ b/src/alf/util/useColorModeTheme.ts @@ -1,10 +1,10 @@ import React from 'react' import {type ColorSchemeName, useColorScheme} from 'react-native' -import {type ThemeName} from '@bsky.app/alf' import {isWeb} from '#/platform/detection' import {useThemePrefs} from '#/state/shell' import {dark, dim, light} from '#/alf/themes' +import {type ThemeName} from '#/alf/types' export function useColorModeTheme(): ThemeName { const theme = useThemeName() diff --git a/src/components/AccountList.tsx b/src/components/AccountList.tsx index e3b2b7d12..eb770eeca 100644 --- a/src/components/AccountList.tsx +++ b/src/components/AccountList.tsx @@ -77,7 +77,7 @@ export function AccountList({ ]}> {sanitizeDisplayName( profile?.displayName || profile?.handle || account.handle, diff --git a/src/components/BlockedGeoOverlay.tsx b/src/components/BlockedGeoOverlay.tsx index d6e262687..8dd55c2bf 100644 --- a/src/components/BlockedGeoOverlay.tsx +++ b/src/components/BlockedGeoOverlay.tsx @@ -96,7 +96,7 @@ export function BlockedGeoOverlay() { - + Not in Mississippi? ( } } else if (color === 'secondary') { if (!disabled) { - baseStyles.push(t.atoms.bg_contrast_50) + baseStyles.push(t.atoms.bg_contrast_25) hoverStyles.push(t.atoms.bg_contrast_100) } else { baseStyles.push(t.atoms.bg_contrast_50) @@ -289,7 +289,11 @@ export const Button = React.forwardRef( }) } else { baseStyles.push({ - backgroundColor: t.palette.primary_50, + backgroundColor: select(t.name, { + light: t.palette.primary_25, + dim: t.palette.primary_50, + dark: t.palette.primary_50, + }), }) } } else if (color === 'negative_subtle') { @@ -310,7 +314,11 @@ export const Button = React.forwardRef( }) } else { baseStyles.push({ - backgroundColor: t.palette.negative_50, + backgroundColor: select(t.name, { + light: t.palette.negative_25, + dim: t.palette.negative_50, + dark: t.palette.negative_50, + }), }) } } @@ -364,7 +372,7 @@ export const Button = React.forwardRef( if (!disabled) { baseStyles.push(t.atoms.bg) hoverStyles.push({ - backgroundColor: t.palette.contrast_50, + backgroundColor: t.palette.contrast_25, }) } } @@ -388,7 +396,7 @@ export const Button = React.forwardRef( if (!disabled) { baseStyles.push(t.atoms.bg) hoverStyles.push({ - backgroundColor: t.palette.contrast_50, + backgroundColor: t.palette.contrast_25, }) } } diff --git a/src/components/ContextMenu/index.tsx b/src/components/ContextMenu/index.tsx index 7d078bb2d..9d7189473 100644 --- a/src/components/ContextMenu/index.tsx +++ b/src/components/ContextMenu/index.tsx @@ -796,7 +796,7 @@ export function ItemText({children, style}: ItemTextProps) { style={[ a.flex_1, a.text_md, - a.font_semi_bold, + a.font_bold, t.atoms.text_contrast_high, {paddingTop: 3}, style, @@ -855,11 +855,7 @@ export function LabelText({children}: {children: React.ReactNode}) { const t = useTheme() return ( + style={[a.font_bold, t.atoms.text_contrast_medium, {marginBottom: -8}]}> {children} ) diff --git a/src/components/Dialog/shared.tsx b/src/components/Dialog/shared.tsx index e9fdf50fa..b5513b19c 100644 --- a/src/components/Dialog/shared.tsx +++ b/src/components/Dialog/shared.tsx @@ -62,7 +62,7 @@ export function HeaderText({ style?: StyleProp }) { return ( - + {children} ) diff --git a/src/components/Error.tsx b/src/components/Error.tsx index 92b8b2e7c..dc8e53b46 100644 --- a/src/components/Error.tsx +++ b/src/components/Error.tsx @@ -40,7 +40,7 @@ export function Error({ ]} sideBorders={sideBorders}> - {title} + {title} {title} @@ -214,7 +214,7 @@ export function DescriptionPlaceholder() { export function Likes({count}: {count: number}) { const t = useTheme() return ( - + Liked by diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx index 5a65215b1..6278449a0 100644 --- a/src/components/FeedInterstitials.tsx +++ b/src/components/FeedInterstitials.tsx @@ -380,7 +380,7 @@ export function ProfileGrid({ a.justify_between, ]} pointerEvents={isIOS ? 'auto' : 'box-none'}> - + {isFeedContext ? ( Suggested for you ) : ( @@ -516,7 +516,7 @@ export function SuggestedFeeds() { style={[ a.flex_1, a.text_lg, - a.font_semi_bold, + a.font_bold, t.atoms.text_contrast_medium, ]}> Some other feeds you might like diff --git a/src/components/LabelingServiceCard/index.tsx b/src/components/LabelingServiceCard/index.tsx index ecb47a758..990dbb1c6 100644 --- a/src/components/LabelingServiceCard/index.tsx +++ b/src/components/LabelingServiceCard/index.tsx @@ -45,7 +45,7 @@ export function Avatar({avatar}: {avatar?: string}) { export function Title({value}: {value: string}) { return ( - + {value} ) diff --git a/src/components/Layout/Header/index.tsx b/src/components/Layout/Header/index.tsx index 596540a23..1a049a696 100644 --- a/src/components/Layout/Header/index.tsx +++ b/src/components/Layout/Header/index.tsx @@ -181,7 +181,7 @@ export function TitleText({ Hidden list @@ -135,7 +135,7 @@ export function TitleAndByline({ {title} diff --git a/src/components/LoggedOutCTA.tsx b/src/components/LoggedOutCTA.tsx index de0e23dc9..0bafbd45f 100644 --- a/src/components/LoggedOutCTA.tsx +++ b/src/components/LoggedOutCTA.tsx @@ -50,7 +50,7 @@ export function LoggedOutCTA({style, gateName}: LoggedOutCTAProps) { - + Join Bluesky - + {isMe ? Welcome, friend! : Say hello!} diff --git a/src/components/Pills.tsx b/src/components/Pills.tsx index 4469c83bd..550089a80 100644 --- a/src/components/Pills.tsx +++ b/src/components/Pills.tsx @@ -133,7 +133,7 @@ export function Label({ emoji style={[ text, - a.font_semi_bold, + a.font_bold, a.leading_tight, t.atoms.text_contrast_medium, {paddingRight: 3}, diff --git a/src/components/PolicyUpdateOverlay/Badge.tsx b/src/components/PolicyUpdateOverlay/Badge.tsx index b3bb8b77b..3829f60a5 100644 --- a/src/components/PolicyUpdateOverlay/Badge.tsx +++ b/src/components/PolicyUpdateOverlay/Badge.tsx @@ -25,7 +25,7 @@ export function Badge() { - + Hey there 👋 @@ -115,7 +115,7 @@ export function Content({state}: {state: PolicyUpdateState}) { ) : ( - + Hey there 👋 diff --git a/src/components/Post/Embed/ExternalEmbed/index.tsx b/src/components/Post/Embed/ExternalEmbed/index.tsx index 7911df726..714eaecd6 100644 --- a/src/components/Post/Embed/ExternalEmbed/index.tsx +++ b/src/components/Post/Embed/ExternalEmbed/index.tsx @@ -126,7 +126,7 @@ export const ExternalEmbed = ({ + style={[a.text_md, a.font_bold, a.leading_snug]}> {link.title || link.uri} )} diff --git a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/TimeIndicator.tsx b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/TimeIndicator.tsx index 01828011b..67af7618c 100644 --- a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/TimeIndicator.tsx +++ b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/TimeIndicator.tsx @@ -54,7 +54,7 @@ export function TimeIndicator({ {`${minutes}:${seconds}`} diff --git a/src/components/PostControls/PostControlButton.tsx b/src/components/PostControls/PostControlButton.tsx index 9a24eb917..f7070c4c8 100644 --- a/src/components/PostControls/PostControlButton.tsx +++ b/src/components/PostControls/PostControlButton.tsx @@ -128,12 +128,7 @@ export function PostControlButtonText({style, ...props}: TextProps) { return ( ) diff --git a/src/components/PostControls/RepostButton.tsx b/src/components/PostControls/RepostButton.tsx index f34e37c29..d4a3960a7 100644 --- a/src/components/PostControls/RepostButton.tsx +++ b/src/components/PostControls/RepostButton.tsx @@ -157,7 +157,7 @@ let RepostButtonDialogInner = ({ variant="ghost" color="primary"> - + {isReposted ? ( Remove repost ) : ( @@ -188,7 +188,7 @@ let RepostButtonDialogInner = ({ /> diff --git a/src/components/PostControls/ShareMenu/RecentChats.tsx b/src/components/PostControls/ShareMenu/RecentChats.tsx index 28724061f..4b94e0df9 100644 --- a/src/components/PostControls/ShareMenu/RecentChats.tsx +++ b/src/components/PostControls/ShareMenu/RecentChats.tsx @@ -203,7 +203,7 @@ function NoConvos() { a.text_sm, t.atoms.text_contrast_high, a.text_center, - a.font_semi_bold, + a.font_bold, ]}> Start a conversation, and it will appear here. diff --git a/src/components/ProfileCard.tsx b/src/components/ProfileCard.tsx index 70323f9fc..095b62167 100644 --- a/src/components/ProfileCard.tsx +++ b/src/components/ProfileCard.tsx @@ -233,7 +233,7 @@ function InlineNameAndHandle({ + style={[a.text_lg, a.font_bold, a.self_start]}> {sanitizeDisplayName( profile.displayName || sanitizeHandle(profile.handle), moderation.ui('displayName'), @@ -562,7 +562,7 @@ function Inner({ label={`${followers} ${pluralizedFollowers}`} style={[t.atoms.text]} onPress={hide}> - {followers} + {followers} {pluralizedFollowers} @@ -572,7 +572,7 @@ function Inner({ label={_(msg`${following} following`)} style={[t.atoms.text]} onPress={hide}> - {following} + {following} {pluralizedFollowings} diff --git a/src/components/ProgressGuide/FollowDialog.tsx b/src/components/ProgressGuide/FollowDialog.tsx index 3dd308e83..c4a5f0fa0 100644 --- a/src/components/ProgressGuide/FollowDialog.tsx +++ b/src/components/ProgressGuide/FollowDialog.tsx @@ -360,7 +360,7 @@ function HeaderTop({guide}: {guide: Follow10ProgressGuide}) { style={[ a.z_10, a.text_lg, - a.font_bold, + a.font_heavy, a.leading_tight, t.atoms.text_contrast_high, ]}> diff --git a/src/components/ProgressGuide/List.tsx b/src/components/ProgressGuide/List.tsx index cae307a6d..52fc4c27a 100644 --- a/src/components/ProgressGuide/List.tsx +++ b/src/components/ProgressGuide/List.tsx @@ -28,7 +28,7 @@ export function ProgressGuideList({style}: {style?: StyleProp}) { diff --git a/src/components/ProgressGuide/Task.tsx b/src/components/ProgressGuide/Task.tsx index 449a28fcd..b9ba3fd9a 100644 --- a/src/components/ProgressGuide/Task.tsx +++ b/src/components/ProgressGuide/Task.tsx @@ -39,7 +39,7 @@ export function ProgressGuideTask({ diff --git a/src/components/ProgressGuide/Toast.tsx b/src/components/ProgressGuide/Toast.tsx index ad0feff2e..d4ac771b2 100644 --- a/src/components/ProgressGuide/Toast.tsx +++ b/src/components/ProgressGuide/Toast.tsx @@ -160,7 +160,7 @@ export const ProgressGuideToast = React.forwardRef< ref={animatedCheckRef} /> - {title} + {title} {subtitle && ( {subtitle} diff --git a/src/components/Prompt.tsx b/src/components/Prompt.tsx index a7bd89521..626d8316d 100644 --- a/src/components/Prompt.tsx +++ b/src/components/Prompt.tsx @@ -77,7 +77,7 @@ export function TitleText({ style={[ a.flex_1, a.text_2xl, - a.font_semi_bold, + a.font_bold, a.pb_sm, a.leading_snug, style, diff --git a/src/components/ReportDialog/SelectLabelerView.tsx b/src/components/ReportDialog/SelectLabelerView.tsx index 02b324442..be666ced1 100644 --- a/src/components/ReportDialog/SelectLabelerView.tsx +++ b/src/components/ReportDialog/SelectLabelerView.tsx @@ -24,7 +24,7 @@ export function SelectLabelerView({ return ( - + Select moderator @@ -75,8 +75,7 @@ function LabelerButton({ handle: labeler.creator.handle, })} /> - + @{labeler.creator.handle} diff --git a/src/components/ReportDialog/SelectReportOptionView.tsx b/src/components/ReportDialog/SelectReportOptionView.tsx index 0fd321cdf..f5165f8f7 100644 --- a/src/components/ReportDialog/SelectReportOptionView.tsx +++ b/src/components/ReportDialog/SelectReportOptionView.tsx @@ -85,7 +85,7 @@ export function SelectReportOptionView(props: { ) : null} - {i18n.title} + {i18n.title} {i18n.description} @@ -173,8 +173,7 @@ function ReportOptionButton({ interacted && t.atoms.bg_contrast_50, ]}> - + {title} {description} diff --git a/src/components/ReportDialog/SubmitView.tsx b/src/components/ReportDialog/SubmitView.tsx index 3dbb1389d..418f364a7 100644 --- a/src/components/ReportDialog/SubmitView.tsx +++ b/src/components/ReportDialog/SubmitView.tsx @@ -125,7 +125,7 @@ export function SubmitView({ t.atoms.border_contrast_low, ]}> - + {selectedReportOption.title} diff --git a/src/components/SearchError.tsx b/src/components/SearchError.tsx index 07a6ca1b2..633710e34 100644 --- a/src/components/SearchError.tsx +++ b/src/components/SearchError.tsx @@ -36,13 +36,7 @@ export function SearchError({ {maxWidth: gtMobile ? 394 : 294}, gtMobile ? a.gap_md : a.gap_sm, ]}> - + {title} {children} diff --git a/src/components/Select/index.tsx b/src/components/Select/index.tsx index 33a828911..82520f12a 100644 --- a/src/components/Select/index.tsx +++ b/src/components/Select/index.tsx @@ -280,7 +280,7 @@ export function ItemText({children}: ItemTextProps) { // eslint-disable-next-line bsky-internal/avoid-unwrapped-text return ( - {children} + {children} ) } diff --git a/src/components/Select/index.web.tsx b/src/components/Select/index.web.tsx index f53749ef0..4e92d3c51 100644 --- a/src/components/Select/index.web.tsx +++ b/src/components/Select/index.web.tsx @@ -259,7 +259,7 @@ export function Item({ref, value, style, children}: ItemProps) { a.text_sm, {outline: 0}, (hovered || focused) && {backgroundColor: t.palette.primary_50}, - selected && [a.font_semi_bold], + selected && [a.font_bold], a.transition_color, style, ])}> diff --git a/src/components/StarterPack/ProfileStarterPacks.tsx b/src/components/StarterPack/ProfileStarterPacks.tsx index ecb5357e0..7252a1162 100644 --- a/src/components/StarterPack/ProfileStarterPacks.tsx +++ b/src/components/StarterPack/ProfileStarterPacks.tsx @@ -255,7 +255,7 @@ function Empty() { {marginTop: a.border.borderWidth}, ]}> - + You haven't created a starter pack yet! diff --git a/src/components/StarterPack/QrCode.tsx b/src/components/StarterPack/QrCode.tsx index 64c5cf50f..4c28a41c5 100644 --- a/src/components/StarterPack/QrCode.tsx +++ b/src/components/StarterPack/QrCode.tsx @@ -54,19 +54,14 @@ export function QrCode({ ]}> + style={[a.font_bold, a.text_3xl, a.text_center, {color: 'white'}]}> {record.name} @@ -81,7 +76,7 @@ export function QrCode({ a.flex, a.flex_row, a.align_center, - a.font_semi_bold, + a.font_bold, {color: 'white', fontSize: 18, gap: 6}, ]}> diff --git a/src/components/StarterPack/ShareDialog.tsx b/src/components/StarterPack/ShareDialog.tsx index 6c282f117..32932fe2d 100644 --- a/src/components/StarterPack/ShareDialog.tsx +++ b/src/components/StarterPack/ShareDialog.tsx @@ -77,7 +77,7 @@ function ShareDialogInner({ ) : ( - + Invite people to this starter pack! diff --git a/src/components/StarterPack/StarterPackCard.tsx b/src/components/StarterPack/StarterPackCard.tsx index e58c2ed27..d889b2e72 100644 --- a/src/components/StarterPack/StarterPackCard.tsx +++ b/src/components/StarterPack/StarterPackCard.tsx @@ -77,7 +77,7 @@ export function Card({ {record.name} @@ -97,7 +97,7 @@ export function Card({ ) : null} {!!joinedAllTimeCount && joinedAllTimeCount >= 50 && ( - + joined! diff --git a/src/components/StarterPack/Wizard/WizardEditListDialog.tsx b/src/components/StarterPack/Wizard/WizardEditListDialog.tsx index b1103bb4c..7dfde900f 100644 --- a/src/components/StarterPack/Wizard/WizardEditListDialog.tsx +++ b/src/components/StarterPack/Wizard/WizardEditListDialog.tsx @@ -105,7 +105,7 @@ export function WizardEditListDialog({ : [a.pb_sm, a.align_end], ]}> - + {state.currentStep === 'Profiles' ? ( Edit People ) : ( diff --git a/src/components/StarterPack/Wizard/WizardListCard.tsx b/src/components/StarterPack/Wizard/WizardListCard.tsx index 4b7431157..09c265d78 100644 --- a/src/components/StarterPack/Wizard/WizardListCard.tsx +++ b/src/components/StarterPack/Wizard/WizardListCard.tsx @@ -83,7 +83,7 @@ function WizardListCard({ emoji style={[ a.flex_1, - a.font_semi_bold, + a.font_bold, a.text_md, a.leading_tight, a.self_start, diff --git a/src/components/SubtleWebHover.web.tsx b/src/components/SubtleWebHover.web.tsx index 8e7b48f93..af00cf43a 100644 --- a/src/components/SubtleWebHover.web.tsx +++ b/src/components/SubtleWebHover.web.tsx @@ -11,7 +11,7 @@ export function SubtleWebHover({ if (isTouchDevice) { return null } - let opacity = 0.5 + let opacity: number switch (t.name) { case 'dark': opacity = 0.4 diff --git a/src/components/TrendingTopics.tsx b/src/components/TrendingTopics.tsx index b2ee8140e..50e0fc5ed 100644 --- a/src/components/TrendingTopics.tsx +++ b/src/components/TrendingTopics.tsx @@ -90,7 +90,7 @@ export function TrendingTopic({ 0 && ( - + {formatCount(i18n, likeCount)} @@ -236,8 +235,7 @@ export function VideoPostCard({ {repostCount > 0 && ( - + {formatCount(i18n, repostCount)} @@ -522,11 +520,7 @@ export function CompactVideoPostCard({ + style={[a.text_sm, a.font_bold, {color: 'white'}]}> {formatCount(i18n, likeCount)} diff --git a/src/components/WelcomeModal.tsx b/src/components/WelcomeModal.tsx index 1271a5f3a..7c9ecd84d 100644 --- a/src/components/WelcomeModal.tsx +++ b/src/components/WelcomeModal.tsx @@ -108,7 +108,7 @@ export function WelcomeModal({control}: WelcomeModalProps) { @@ -127,7 +127,7 @@ export function WelcomeModal({control}: WelcomeModalProps) { - + Who can interact with this post? - + Keep me posted diff --git a/src/components/ageAssurance/AgeAssuranceAdmonition.tsx b/src/components/ageAssurance/AgeAssuranceAdmonition.tsx index 028e1dad5..e53c37b34 100644 --- a/src/components/ageAssurance/AgeAssuranceAdmonition.tsx +++ b/src/components/ageAssurance/AgeAssuranceAdmonition.tsx @@ -82,13 +82,13 @@ function Inner({ {children} - + Learn more in your{' '} { logger.metric('ageAssurance:navigateToSettings', {}) }}> diff --git a/src/components/ageAssurance/AgeAssuranceAppealDialog.tsx b/src/components/ageAssurance/AgeAssuranceAppealDialog.tsx index a63c348fb..b9dcff706 100644 --- a/src/components/ageAssurance/AgeAssuranceAppealDialog.tsx +++ b/src/components/ageAssurance/AgeAssuranceAppealDialog.tsx @@ -89,7 +89,7 @@ function Inner({control}: {control: Dialog.DialogControlProps}) { - + Contact us diff --git a/src/components/ageAssurance/AgeAssuranceBadge.tsx b/src/components/ageAssurance/AgeAssuranceBadge.tsx index f8b5ee9b2..030e30529 100644 --- a/src/components/ageAssurance/AgeAssuranceBadge.tsx +++ b/src/components/ageAssurance/AgeAssuranceBadge.tsx @@ -29,7 +29,7 @@ export function AgeAssuranceBadge() { - + {success ? Success! : Verify your age} diff --git a/src/components/ageAssurance/AgeAssuranceRedirectDialog.tsx b/src/components/ageAssurance/AgeAssuranceRedirectDialog.tsx index c45bc3a2c..b1c287e1b 100644 --- a/src/components/ageAssurance/AgeAssuranceRedirectDialog.tsx +++ b/src/components/ageAssurance/AgeAssuranceRedirectDialog.tsx @@ -160,7 +160,7 @@ export function Inner({}: {optimisticState?: AgeAssuranceRedirectDialogState}) { a.pb_md, ]}> - + Success @@ -209,7 +209,7 @@ export function Inner({}: {optimisticState?: AgeAssuranceRedirectDialogState}) { ]}> {error && } - + {error ? Connection issue : Verifying} diff --git a/src/components/ageAssurance/AgeRestrictedScreen.tsx b/src/components/ageAssurance/AgeRestrictedScreen.tsx index b6a8c26a3..1430aaaff 100644 --- a/src/components/ageAssurance/AgeRestrictedScreen.tsx +++ b/src/components/ageAssurance/AgeRestrictedScreen.tsx @@ -62,7 +62,7 @@ export function AgeRestrictedScreen({ - + You must complete age assurance in order to access this screen. diff --git a/src/components/dialogs/BirthDateSettings.tsx b/src/components/dialogs/BirthDateSettings.tsx index e1c73b67c..0b8dfb540 100644 --- a/src/components/dialogs/BirthDateSettings.tsx +++ b/src/components/dialogs/BirthDateSettings.tsx @@ -38,7 +38,7 @@ export function BirthDateSettingsDialog({ label={_(msg`My Birthday`)} style={web({maxWidth: 400})}> - + My Birthday diff --git a/src/components/dialogs/DeviceLocationRequestDialog.tsx b/src/components/dialogs/DeviceLocationRequestDialog.tsx index b6547d4f0..ac3362406 100644 --- a/src/components/dialogs/DeviceLocationRequestDialog.tsx +++ b/src/components/dialogs/DeviceLocationRequestDialog.tsx @@ -108,7 +108,7 @@ function DeviceLocationRequestDialogInner({onLocationAcquired}: Props) { return ( - + Confirm your location diff --git a/src/components/dialogs/EmailDialog/screens/Manage2FA/Disable.tsx b/src/components/dialogs/EmailDialog/screens/Manage2FA/Disable.tsx index d10d5cab7..2b0e86c61 100644 --- a/src/components/dialogs/EmailDialog/screens/Manage2FA/Disable.tsx +++ b/src/components/dialogs/EmailDialog/screens/Manage2FA/Disable.tsx @@ -153,7 +153,7 @@ export function Disable() { return ( - + Disable email 2FA @@ -163,7 +163,7 @@ export function Disable() { style={[a.text_sm, a.leading_snug, t.atoms.text_contrast_medium]}> To disable your email 2FA method, please verify your access to{' '} - {currentAccount?.email} + {currentAccount?.email} @@ -214,7 +214,7 @@ export function Disable() { style={[a.text_sm, a.leading_snug, t.atoms.text_contrast_medium]}> To disable your email 2FA method, please verify your access to{' '} - {currentAccount?.email} + {currentAccount?.email} diff --git a/src/components/dialogs/EmailDialog/screens/Manage2FA/Enable.tsx b/src/components/dialogs/EmailDialog/screens/Manage2FA/Enable.tsx index 4a3f438df..bf893701c 100644 --- a/src/components/dialogs/EmailDialog/screens/Manage2FA/Enable.tsx +++ b/src/components/dialogs/EmailDialog/screens/Manage2FA/Enable.tsx @@ -88,7 +88,7 @@ export function Enable() { return ( - + Enable email 2FA diff --git a/src/components/dialogs/EmailDialog/screens/Update.tsx b/src/components/dialogs/EmailDialog/screens/Update.tsx index a0ec69c85..be0af8807 100644 --- a/src/components/dialogs/EmailDialog/screens/Update.tsx +++ b/src/components/dialogs/EmailDialog/screens/Update.tsx @@ -199,7 +199,7 @@ export function Update(_props: ScreenProps) { return ( - + Update your email @@ -239,7 +239,7 @@ export function Update(_props: ScreenProps) { <> - + Security step required ) { - + Success! diff --git a/src/components/dialogs/EmailDialog/screens/VerificationReminder.tsx b/src/components/dialogs/EmailDialog/screens/VerificationReminder.tsx index 77ee6ae09..d6c946956 100644 --- a/src/components/dialogs/EmailDialog/screens/VerificationReminder.tsx +++ b/src/components/dialogs/EmailDialog/screens/VerificationReminder.tsx @@ -58,7 +58,7 @@ export function VerificationReminder({ - + Please verify your email diff --git a/src/components/dialogs/EmailDialog/screens/Verify.tsx b/src/components/dialogs/EmailDialog/screens/Verify.tsx index 74ff9c96b..07aef6145 100644 --- a/src/components/dialogs/EmailDialog/screens/Verify.tsx +++ b/src/components/dialogs/EmailDialog/screens/Verify.tsx @@ -174,7 +174,7 @@ export function Verify({config, showScreen}: ScreenProps) { return ( - + @@ -197,7 +197,7 @@ export function Verify({config, showScreen}: ScreenProps) { return ( - + {state.step === 'email' ? ( state.mutationStatus === 'success' ? ( <> @@ -239,7 +239,7 @@ export function Verify({config, showScreen}: ScreenProps) { state.mutationStatus === 'success' ? ( We sent an email to{' '} - + {currentAccount!.email} {' '} containing a link. Please click on it to complete the email @@ -248,7 +248,7 @@ export function Verify({config, showScreen}: ScreenProps) { ) : ( We'll send an email to{' '} - + {currentAccount!.email} {' '} containing a link. Please click on it to complete the email @@ -258,7 +258,7 @@ export function Verify({config, showScreen}: ScreenProps) { ) : ( Please enter the code we sent to{' '} - + {currentAccount!.email} {' '} below. diff --git a/src/components/dialogs/Embed.tsx b/src/components/dialogs/Embed.tsx index a61004fd2..594800c82 100644 --- a/src/components/dialogs/Embed.tsx +++ b/src/components/dialogs/Embed.tsx @@ -104,7 +104,7 @@ function EmbedDialogInner({ - + Embed post - + Color theme - + External Media diff --git a/src/components/dialogs/InAppBrowserConsent.tsx b/src/components/dialogs/InAppBrowserConsent.tsx index 5ac3ad916..4459c64db 100644 --- a/src/components/dialogs/InAppBrowserConsent.tsx +++ b/src/components/dialogs/InAppBrowserConsent.tsx @@ -62,7 +62,7 @@ function InAppBrowserConsentInner({href}: {href?: string}) { - + How should we open this link? diff --git a/src/components/dialogs/LinkWarning.tsx b/src/components/dialogs/LinkWarning.tsx index 74be78f9d..9ae871812 100644 --- a/src/components/dialogs/LinkWarning.tsx +++ b/src/components/dialogs/LinkWarning.tsx @@ -68,7 +68,7 @@ function InAppBrowserConsentInner({ }> - + {potentiallyMisleading ? ( Potentially misleading link ) : ( @@ -151,8 +151,7 @@ function LinkBox({href}: {href: string}) { ]}> {scheme} - + {hostname} {rest} diff --git a/src/components/dialogs/MutedWords.tsx b/src/components/dialogs/MutedWords.tsx index dc9158ede..e289e1641 100644 --- a/src/components/dialogs/MutedWords.tsx +++ b/src/components/dialogs/MutedWords.tsx @@ -108,12 +108,7 @@ function MutedWordsInner() { + style={[a.text_md, a.font_bold, a.pb_sm, t.atoms.text_contrast_high]}> Add muted words and tags @@ -152,7 +147,7 @@ function MutedWordsInner() { style={[ a.pb_xs, a.text_sm, - a.font_semi_bold, + a.font_bold, t.atoms.text_contrast_medium, ]}> Duration: @@ -252,7 +247,7 @@ function MutedWordsInner() { style={[ a.pb_xs, a.text_sm, - a.font_semi_bold, + a.font_bold, t.atoms.text_contrast_medium, ]}> Mute in: @@ -298,7 +293,7 @@ function MutedWordsInner() { style={[ a.pb_xs, a.text_sm, - a.font_semi_bold, + a.font_bold, t.atoms.text_contrast_medium, ]}> Options: @@ -367,7 +362,7 @@ function MutedWordsInner() { @@ -460,7 +455,7 @@ function MutedWordRow({ style={[ a.flex_1, a.leading_snug, - a.font_semi_bold, + a.font_bold, web({ overflowWrap: 'break-word', wordBreak: 'break-word', @@ -471,8 +466,7 @@ function MutedWordRow({ {word.value}{' '} in{' '} - + text & tags @@ -482,8 +476,7 @@ function MutedWordRow({ {word.value}{' '} in{' '} - + tags diff --git a/src/components/dialogs/PostInteractionSettingsDialog.tsx b/src/components/dialogs/PostInteractionSettingsDialog.tsx index 01194ef65..dbb966fd3 100644 --- a/src/components/dialogs/PostInteractionSettingsDialog.tsx +++ b/src/components/dialogs/PostInteractionSettingsDialog.tsx @@ -84,7 +84,7 @@ export function PostInteractionSettingsControlledDialog({ ]}> You can set default interaction settings in{' '} - + Settings → Moderation → Interaction settings . @@ -100,7 +100,7 @@ export function PostInteractionSettingsControlledDialog({ export function Header() { return ( - + Post interaction settings @@ -329,7 +329,7 @@ export function PostInteractionSettingsForm({ - + Quote settings @@ -385,7 +385,7 @@ export function PostInteractionSettingsForm({ opacity: replySettingsDisabled ? 0.3 : 1, }, ]}> - + Reply settings @@ -535,9 +535,7 @@ function Selectable({ }, style, ]}> - - {label} - + {label} {isSelected ? ( ) : ( diff --git a/src/components/dialogs/SearchablePeopleList.tsx b/src/components/dialogs/SearchablePeopleList.tsx index 41b31b255..4259f3760 100644 --- a/src/components/dialogs/SearchablePeopleList.tsx +++ b/src/components/dialogs/SearchablePeopleList.tsx @@ -284,7 +284,7 @@ export function SearchablePeopleList({ style={[ a.z_10, a.text_lg, - a.font_bold, + a.font_heavy, a.leading_tight, t.atoms.text_contrast_high, ]}> diff --git a/src/components/dialogs/StarterPackDialog.tsx b/src/components/dialogs/StarterPackDialog.tsx index 13b04e201..6a502072c 100644 --- a/src/components/dialogs/StarterPackDialog.tsx +++ b/src/components/dialogs/StarterPackDialog.tsx @@ -172,7 +172,7 @@ function StarterPackList({ isWeb ? a.mb_2xl : a.my_lg, a.align_center, ]}> - + Add to starter packs - {copy.title} + {copy.title} Your report will be sent to the Bluesky Moderation Service @@ -213,11 +213,10 @@ function SubmitStep({ )} - + Reason: {' '} - {reportOption.title} + {reportOption.title} @@ -347,7 +346,7 @@ function DoneStep({ return ( - + Report submitted diff --git a/src/components/forms/FormError.tsx b/src/components/forms/FormError.tsx index d28c89c8d..d51243d50 100644 --- a/src/components/forms/FormError.tsx +++ b/src/components/forms/FormError.tsx @@ -20,8 +20,7 @@ export function FormError({error}: {error?: string}) { ]}> - + {error} diff --git a/src/components/forms/TextField.tsx b/src/components/forms/TextField.tsx index 48f71e73a..85fb7c481 100644 --- a/src/components/forms/TextField.tsx +++ b/src/components/forms/TextField.tsx @@ -15,6 +15,7 @@ import { android, applyFonts, atoms as a, + ios, platform, type TextStyleProp, tokens, @@ -201,23 +202,17 @@ export function createInput(Component: typeof TextInput) { a.px_xs, { // paddingVertical doesn't work w/multiline - esb - lineHeight: a.text_md.fontSize * 1.2, + lineHeight: a.text_md.fontSize * 1.1875, textAlignVertical: rest.multiline ? 'top' : undefined, minHeight: rest.multiline ? 80 : undefined, minWidth: 0, - paddingTop: 13, - paddingBottom: 13, }, - android({ - paddingTop: 8, - paddingBottom: 9, - }), - /* - * Margins are needed here to avoid autofill background overlapping the - * top and bottom borders - esb - */ + ios({paddingTop: 12, paddingBottom: 13}), + // Needs to be sm on Paper, md on Fabric for some godforsaken reason -sfn + android(a.py_sm), + // fix for autofill styles covering border web({ - paddingTop: 11, + paddingTop: 10, paddingBottom: 11, marginTop: 2, marginBottom: 2, @@ -267,7 +262,7 @@ export function createInput(Component: typeof TextInput) { a.absolute, a.inset_0, a.rounded_sm, - t.atoms.bg_contrast_50, + t.atoms.bg_contrast_25, {borderColor: 'transparent', borderWidth: 2}, ctx.hovered ? chromeHover : {}, ctx.focused ? chromeFocus : {}, @@ -292,12 +287,7 @@ export function LabelText({ return ( + style={[a.text_sm, a.font_bold, t.atoms.text_contrast_medium, a.mb_sm]}> {children} ) diff --git a/src/components/forms/Toggle.tsx b/src/components/forms/Toggle.tsx index d6a968ecf..bb9fde2e1 100644 --- a/src/components/forms/Toggle.tsx +++ b/src/components/forms/Toggle.tsx @@ -249,7 +249,7 @@ export function LabelText({ return ( diff --git a/src/components/intents/VerifyEmailIntentDialog.tsx b/src/components/intents/VerifyEmailIntentDialog.tsx index 3aca1b6d8..ab628eeef 100644 --- a/src/components/intents/VerifyEmailIntentDialog.tsx +++ b/src/components/intents/VerifyEmailIntentDialog.tsx @@ -75,7 +75,7 @@ function Inner({}: {control: DialogControlProps}) { ) : status === 'success' ? ( - + Email Verified @@ -87,7 +87,7 @@ function Inner({}: {control: DialogControlProps}) { ) : status === 'failure' ? ( - + Invalid Verification Code @@ -100,13 +100,13 @@ function Inner({}: {control: DialogControlProps}) { ) : ( - + Email Resent We have sent another verification email to{' '} - + {currentAccount?.email} . diff --git a/src/components/interstitials/Trending.tsx b/src/components/interstitials/Trending.tsx index 2580ef28f..5561be18e 100644 --- a/src/components/interstitials/Trending.tsx +++ b/src/components/interstitials/Trending.tsx @@ -82,7 +82,7 @@ export function Inner() { style={[ t.atoms.text_contrast_medium, a.text_sm, - a.font_semi_bold, + a.font_bold, ]}> {' '} @@ -101,7 +101,7 @@ export function Inner() { style={[ t.atoms.text, a.text_sm, - a.font_semi_bold, + a.font_bold, {opacity: 0.7}, // NOTE: we use opacity 0.7 instead of a color to match the color of the home pager tab bar ]}> {topic.topic} diff --git a/src/components/interstitials/TrendingVideos.tsx b/src/components/interstitials/TrendingVideos.tsx index 175f92fd5..6be64335a 100644 --- a/src/components/interstitials/TrendingVideos.tsx +++ b/src/components/interstitials/TrendingVideos.tsx @@ -82,7 +82,7 @@ export function TrendingVideos() { a.align_center, a.justify_between, ]}> - + Trending Videos