UNPKG

consensys-ui

Version:

Consensys UI component library and design system

215 lines (198 loc) 6.42 kB
import { Config as TailwindConfig } from 'tailwindcss'; import plugin from 'tailwindcss/plugin.js'; import tailwindcssAnimate from 'tailwindcss-animate'; import { generateColorCssVars, generateThemeCssVars, generateShadowCssVars, generateConfig, } from "./utils"; import _ from "lodash"; import { Config, ConfigColorShades, ConfigTheme, ConfigThemes, CssVariableRecord, UserConfig } from "./types"; import { COLOR_MODES, DEFAULT_THEME } from "./constants"; import rnrPreset from './rnr.config'; import type { CSSRuleObject } from 'tailwindcss/types/config'; const getThemeColorKeys = (themes: ConfigThemes): string[] => { return _.uniq(_.flatMap(Object.values(themes), (theme: ConfigTheme) => { const colors = theme.colors; const mergedTheme = _.merge( {}, _.omit(colors, [COLOR_MODES.Light, COLOR_MODES.Dark]), colors[COLOR_MODES.Light] || {}, colors[COLOR_MODES.Dark] || {} ); return Object.keys(mergedTheme); })); }; const defineCssVars = (themes: ConfigThemes) => plugin(({ addBase }) => { const vars: Record<string, CssVariableRecord> = {}; Object.entries(themes).forEach(([themeName, theme]) => { const lightClassName = themeName === DEFAULT_THEME ? `.${COLOR_MODES.Light}` : `.${themeName}.${COLOR_MODES.Light}`; const darkClassName = themeName === DEFAULT_THEME ? `.${COLOR_MODES.Dark}` : `.${themeName}.${COLOR_MODES.Dark}`; // Generate color variables const lightVars = generateThemeCssVars(theme.colors.light); const darkVars = generateThemeCssVars(theme.colors.dark); // Generate shadow variables if they exist if (theme.boxShadow) { Object.assign(lightVars, generateShadowCssVars(theme.boxShadow.light)); Object.assign(darkVars, generateShadowCssVars(theme.boxShadow.dark)); } vars[lightClassName] = lightVars; vars[darkClassName] = darkVars; }); // Convert the vars record into a CSSRuleObject const cssRules: CSSRuleObject = Object.entries(vars).reduce((acc, [selector, variables]) => ({ ...acc, [selector]: variables }), {}); addBase(cssRules); }); const assignCssVars = (themes: ConfigThemes): Record<string, ConfigColorShades> => { return Object.fromEntries( getThemeColorKeys(themes).map(key => [key, generateColorCssVars(key)]) ); }; const assignShadowVars = (themes: ConfigThemes): Record<string, string> => { const defaultTheme = themes[DEFAULT_THEME]; if (!defaultTheme?.boxShadow?.light) return {}; return Object.fromEntries( Object.keys(defaultTheme.boxShadow.light).map(key => [ key, `var(--shadow-${key})` ]) ); }; const pxToRem = (px: number, base: number = 16) => `${px / base}rem`; export const tailwindPreset = (userConfig: UserConfig): TailwindConfig => { const config = generateConfig(userConfig); return { darkMode: 'class', content: [], presets: [ rnrPreset, ], plugins: [ defineCssVars(config.themes), tailwindcssAnimate, ], theme: { extend: { colors: assignCssVars(config.themes), boxShadow: assignShadowVars(config.themes), spacing: { 0: '0rem', '0.5': '0.125rem', 1: '0.25rem', '1.5': '0.375rem', 2: '0.5rem', '2.5': '0.625rem', 3: '0.75rem', '3.5': '0.875rem', 4: '1rem', 5: '1.25rem', 6: '1.5rem', 7: '1.75rem', 8: '2rem', 10: '2.5rem', 12: '3rem', 14: '3.5rem', 16: '4rem', 18: '4.5rem', 20: '5rem', 24: '6rem', 28: '7rem', 32: '8rem', 36: '9rem', 40: '10rem', }, borderRadius: { 0: '0', 1: pxToRem(2), 2: pxToRem(4), 3: pxToRem(6), 4: pxToRem(8), 5: pxToRem(10), 6: pxToRem(12), 7: pxToRem(14), 8: pxToRem(16), 'full': '9999px', }, fontFamily: { inter: ['"Inter"', 'sans-serif'], roboto: ['"Roboto"', 'sans-serif'], robotoCondensed: ['"Roboto Condensed"', 'sans-serif'], robotoSlab: ['"Roboto Slab"', 'serif'], libreFranklin: ['"Libre Franklin"', 'sans-serif'], }, fontWeight: { light: '300', regular: '400', medium: '500', bold: '700', }, lineHeight: { 'tight': '1.25', 'normal': '1.5', 'loose': '2', }, fontSize: { // font 2: '0.5rem', '2.5': '0.625rem', 3: '0.75rem', '3.5': '0.875rem', 4: '1rem', '4.5': '1.125rem', 5: '1.25rem', '5.5': '1.375rem', 6: '1.5rem', 7: '1.75rem', 8: '2rem', 10: '2.5rem', 12: '3rem', 14: '3.5rem', 16: '4rem', // text 'xl': ['1.25rem', { lineHeight: '1.875rem', fontWeight: '400' }], 'lg': ['1.125rem', { lineHeight: '1.6875rem', fontWeight: '400' }], 'base': ['1rem', { lineHeight: '1.5rem', fontWeight: '400' }], 'sm': ['0.875rem', { lineHeight: '1.3125rem', fontWeight: '400' }], 'xs': ['0.75rem', { lineHeight: '1.125rem', fontWeight: '400' }], // heading 'h1': ['4rem', { lineHeight: '5rem', fontWeight: '700' }], 'h2': ['3rem', { lineHeight: '3.75rem', fontWeight: '700' }], 'h3': ['2rem', { lineHeight: '2.5rem', fontWeight: '700' }], 'h4': ['1.75rem', { lineHeight: '2.1875rem', fontWeight: '700' }], 'h5': ['1.5rem', { lineHeight: '1.875rem', fontWeight: '700' }], 'h6': ['1.25rem', { lineHeight: '1.5625rem', fontWeight: '700' }], }, animation: { 'spin-normal': 'spin 2s linear infinite', 'spin-slow': 'spin 4s linear infinite', 'spin-fast': 'spin 1s linear infinite', 'spin-reverse': 'spin 2s linear infinite reverse', }, keyframes: { spin: { '0%': { transform: 'rotate(0deg)' }, '100%': { transform: 'rotate(360deg)' }, }, }, }, }, safelist: [ ...Object.values(COLOR_MODES), ...Object.keys(config.themes), ], }; };