UNPKG

@devseed-ui/theme-provider

Version:
289 lines (265 loc) 7.75 kB
import { createColorPalette } from './color-palette'; /** * Creates a UI theme by combining the provided options with the default ones. * When an override for a value is provided, it gets propagated to all the * variables that use that value. For example: The primary color will be used * for links unless a color for "link" is provided. * * @param {DevseedUITheme} definition The theme definition * * @returns DevseedUITheme */ export function createUITheme(definition = {}) { const { color = {}, type = {}, shape = {}, layout = {}, button = {}, boxShadow = {}, mediaRanges = {}, ...customDefinition } = definition; const { surface = '#FFFFFF', base = '#443F3F', primary = '#CF3F02', secondary = '#E2C044', danger = '#A71D31', warning = '#E2C044', success = '#4DA167', info = '#2E86AB', background, link, ...customColors } = color; const colorScales = { ...createColorPalette('base', base), ...createColorPalette('surface', surface), ...createColorPalette('primary', primary), ...createColorPalette('secondary', secondary), ...createColorPalette('danger', danger), ...createColorPalette('warning', warning), ...createColorPalette('success', success), ...createColorPalette('info', info) }; const { base: typeBase = {}, heading: typeHeading = {}, overline: typeOverline = {}, ...customType } = type; const { size: typeBaseSize = '1rem', line: typeBaseLine = 'calc(0.5rem + 1em)', color: typeBaseColor = base, family: typeBaseFamily = '"Open Sans", sans-serif', style: typeBaseStyle = 'normal', settings: typeBaseSettings = "'pnum' 0", case: typeBaseCase = 'none', light: typeBaseLight = 300, regular: typeBaseRegular = 400, medium: typeBaseMedium = 600, bold: typeBaseBold = 700, weight: typeBaseWeight = 300, antialiasing: typeBaseAntialiasing = true, ...customTypeBase } = typeBase; const { leadSize: typeLeadSize = `calc(${typeBaseSize} * 1.5)` } = typeBase; const { family: typeHeadingFamily = typeBaseFamily, style: typeHeadingStyle = typeBaseStyle, settings: typeHeadingSettings = '"wdth" 80, "wght" 780', case: typeHeadingCase = typeBaseCase, light: typeHeadingLight = typeBaseLight, regular: typeHeadingRegular = typeBaseRegular, medium: typeHeadingMedium = typeBaseMedium, bold: typeHeadingBold = typeBaseBold, weight: typeHeadingWeight = typeBaseBold, textTransform: typeHeadingTextTransform = 'none', ...customTypeHeading } = typeHeading; const { family: typeOverlineFamily = typeBaseFamily, style: typeOverlineStyle = typeBaseStyle, settings: typeOverlineSettings = typeBaseSettings, case: typeOverlineCase = typeBaseCase, light: typeOverlineLight = typeBaseLight, regular: typeOverlineRegular = typeBaseRegular, medium: typeOverlineMedium = typeBaseMedium, bold: typeOverlineBold = typeBaseBold, weight: typeOverlineWeight = typeBaseBold, textTransform: typeOverlineTextTransform = 'uppercase', ...customTypeOverline } = typeOverline; const { rounded = '0.25rem', ellipsoid = '320rem', ...customShape } = shape; const { space = '1rem', border = '1px', min = '320px', max = '1280px', ...customLayout } = layout; const { type: buttonType = {}, shape: buttonShape = {}, ...customButton } = button; const { family: buttonTypeFamily = typeBaseFamily, style: buttonTypeStyle = typeBaseStyle, settings: buttonTypeSettings = typeBaseSettings, case: buttonTypeCase = typeBaseCase, weight: buttonTypeWeight = typeBaseBold, ...customButtonType } = buttonType; const { border: buttonShapeBorder = border, rounded: buttonShapeRounded = rounded, ...customButtonShape } = buttonShape; const { inset = `inset 0px 0px 3px 0px ${colorScales['base-50a']};`, input = `0 -1px 1px 0 ${colorScales['base-100a']}, 0 2px 6px 0 ${colorScales['base-200a']};`, elevationA = `0 0 4px 0 ${colorScales['base-100a']}, 0 2px 2px 0 ${colorScales['base-100a']};`, elevationB = `0 0 4px 0 ${colorScales['base-100a']}, 0 4px 4px 0 ${colorScales['base-100a']};`, elevationC = `0 0 4px 0 ${colorScales['base-100a']}, 0 8px 12px 0 ${colorScales['base-100a']};`, elevationD = `0 0 4px 0 ${colorScales['base-100a']}, 0 12px 24px 0 ${colorScales['base-100a']};`, ...customBoxShadow } = boxShadow; const { xsmall = [null, 543], small = [544, 767], medium = [768, 991], large = [992, 1215], xlarge = [1216, null] } = mediaRanges; // // Theme object definition return { ...customDefinition, color: { // base color for the site. Text and all elements that are not colored. // required base, // Background color for filled elements that sit on top of the body. // (cards, panel, modal...) // required surface, // required primary, // required secondary, // States colors // required danger, // required warning, // required success, // required info, // Only used for body color. Uses surface if not provided. background: background || surface, // Color for links. Uses primary if not defined link: link || primary, // User defined colors which may include scales. ...customColors, // Scales ...colorScales }, type: { base: { size: typeBaseSize, leadSize: typeLeadSize, line: typeBaseLine, color: typeBaseColor, family: typeBaseFamily, style: typeBaseStyle, settings: typeBaseSettings, case: typeBaseCase, light: typeBaseLight, regular: typeBaseRegular, medium: typeBaseMedium, bold: typeBaseBold, weight: typeBaseWeight, antialiasing: typeBaseAntialiasing, ...customTypeBase }, heading: { family: typeHeadingFamily, style: typeHeadingStyle, settings: typeHeadingSettings, case: typeHeadingCase, light: typeHeadingLight, regular: typeHeadingRegular, medium: typeHeadingMedium, bold: typeHeadingBold, weight: typeHeadingWeight, textTransform: typeHeadingTextTransform, ...customTypeHeading }, overline: { family: typeOverlineFamily, style: typeOverlineStyle, settings: typeOverlineSettings, case: typeOverlineCase, light: typeOverlineLight, regular: typeOverlineRegular, medium: typeOverlineMedium, bold: typeOverlineBold, weight: typeOverlineWeight, textTransform: typeOverlineTextTransform, ...customTypeOverline }, ...customType }, shape: { rounded, ellipsoid, ...customShape }, layout: { space, border, min, max, ...customLayout }, button: { type: { family: buttonTypeFamily, style: buttonTypeStyle, settings: buttonTypeSettings, case: buttonTypeCase, weight: buttonTypeWeight, ...customButtonType }, shape: { border: buttonShapeBorder, rounded: buttonShapeRounded, ...customButtonShape }, ...customButton }, boxShadow: { inset, input, elevationA, elevationB, elevationC, elevationD, ...customBoxShadow }, mediaRanges: { xsmall, small, medium, large, xlarge } }; } export const theme = { main: createUITheme() };