crystal-ball/componentry

View on GitHub
src/theme/theme-defaults.ts

Summary

Maintainability
B
4 hrs
Test Coverage
A
100%
/*                                 ⚙️ Componentry default theme specification
 * -------------------------------------------------------------------------- */

const gray = {
  100: '#eff2f3',
  200: '#d7dfe2',
  300: '#bfcbd1',
  400: '#90a4ae',
  500: '#607d8b',
  600: '#56717d',
  700: '#3a4b53',
  800: '#2b383f',
  900: '#1d262a',
}

export const themeDefaults = {
  // --- SCREENS
  screens: {
    //   Componentry has a single breakpoint by default, additional breakpoints can
    //   be added. 1200px is used for the default to try and ensure all smaller
    //   desktops are included. (992, 1200, 1280 are the most common large breakpoints)
    //   For multiple breakpoints 768 and 1280 are common breakpoints for md and lg.
    lg: '1200px',
  },

  // --- COLORS
  colors: {
    current: 'currentColor',
    transparent: 'transparent',
    background: '#fff',
    inherit: 'inherit',
    inverse: '#eff',
    gray,
    primary: {
      100: '#f2f1ff',
      200: '#dfddff',
      300: '#cbc9ff',
      400: '#a4a0ff',
      500: '#7d77ff',
      600: '#716be6',
      700: '#4b4799',
      800: '#383673',
      900: '#26244d',
    },
    info: {
      100: '#dbeafe',
      200: '#bfdbfe',
      300: '#93c5fd',
      400: '#60a5fa',
      500: '#3b82f6',
      600: '#2563eb',
      700: '#1d4ed8',
      800: '#1e40af',
      900: '#1e3a8a',
    },
    success: {
      100: '#f4f9ed',
      200: '#e4f1d2',
      300: '#d4e8b7',
      400: '#b3d681',
      500: '#93c54b',
      600: '#84b144',
      700: '#58762d',
      800: '#425922',
      900: '#2c3b17',
    },
    warning: {
      100: '#fdf8ec',
      200: '#fbedcf',
      300: '#f9e2b2',
      400: '#f4cd78',
      500: '#efb73e',
      600: '#d7a538',
      700: '#8f6e25',
      800: '#6c521c',
      900: '#483713',
    },
    error: {
      100: '#fbeeed',
      200: '#f6d4d3',
      300: '#f0bab9',
      400: '#e48784',
      500: '#d9534f',
      600: '#c34b47',
      700: '#82322f',
      800: '#622524',
      900: '#411918',
    },
  },

  // --- LAYOUT
  zIndex: {
    auto: 'auto',
    modal: 10,
  },

  // --- FLEX/GRID
  flexBasis: { auto: 'auto', px: 'px', full: 'full' },
  flexGrow: { DEFAULT: 1, 0: 0 },
  flexShrink: { DEFAULT: 1, 0: 0 },
  gridColumn: {
    auto: 'auto',
    'span-full': 'span-full',
    'start-auto': 'start-auto',
    'end-auto': 'end-auto',
  },
  gridRow: {
    auto: 'auto',
    'span-full': 'span-full',
    'start-auto': 'start-auto',
    'end-auto': 'end-auto',
  },
  gridTemplateColumns: { none: 'none' },
  gridTemplateRows: { none: 'none' },
  order: { first: 'first', last: 'last', none: 'none' },

  // --- SPACING
  spacing: {
    auto: 'auto',
    px: '1px',
    0: 0,
    0.5: '0.125rem', // 2px
    1: '0.25rem', // 4px
    1.5: '0.375rem', // 6px
    2: '0.5rem', // 8px
    2.5: '0.625rem', // 10px
    3: '0.75rem', // 12px
    4: '1rem', // 16px
    5: '1.25rem', // 20px
    6: '1.5rem', // 24px
    8: '2rem', // 32px
    10: '2.5rem', // 40px
    12: '3rem', // 48px
    14: '3.5rem', // 56px
    16: '4rem', // 64px
    20: '5rem', // 80px
    24: '6rem', // 96px
    32: '8rem', // 128px
    48: '12rem', // 192px
    64: '16rem', // 256px
  },
  /**
   * spacingRatio allows defining a spacing conversion function for computing
   * spacing values.
   * @remarks
   * This is useful when using Componentry with other component libraries that
   * depend on computing spacing values.
   * @example
   * {
   *   // Convert any arbitrary value to an 8px grid value
   *   spacingRatio: base => `${base * 8}px`
   * }
   */
  spacingRatio: undefined as undefined | ((base: number) => string),

  // --- SIZING
  height: {
    0: 0,
    auto: 'auto',
    full: '100%',
    screen: '100vh',
    min: 'min-content',
    max: 'max-content',
    fit: 'fit-content',
  },
  width: {
    0: 0,
    auto: 'auto',
    full: '100%',
    screen: '100vw',
    min: 'min-content',
    max: 'max-content',
    fit: 'fit-content',
    prose: '65ch',
  },

  // --- TYPOGRAPHY
  // remarks: including the text element map in the theme can make it easy to
  // define the value in a place that is importable by Babel for pre-compiling
  textElementMap: undefined as undefined | TextElementMap,
  fontFamily: {
    body: "system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji'",
    mono: "SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace",
  },
  fontSize: {
    inherit: 'inherit',
    base: '1rem', // HTML base size
    sm: '0.875rem',
    lg: '1.25rem',
    h1: '3rem',
    h2: '2rem',
    h3: '1.5rem',
    body: '1rem',
  },
  fontWeight: {
    light: 300,
    normal: 400,
    bold: 700,
  },
  letterSpacing: {
    tighter: '-0.05em',
    tight: '-0.025em',
    normal: '0em',
    wide: '0.025em',
    wider: '0.05em',
    widest: '0.1em',
  },
  lineHeight: {
    none: 1,
    normal: 1.5,
  },

  textColor: undefined as { [Color: string]: string } | undefined, // Optional semantic typography colors definition

  // --- BACKGROUND

  backgroundColor: undefined as { [Color: string]: string } | undefined, // Optional semantic background colors definition

  // --- BORDERS
  border: {
    DEFAULT: `1px solid ${gray[500]}`,
  },
  borderRadius: {
    DEFAULT: '0.25rem', // 4px
    none: '0px',
    full: '9999px',
    sm: '0.125rem', // 2px
    md: '0.375rem', // 6px
    lg: '6px', // 8px
    xl: '0.75rem', // 12px
    '2xl': '1rem', // 16px
    '3xl': '1.5rem', // 24px
  },
  borderStyle: {
    dashed: 'dashed',
    dotted: 'dotted',
    double: 'double',
    hidden: 'hidden',
    none: 'none',
    solid: 'solid',
  },
  borderWidth: {
    0: 0,
    1: '1px',
    2: '2px',
    4: '4px',
    8: '8px',
  },

  borderColor: undefined as { [Color: string]: string } | undefined, // Optional semantic border colors definition

  // --- EFFECTS
  boxShadow: {
    DEFAULT: '0 0.5rem 1rem rgba(73, 80, 87, 0.15)',
  },
} as const

/**
 * Mapping of Text variants to rendered elements
 * @example
 * ```ts
 * const textElementsMap: TextElementsMap = {
 *   h1: 'h1',
 *   body: 'p',
 * }
 * ```
 */
export interface TextElementMap {
  [Variant: string]: keyof JSX.IntrinsicElements | React.ComponentType
}