Skip to content

Instantly share code, notes, and snippets.

@dariye
Created June 26, 2019 08:49
Show Gist options
  • Save dariye/2fa113f84658284811cb7006e957ed9a to your computer and use it in GitHub Desktop.
Save dariye/2fa113f84658284811cb7006e957ed9a to your computer and use it in GitHub Desktop.
theme.ts
import { darken, parseToHsl, hsl, getLuminance } from "polished";
const addAliases = (arr: (string | number)[], aliases: string[]) =>
aliases.forEach((key, i) =>
Object.defineProperty(arr, key, {
enumerable: false,
get() {
return this[i];
}
})
);
const createMediaQuery = (n: number) => `@media screen and (min-width:${n}em)`;
const aliases = ["sm", "md", "lg", "xl"];
// Breakpoints
export const breakpoints = [32, 48, 64, 75];
export const mediaQueries = breakpoints.map(createMediaQuery);
addAliases(breakpoints, aliases);
addAliases(mediaQueries, aliases);
// Spacing
export const space = [0, 4, 8, 16, 22, 28, 32, 64, 128, 256, 512];
// Typography
export const fonts = {
sans: "'Inter UI', 'Open Sans', arial, system-ui, sans-serif",
system:
"-apple-system,BlinkMacSystemFont,Segoe UI',Roboto,Oxygen-Sans,Ubuntu,Cantarell,'Helvetica Neue', sans-serif",
serif: "'Courier New', monospace, serif",
mono:
"'Lucida Console', 'Lucida Sans Typewriter', monaco, 'Bitstream Vera Sans Mono', monospace"
};
export const fontSizes = [12, 14, 16, 20, 24, 32, 48];
export const thin = 300;
export const regular = 400;
export const medium = 500;
export const semibold = 600;
export const bold = 700;
export const bolder = 900;
export const fontWeights = {
thin,
regular,
medium,
semibold,
bold,
bolder
};
export const lineHeights = {
normal: 1,
body: 1.5,
title: 1.25
};
const letterSpacings = {
normal: "normal",
tracked: "0.1em",
tight: "-0.05em",
mega: "0.025em"
};
// Border radius
export const radii = [0, "2px", "6px", "8px", "12px", "22px", "999px", "100%"];
// Borders
export const borderWidths = [0, "1px", "2px", "7px"];
// Max container
export const maxContainerWidth = "1329px";
// Colors
const names = [
"red", // 0
"orange", // 30
"yellow", // 60
"lime", // 90
"green", // 120
"teal", // 150
"cyan", // 180
"blue", // 210
"indigo", // 240
"violet", // 270
"fuchsia", // 300
"pink", // 330
"red" // 360
];
const palette = {
"shade-900": "#000000",
"shade-700": "#222222",
"shade-600": "#333333",
"shade-500": "#676D70",
"shade-400": "#838C91",
"shade-300": "#BEC3C6",
"shade-200": "#E2E4E6",
"shade-100": "#EEEEEE",
"shade-50": "#FAFAFA",
"shade-0": "#FFFFFF",
"pink-900": "#801933",
"pink-800": "#B32447",
"pink-700": "#CC2952",
"pink-600": "#E62E5C",
"pink-500": "#FF3366",
"pink-400": "#FF3769",
"pink-300": "#FF98B2",
"pink-200": "#FFC1D1",
"pink-100": "#FFD6E0",
"pink-50": "#FFF5F8",
"blue-900": "#285180",
"blue-800": "#2F6199",
"blue-700": "#3771B3",
"blue-600": "#3F81CC",
"blue-500": "#4790E5",
"blue-400": "#4FA1FF",
"blue-300": "#91BCEF",
"blue-200": "#B5D3F5",
"blue-100": "#DAE9FA",
"blue-50": "#F2F7FD",
"green-900": "#2E804C",
"green-800": "#37995B",
"green-700": "#40B36A",
"green-600": "#49CC79",
"green-500": "#53E588",
"green-400": "#5CFF98",
"green-300": "#BAF5CF",
"green-200": "#CBF7DB",
"green-100": "#DDFAE7",
"green-50": "#F3FDF7",
"red-900": "#751616",
"red-800": "#8F1B1B",
"red-700": "#A82020",
"red-600": "#C22525",
"red-500": "#DB2929",
"red-400": "#DB2929",
"red-300": "#F1A9A9",
"red-200": "#F4BEBE",
"red-100": "#F8D4D",
"red-50": "#FCF0F0",
"yellow-900": "#99710B",
"yellow-800": "#B3830C",
"yellow-700": "#CC960E",
"yellow-600": "#E6A910",
"yellow-500": "#FFBB11",
"yellow-400": "#F9D34B",
"yellow-300": "#FFE4A0",
"yellow-200": "#FFEAB7",
"yellow-100": "#FFF1CF",
"yellow-50": "#FFFAEE"
};
const baseColors = {
...palette,
white: "#FFFFFF",
black: "#000000",
grey: palette["shade-500"],
pink: palette["pink-500"],
blue: palette["blue-500"],
green: palette["green-500"],
red: palette["red-500"],
yellow: palette["yellow-500"]
};
const hueName = (h: number) => {
const i = Math.round((h - 2) / 30);
const name = names[i];
return name;
};
const createHues = (h: number) =>
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].map(n =>
Math.floor((h + (n * 360) / 12) % 360)
);
export const createColors = (base: string) => {
const colors = {
...baseColors,
// Old colors
error: baseColors.red,
success: baseColors.green,
warning: baseColors.yellow,
border: baseColors["shade-100"],
"dark-text": palette["shade-600"],
"darker-grey": baseColors.grey,
"dark-grey": baseColors["shade-300"],
"neutral-grey": baseColors["shade-300"],
"light-grey": baseColors["shade-100"],
"white-gray": baseColors["shade-50"],
"off-white": baseColors["shade-100"],
"page-background": baseColors["shade-100"],
"page-background-overlay": darken(0.2, baseColors["shade-100"]),
"drop-shadow": baseColors["shade-300"],
"brand-pink": baseColors.pink,
"brand-pink-hover": baseColors["pink-600"],
"brand-pink-light": baseColors["pink-200"],
"brand-blue": baseColors["blue-500"],
"brand-blue-alpha": baseColors["blue-50"],
"brand-blue-hover": baseColors["blue-600"],
"brand-blue-light": baseColors["blue-200"],
"brand-white": baseColors["shade-0"],
"text-color-lighter": baseColors["shade-400"],
"text-color-light": baseColors.grey,
"text-color-dark": baseColors["shade-600"],
"text-color-positive": baseColors.green,
"input-neutral": baseColors["shade-100"],
"input-focus": baseColors.blue,
"input-unfocus": baseColors["shade-300"],
backdrop: baseColors["shade-400"],
"border-light-grey": baseColors["shade-100"],
"table-header-light": baseColors["shade-0"],
"table-header-dark": baseColors["shade-100"],
"dark-blue": baseColors["shade-600"]
};
const { hue, saturation, lightness } = parseToHsl(base);
const hues = createHues(hue);
hues.forEach((h: number) => {
const name = hueName(h);
colors[name] = hsl(h, saturation, lightness);
});
return colors;
};
export const invertLuminance = (base: string) => {
const luminance = getLuminance(base);
const { hue, saturation } = parseToHsl(base);
return hsl(hue, saturation, 1 - luminance);
};
export const colors = createColors(baseColors.pink);
export const boxShadows = [
`0 0 2px 0 rgba(0,0,0,.08),0 1px 4px 0 rgba(0,0,0,.16)`,
`0 0 2px 0 rgba(0,0,0,.08),0 2px 8px 0 rgba(0,0,0,.16)`,
`0 0 2px 0 rgba(0,0,0,.08),0 4px 16px 0 rgba(0,0,0,.16)`,
`0 0 2px 0 rgba(0,0,0,.08),0 8px 32px 0 rgba(0,0,0,.16)`
];
// // Duration
export const duration = {
fast: `150ms`,
normal: `300ms`,
slow: `450ms`,
slowest: `600ms`
};
// // Timing
const easeInOut = "cubic-bezier(0.5, 0, 0.25, 1)";
const easeOut = "cubic-bezier(0, 0, 0.25, 1)";
const easeIn = "cubic-bezier(0.5, 0, 1, 1)";
const timingFunctions = {
easeInOut,
easeOut,
easeIn
};
// // Delay
const transitionDelays = {
small: `60ms`,
medium: `160ms`,
large: `260ms`,
xLarge: `360ms`
};
// Default component styles
const Text = {
fontFamily: fonts.sans,
lineHeight: lineHeights.body,
fontSize: fontSizes[2]
};
// variants
const texts = {
body: {},
strong: {}
};
const Heading = {
fontFamily: fonts.sans,
lineHeight: lineHeights.title,
fontSize: fontSizes[4]
};
// variants
const headings = {
h1: {},
h2: {},
h3: {},
h4: {},
h5: {},
h6: {}
};
const Button = {
height: "40px",
borderRadius: radii[5],
paddingLeft: 30,
paddingRight: 30,
paddingTop: 0,
paddingBottom: 0,
fontSize: fontSizes[2],
fontWeight: fontWeights.regular,
fill: "currentColor"
};
// variants
const buttons = {
default: {
color: colors.grey,
background: "#ebeff3",
boxShadow: "inset 0 0 0 3px #f0f4f6",
"&:hover": {
boxShadow: "inset 0 0 0 3px #ddd"
}
},
link: {
paddingLeft: 0,
paddingRight: 0,
paddingTop: 0,
paddingBottom: 0,
margin: 0,
border: 0,
color: colors.blue,
textDecoration: "none",
verticalAlign: "middle",
cursor: "pointer",
background: "none",
boxShadow: "none"
},
disabled: {
color: "#B3B4C2",
cursor: "not-allowed",
bg: "#B3B4C2"
},
rounded: {
borderRadius: radii[4]
},
transparent: {
background: "transparent",
border: `1px solid ${colors["light-grey"]}`
}
};
const Link = {
color: colors.blue
};
// variants
const links = {};
const Image = {};
// variants
const images = {
avatar: {
borderRadius: radii[7],
height: 32,
width: 32
},
loading: {
opacity: 0
},
square: {
borderRadius: radii[1]
},
fallback: {
color: colors["brand-white"],
border: "none"
}
};
const Card = {};
// variants
const cards = {};
export const lightTheme = {
name: "light",
breakpoints,
mediaQueries,
space,
fonts,
fontSizes,
fontWeights,
lineHeights,
letterSpacings,
thin,
regular,
medium,
semibold,
bold,
bolder,
colors,
radii,
borderWidths,
maxContainerWidth,
boxShadows,
duration,
timingFunctions,
transitionDelays,
Text,
texts,
Heading,
headings,
Button,
buttons,
Link,
links,
Image,
images,
Card,
cards
};
export const darkTheme = {
...lightTheme,
name: "dark",
colors: {
...colors,
"page-background": colors.black
}
};
export default { light: lightTheme, dark: darkTheme };
// Todo:
// Web
// Shadows
// Mobile themes
// padding: 22 / 28
// colors
// border-radius
// margin
// shadows // elevated // color
// flex // width
// fontSize
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment