about summary refs log tree commit diff
path: root/src/alf
diff options
context:
space:
mode:
Diffstat (limited to 'src/alf')
-rw-r--r--src/alf/atoms.ts41
-rw-r--r--src/alf/index.tsx6
-rw-r--r--src/alf/themes.ts87
-rw-r--r--src/alf/tokens.ts46
-rw-r--r--src/alf/util/colorGeneration.ts17
-rw-r--r--src/alf/util/platform.ts26
-rw-r--r--src/alf/util/useColorModeTheme.ts19
7 files changed, 185 insertions, 57 deletions
diff --git a/src/alf/atoms.ts b/src/alf/atoms.ts
index f75e8ffe0..0b473ba90 100644
--- a/src/alf/atoms.ts
+++ b/src/alf/atoms.ts
@@ -1,3 +1,5 @@
+import {Platform} from 'react-native'
+import {web, native} from '#/alf/util/platform'
 import * as tokens from '#/alf/tokens'
 
 export const atoms = {
@@ -5,7 +7,7 @@ export const atoms = {
    * Positioning
    */
   fixed: {
-    position: 'fixed',
+    position: Platform.select({web: 'fixed', native: 'absolute'}) as 'absolute',
   },
   absolute: {
     position: 'absolute',
@@ -48,6 +50,9 @@ export const atoms = {
   h_full: {
     height: '100%',
   },
+  h_full_vh: web({
+    height: '100vh',
+  }),
 
   /*
    * Border radius
@@ -110,9 +115,18 @@ export const atoms = {
   flex_row: {
     flexDirection: 'row',
   },
+  flex_col_reverse: {
+    flexDirection: 'column-reverse',
+  },
+  flex_row_reverse: {
+    flexDirection: 'row-reverse',
+  },
   flex_wrap: {
     flexWrap: 'wrap',
   },
+  flex_0: {
+    flex: web('0 0 auto') || (native(0) as number),
+  },
   flex_1: {
     flex: 1,
   },
@@ -176,46 +190,65 @@ export const atoms = {
   },
   text_2xs: {
     fontSize: tokens.fontSize._2xs,
+    letterSpacing: 0.25,
   },
   text_xs: {
     fontSize: tokens.fontSize.xs,
+    letterSpacing: 0.25,
   },
   text_sm: {
     fontSize: tokens.fontSize.sm,
+    letterSpacing: 0.25,
   },
   text_md: {
     fontSize: tokens.fontSize.md,
+    letterSpacing: 0.25,
   },
   text_lg: {
     fontSize: tokens.fontSize.lg,
+    letterSpacing: 0.25,
   },
   text_xl: {
     fontSize: tokens.fontSize.xl,
+    letterSpacing: 0.25,
   },
   text_2xl: {
     fontSize: tokens.fontSize._2xl,
+    letterSpacing: 0.25,
   },
   text_3xl: {
     fontSize: tokens.fontSize._3xl,
+    letterSpacing: 0.25,
   },
   text_4xl: {
     fontSize: tokens.fontSize._4xl,
+    letterSpacing: 0.25,
   },
   text_5xl: {
     fontSize: tokens.fontSize._5xl,
+    letterSpacing: 0.25,
   },
   leading_tight: {
     lineHeight: 1.15,
   },
   leading_snug: {
-    lineHeight: 1.25,
+    lineHeight: 1.3,
   },
   leading_normal: {
     lineHeight: 1.5,
   },
+  tracking_normal: {
+    letterSpacing: 0,
+  },
+  tracking_wide: {
+    letterSpacing: 0.25,
+  },
   font_normal: {
     fontWeight: tokens.fontWeight.normal,
   },
+  font_semibold: {
+    fontWeight: '500',
+  },
   font_bold: {
     fontWeight: tokens.fontWeight.semibold,
   },
@@ -501,6 +534,10 @@ export const atoms = {
   /*
    * Margin
    */
+  mx_auto: {
+    marginLeft: 'auto',
+    marginRight: 'auto',
+  },
   m_2xs: {
     margin: tokens.space._2xs,
   },
diff --git a/src/alf/index.tsx b/src/alf/index.tsx
index 06d6ebf01..f0a0ede7a 100644
--- a/src/alf/index.tsx
+++ b/src/alf/index.tsx
@@ -16,8 +16,9 @@ type BreakpointName = keyof typeof breakpoints
 const breakpoints: {
   [key: string]: number
 } = {
+  gtPhone: 500,
   gtMobile: 800,
-  gtTablet: 1200,
+  gtTablet: 1300,
 }
 function getActiveBreakpoints({width}: {width: number}) {
   const active: (keyof typeof breakpoints)[] = Object.keys(breakpoints).filter(
@@ -26,6 +27,7 @@ function getActiveBreakpoints({width}: {width: number}) {
 
   return {
     active: active[active.length - 1],
+    gtPhone: active.includes('gtPhone'),
     gtMobile: active.includes('gtMobile'),
     gtTablet: active.includes('gtTablet'),
   }
@@ -39,6 +41,7 @@ export const Context = React.createContext<{
   theme: themes.Theme
   breakpoints: {
     active: BreakpointName | undefined
+    gtPhone: boolean
     gtMobile: boolean
     gtTablet: boolean
   }
@@ -47,6 +50,7 @@ export const Context = React.createContext<{
   theme: themes.light,
   breakpoints: {
     active: undefined,
+    gtPhone: false,
     gtMobile: false,
     gtTablet: false,
   },
diff --git a/src/alf/themes.ts b/src/alf/themes.ts
index 72e08e894..0c95a459e 100644
--- a/src/alf/themes.ts
+++ b/src/alf/themes.ts
@@ -1,6 +1,7 @@
 import * as tokens from '#/alf/tokens'
 import type {Mutable} from '#/alf/types'
 import {atoms} from '#/alf/atoms'
+import {BLUE_HUE, GREEN_HUE, RED_HUE} from '#/alf/util/colorGeneration'
 
 export type ThemeName = 'light' | 'dim' | 'dark'
 export type ReadonlyTheme = typeof light
@@ -132,21 +133,63 @@ export const darkPalette: Palette = {
 
 export const dimPalette: Palette = {
   ...darkPalette,
-  black: tokens.color.gray_1000,
+  black: `hsl(${BLUE_HUE}, 28%, ${tokens.dimScale[0]}%)`,
 
-  contrast_25: tokens.color.gray_975,
-  contrast_50: tokens.color.gray_950,
-  contrast_100: tokens.color.gray_900,
-  contrast_200: tokens.color.gray_800,
-  contrast_300: tokens.color.gray_700,
-  contrast_400: tokens.color.gray_600,
-  contrast_500: tokens.color.gray_500,
-  contrast_600: tokens.color.gray_400,
-  contrast_700: tokens.color.gray_300,
-  contrast_800: tokens.color.gray_200,
-  contrast_900: tokens.color.gray_100,
-  contrast_950: tokens.color.gray_50,
-  contrast_975: tokens.color.gray_25,
+  contrast_25: `hsl(${BLUE_HUE}, 28%, ${tokens.dimScale[1]}%)`,
+  contrast_50: `hsl(${BLUE_HUE}, 28%, ${tokens.dimScale[2]}%)`,
+  contrast_100: `hsl(${BLUE_HUE}, 28%, ${tokens.dimScale[3]}%)`,
+  contrast_200: `hsl(${BLUE_HUE}, 28%, ${tokens.dimScale[4]}%)`,
+  contrast_300: `hsl(${BLUE_HUE}, 24%, ${tokens.dimScale[5]}%)`,
+  contrast_400: `hsl(${BLUE_HUE}, 24%, ${tokens.dimScale[6]}%)`,
+  contrast_500: `hsl(${BLUE_HUE}, 20%, ${tokens.dimScale[7]}%)`,
+  contrast_600: `hsl(${BLUE_HUE}, 20%, ${tokens.dimScale[8]}%)`,
+  contrast_700: `hsl(${BLUE_HUE}, 20%, ${tokens.dimScale[9]}%)`,
+  contrast_800: `hsl(${BLUE_HUE}, 20%, ${tokens.dimScale[10]}%)`,
+  contrast_900: `hsl(${BLUE_HUE}, 20%, ${tokens.dimScale[11]}%)`,
+  contrast_950: `hsl(${BLUE_HUE}, 20%, ${tokens.dimScale[12]}%)`,
+  contrast_975: `hsl(${BLUE_HUE}, 20%, ${tokens.dimScale[13]}%)`,
+
+  primary_25: `hsl(${BLUE_HUE}, 99%, ${tokens.dimScale[13]}%)`,
+  primary_50: `hsl(${BLUE_HUE}, 99%, ${tokens.dimScale[12]}%)`,
+  primary_100: `hsl(${BLUE_HUE}, 99%, ${tokens.dimScale[11]}%)`,
+  primary_200: `hsl(${BLUE_HUE}, 99%, ${tokens.dimScale[10]}%)`,
+  primary_300: `hsl(${BLUE_HUE}, 99%, ${tokens.dimScale[9]}%)`,
+  primary_400: `hsl(${BLUE_HUE}, 99%, ${tokens.dimScale[8]}%)`,
+  primary_500: `hsl(${BLUE_HUE}, 99%, ${tokens.dimScale[7]}%)`,
+  primary_600: `hsl(${BLUE_HUE}, 95%, ${tokens.dimScale[6]}%)`,
+  primary_700: `hsl(${BLUE_HUE}, 90%, ${tokens.dimScale[5]}%)`,
+  primary_800: `hsl(${BLUE_HUE}, 82%, ${tokens.dimScale[4]}%)`,
+  primary_900: `hsl(${BLUE_HUE}, 70%, ${tokens.dimScale[3]}%)`,
+  primary_950: `hsl(${BLUE_HUE}, 60%, ${tokens.dimScale[2]}%)`,
+  primary_975: `hsl(${BLUE_HUE}, 50%, ${tokens.dimScale[1]}%)`,
+
+  positive_25: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[13]}%)`,
+  positive_50: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[12]}%)`,
+  positive_100: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[11]}%)`,
+  positive_200: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[10]}%)`,
+  positive_300: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[9]}%)`,
+  positive_400: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[8]}%)`,
+  positive_500: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[7]}%)`,
+  positive_600: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[6]}%)`,
+  positive_700: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[5]}%)`,
+  positive_800: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[4]}%)`,
+  positive_900: `hsl(${GREEN_HUE}, 70%, ${tokens.dimScale[3]}%)`,
+  positive_950: `hsl(${GREEN_HUE}, 60%, ${tokens.dimScale[2]}%)`,
+  positive_975: `hsl(${GREEN_HUE}, 50%, ${tokens.dimScale[1]}%)`,
+
+  negative_25: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[13]}%)`,
+  negative_50: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[12]}%)`,
+  negative_100: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[11]}%)`,
+  negative_200: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[10]}%)`,
+  negative_300: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[9]}%)`,
+  negative_400: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[8]}%)`,
+  negative_500: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[7]}%)`,
+  negative_600: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[6]}%)`,
+  negative_700: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[5]}%)`,
+  negative_800: `hsl(${RED_HUE}, 88%, ${tokens.dimScale[4]}%)`,
+  negative_900: `hsl(${RED_HUE}, 84%, ${tokens.dimScale[3]}%)`,
+  negative_950: `hsl(${RED_HUE}, 80%, ${tokens.dimScale[2]}%)`,
+  negative_975: `hsl(${RED_HUE}, 70%, ${tokens.dimScale[1]}%)`,
 } as const
 
 export const light = {
@@ -325,6 +368,7 @@ export const dark: Theme = {
 export const dim: Theme = {
   ...dark,
   name: 'dim',
+  palette: dimPalette,
   atoms: {
     ...dark.atoms,
     text: {
@@ -393,5 +437,20 @@ export const dim: Theme = {
     border_contrast_high: {
       borderColor: dimPalette.contrast_300,
     },
+    shadow_sm: {
+      ...atoms.shadow_sm,
+      shadowOpacity: 0.7,
+      shadowColor: `hsl(${BLUE_HUE}, 28%, 6%)`,
+    },
+    shadow_md: {
+      ...atoms.shadow_md,
+      shadowOpacity: 0.7,
+      shadowColor: `hsl(${BLUE_HUE}, 28%, 6%)`,
+    },
+    shadow_lg: {
+      ...atoms.shadow_lg,
+      shadowOpacity: 0.7,
+      shadowColor: `hsl(${BLUE_HUE}, 28%, 6%)`,
+    },
   },
 }
diff --git a/src/alf/tokens.ts b/src/alf/tokens.ts
index f0b8c7c69..4045c831c 100644
--- a/src/alf/tokens.ts
+++ b/src/alf/tokens.ts
@@ -1,25 +1,35 @@
-const BLUE_HUE = 211
-const RED_HUE = 346
-const GREEN_HUE = 152
+import {
+  BLUE_HUE,
+  RED_HUE,
+  GREEN_HUE,
+  generateScale,
+} from '#/alf/util/colorGeneration'
+
+export const scale = generateScale(6, 100)
+// dim shifted 6% lighter
+export const dimScale = generateScale(12, 100)
 
 export const color = {
   trueBlack: '#000000',
 
-  gray_0: `hsl(${BLUE_HUE}, 20%, 100%)`,
-  gray_25: `hsl(${BLUE_HUE}, 20%, 97%)`,
-  gray_50: `hsl(${BLUE_HUE}, 20%, 95%)`,
-  gray_100: `hsl(${BLUE_HUE}, 20%, 90%)`,
-  gray_200: `hsl(${BLUE_HUE}, 20%, 80%)`,
-  gray_300: `hsl(${BLUE_HUE}, 20%, 70%)`,
-  gray_400: `hsl(${BLUE_HUE}, 20%, 60%)`,
-  gray_500: `hsl(${BLUE_HUE}, 20%, 50%)`,
-  gray_600: `hsl(${BLUE_HUE}, 24%, 42%)`,
-  gray_700: `hsl(${BLUE_HUE}, 24%, 34%)`,
-  gray_800: `hsl(${BLUE_HUE}, 28%, 26%)`,
-  gray_900: `hsl(${BLUE_HUE}, 28%, 18%)`,
-  gray_950: `hsl(${BLUE_HUE}, 28%, 10%)`,
-  gray_975: `hsl(${BLUE_HUE}, 28%, 7%)`,
-  gray_1000: `hsl(${BLUE_HUE}, 28%, 4%)`,
+  temp_purple: 'rgb(105 0 255)',
+  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%)`,
diff --git a/src/alf/util/colorGeneration.ts b/src/alf/util/colorGeneration.ts
new file mode 100644
index 000000000..929a01d3a
--- /dev/null
+++ b/src/alf/util/colorGeneration.ts
@@ -0,0 +1,17 @@
+export const BLUE_HUE = 211
+export const RED_HUE = 346
+export const GREEN_HUE = 152
+
+/**
+ * Smooth progression of lightness "stops" for generating HSL colors.
+ */
+export const COLOR_STOPS = [
+  0, 0.05, 0.1, 0.15, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.85, 0.9, 0.95, 1,
+]
+
+export function generateScale(start: number, end: number) {
+  const range = end - start
+  return COLOR_STOPS.map(stop => {
+    return start + range * stop
+  })
+}
diff --git a/src/alf/util/platform.ts b/src/alf/util/platform.ts
index 544f5480b..294e08a8b 100644
--- a/src/alf/util/platform.ts
+++ b/src/alf/util/platform.ts
@@ -1,25 +1,25 @@
-import {Platform} from 'react-native'
+import {isAndroid, isIOS, isNative, isWeb} from 'platform/detection'
 
 export function web(value: any) {
-  return Platform.select({
-    web: value,
-  })
+  if (isWeb) {
+    return value
+  }
 }
 
 export function ios(value: any) {
-  return Platform.select({
-    ios: value,
-  })
+  if (isIOS) {
+    return value
+  }
 }
 
 export function android(value: any) {
-  return Platform.select({
-    android: value,
-  })
+  if (isAndroid) {
+    return value
+  }
 }
 
 export function native(value: any) {
-  return Platform.select({
-    native: value,
-  })
+  if (isNative) {
+    return value
+  }
 }
diff --git a/src/alf/util/useColorModeTheme.ts b/src/alf/util/useColorModeTheme.ts
index 48cf904fe..4f8921bf9 100644
--- a/src/alf/util/useColorModeTheme.ts
+++ b/src/alf/util/useColorModeTheme.ts
@@ -13,7 +13,7 @@ export function useColorModeTheme(): ThemeName {
   React.useLayoutEffect(() => {
     const theme = getThemeName(colorScheme, colorMode, darkTheme)
     updateDocument(theme)
-    updateSystemBackground(theme)
+    SystemUI.setBackgroundColorAsync(getBackgroundColor(theme))
   }, [colorMode, colorScheme, darkTheme])
 
   return React.useMemo(
@@ -42,23 +42,24 @@ function updateDocument(theme: ThemeName) {
   if (isWeb && typeof window !== 'undefined') {
     // @ts-ignore web only
     const html = window.document.documentElement
+    // @ts-ignore web only
+    const meta = window.document.querySelector('meta[name="theme-color"]')
+
     // remove any other color mode classes
     html.className = html.className.replace(/(theme)--\w+/g, '')
-
     html.classList.add(`theme--${theme}`)
+    // set color to 'theme-color' meta tag
+    meta?.setAttribute('content', getBackgroundColor(theme))
   }
 }
 
-function updateSystemBackground(theme: ThemeName) {
+function getBackgroundColor(theme: ThemeName): string {
   switch (theme) {
     case 'light':
-      SystemUI.setBackgroundColorAsync(light.atoms.bg.backgroundColor)
-      break
+      return light.atoms.bg.backgroundColor
     case 'dark':
-      SystemUI.setBackgroundColorAsync(dark.atoms.bg.backgroundColor)
-      break
+      return dark.atoms.bg.backgroundColor
     case 'dim':
-      SystemUI.setBackgroundColorAsync(dim.atoms.bg.backgroundColor)
-      break
+      return dim.atoms.bg.backgroundColor
   }
 }