Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: color modes docs #1186

Merged
merged 36 commits into from
Mar 11, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
f521e18
WIP: color modes docs
BinaryMuse Oct 20, 2020
fb8a46b
Merge branch 'mkt/color-modes-whee' into mkt/color-modes-docs
BinaryMuse Oct 22, 2020
ea3d15d
Update color mode mixin to support 'auto'
BinaryMuse Oct 23, 2020
0046e6d
Merge branch 'mkt/color-modes-whee' into mkt/color-modes-docs
BinaryMuse Oct 23, 2020
024bc21
docs wip
BinaryMuse Oct 23, 2020
18a30ac
Merge branch 'mkt/color-modes-docs' of github.com:primer/css into mkt…
BinaryMuse Oct 23, 2020
fd9a308
Merge remote-tracking branch 'origin/mkt/color-modes-whee' into mkt/c…
BinaryMuse Oct 23, 2020
eca4322
Make color mode toggle global
BinaryMuse Oct 26, 2020
8397fbc
Merge remote-tracking branch 'origin/mkt/color-modes-whee' into mkt/c…
BinaryMuse Oct 26, 2020
d332a33
Tweak global color mode toggle
BinaryMuse Oct 26, 2020
369ff1d
Why is this still here
BinaryMuse Oct 26, 2020
8fd49df
:fire: console.log
BinaryMuse Oct 26, 2020
d5c7f6a
Move CustomEvent to runtime only
BinaryMuse Oct 26, 2020
5711c3a
Merge branch 'mkt/color-modes-whee' into mkt/color-modes-docs
BinaryMuse Oct 26, 2020
a24bbd1
Flesh out color system, add (temporary) migration guide doc
BinaryMuse Oct 28, 2020
6e0a06d
Merge remote-tracking branch 'origin/mkt/color-modes-whee' into mkt/c…
BinaryMuse Oct 28, 2020
f41b615
Fix bad URL
BinaryMuse Oct 28, 2020
dbc1d69
Remove workflow guide
BinaryMuse Oct 29, 2020
2698079
Merge remote-tracking branch 'origin/mkt/color-modes-whee' into mkt/c…
BinaryMuse Oct 29, 2020
6da07ec
Tweaks to color system page
BinaryMuse Oct 29, 2020
b97d401
Update migration guide
BinaryMuse Oct 29, 2020
f7d9c56
Fixup links from .md file
BinaryMuse Oct 29, 2020
c4a5d72
Re-enable variable analysis
BinaryMuse Oct 29, 2020
b771edf
Update Octicon import
BinaryMuse Oct 29, 2020
5c95623
Re-enable variables page
BinaryMuse Oct 29, 2020
2a0a427
Merge remote-tracking branch 'origin/master' into mkt/color-modes-docs
BinaryMuse Nov 10, 2020
82ac274
Merge remote-tracking branch 'origin/mkt/color-modes-whee' into mkt/c…
BinaryMuse Nov 16, 2020
ed44b6e
Update link to Primer Primitives docs
BinaryMuse Nov 16, 2020
b9e538a
Remove docs that were moved to external migration guide
BinaryMuse Nov 16, 2020
a3fb1f7
Reintroduce variable parsing for border colors
BinaryMuse Nov 17, 2020
9a36754
Default to variable name when parsing vars
BinaryMuse Nov 17, 2020
7f7ca98
Update migration guide
simurai Nov 19, 2020
0826721
Merge branch 'mkt/color-modes-whee' into mkt/color-modes-docs
BinaryMuse Dec 14, 2020
728e480
Merge branch 'mkt/color-modes-whee' into mkt/color-modes-docs
BinaryMuse Dec 15, 2020
1667991
Merge branch 'mkt/color-modes-whee' into mkt/color-modes-docs
BinaryMuse Feb 5, 2021
1441170
Merge branch 'mkt/color-modes-whee' into mkt/color-modes-docs
BinaryMuse Feb 5, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
40 changes: 25 additions & 15 deletions docs/content/support/color-system.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,33 @@ bundle: support
import lightColors from '@primer/primitives/dist/js/colors/light'
import {Flash, Box, Flex, Heading, Link, StyledOcticon} from '@primer/components'
import {LinkIcon} from '@primer/octicons-react'
import {palettes} from '../../src/color-variables'
import {PaletteTable, PaletteCell, overlayColor} from '../../src/color-system'
import {colorModes, palettes, functionalVarNames, flattened} from '../../src/color-variables'
import {PaletteTable, PaletteCell, ColorModeTable, overlayColor} from '../../src/color-system'

<Flash scheme="yellow">
Note: the colors listed below are different per color mode, and should not be used directly.
Instead, use functional color names (TODO)
</Flash>
## Functional variables

The Primer color system contains multiple color modes; currently, Primer ships with a light mode and a dark mode. Each color mode comes with a set of CSS variables that can be used to style elements based on the functionality of the element. These should be used instead of specifying colors directly so that the colors adapt correctly when switching between color modes.

When at all possible, favor using [color utility classes](/utilities/colors) over using the CSS color variables.

<ColorModeTable
baseColor="#ffffff"
values={functionalVarNames.filter(v => !v.includes('shadow') && !v.includes('Shadow')).map(name => ({
variable: name,
slug: name,
values: colorModes.reduce((acc, mode) => {
acc[mode] = flattened[mode][name]
return acc
}, {})
}))}
/>

## Color palette

In rare ocassions, it may be necessary to use one of the variables from the base color scale, though since the colors differ in the various color modes, the functional variables listed above should be used in almost all normal cases.

<Flex flexWrap="wrap" mr={-2}>
{palettes
.concat(
{title: 'Black', name: 'black', value: lightColors.scale.gray[9]},
{title: 'White', name: 'white', value: lightColors.scale.white, props: {className: 'border'}}
)
.map(({name, title, value, props = {}}) => (
<Flex.Item
as={Link}
Expand All @@ -44,11 +55,11 @@ import {PaletteTable, PaletteCell, overlayColor} from '../../src/color-system'
))}
</Flex>

## Color variables
### Color variables

<Flex flexWrap="wrap" mr={[0, 0, -4]}>
{palettes.map(({name, title, value, values}) => (
<Flex id={name} flexDirection="column" width={[1, 1, 1 / 2]} pr={[0, 0, 4]} mb={4} key={name}>
<Flex id={name} flexDirection="column" width={1} pr={0} mb={4} key={name}>
<Flex
as={Link}
href={`#${name}`}
Expand All @@ -66,10 +77,9 @@ import {PaletteTable, PaletteCell, overlayColor} from '../../src/color-system'
</Flex.Item>
<StyledOcticon icon={LinkIcon} color="inherit !important" height={20} />
</Flex>
<PaletteTable
columns={['variable', 'value']}
<ColorModeTable
baseColor={value}
values={values}
hasHeader={false}
cellPadding="8px 16px"
/>
</Flex>
Expand Down
59 changes: 55 additions & 4 deletions docs/src/color-system.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,55 @@ import PropTypes from 'prop-types'
import chroma from 'chroma-js'
import styled from 'styled-components'
import {Box, Text} from '@primer/components'
import {colors, getPaletteByName} from './color-variables'
import {colors, colorModes, getPaletteByName} from './color-variables'
import Table from './table'

function capitalize(word) {
return word[0].toUpperCase() + word.substr(1)
}

export function ColorModeTable({baseColor, values, ...rest}) {
const fgColor = overlayColor(baseColor)
const colorProps = {bg: baseColor, color: fgColor}

values.forEach(({variable, values, slug}) => {
if (!values.light || !values.dark) {
console.log(variable, values)
}
})

return (
<Table {...rest}>
<thead>
<tr>
<PaletteCell as="th" {...colorProps}>
Variable
</PaletteCell>
{colorModes.map(mode => (
<PaletteCell as="th" {...colorProps} key={mode}>
{capitalize(mode)} Mode
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to self: move capitalize to CSS

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this make state-hoverPrimaryBg into state-hover-primary-bg? That would be nice for copy&pasta.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used the kebabCase function from lodash to convert hoverPrimerBg to hover-primer-bg in https://primer.style/primitives

</PaletteCell>
))}
</tr>
</thead>
<tbody>
{values.map(({variable, slug, values}) => (
<tr key={slug}>
<PaletteCell {...colorProps}>
<Var>{variable}</Var>
</PaletteCell>
{Object.keys(values).map(mode => (
<PaletteCell key={mode} bg={values[mode]} color={overlayColor(values[mode])}>
<Var>{values[mode]}</Var>
</PaletteCell>
))}
</tr>
))}
</tbody>
</Table>
)
}

export function PaletteTable(props) {
const {columns = [], hasHeader, ...rest} = props
const {children = <PaletteTableFragment columns={columns} {...rest} />} = rest
Expand Down Expand Up @@ -212,9 +258,14 @@ export function overlayColor(bg) {
if ($overlayColorCache.has(bg)) {
return $overlayColorCache.get(bg)
} else {
const result = chroma(bg).luminance() > 0.5 ? colors.black : colors.white
$overlayColorCache.set(bg, result)
return result
try {
const result = chroma(bg).luminance() > 0.5 ? colors.black : colors.white
$overlayColorCache.set(bg, result)
return result
} catch (err) {
console.log('error with value', bg)
return 'white'
}
}
}

Expand Down
49 changes: 46 additions & 3 deletions docs/src/color-variables.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import titleCase from 'title-case'
import lightModeColors from '@primer/primitives/dist/js/colors/light'
import allModeColors from '@primer/primitives/dist/js/colors'

// XXX we don't necessarily define them in this order in primer-colors,
// so we define an array here just to be safe
const gradientHues = ['gray', 'blue', 'green', 'purple', 'yellow', 'orange', 'red', 'pink']

const colors = lightModeColors.scale
const colors = allModeColors.light.scale

const colorModes = Object.keys(allModeColors).sort((a, b) => {
if (a.startsWith('light') && !b.startsWith('light')) return -1
if (!a.startsWith('light') && b.startsWith('light')) return 1
else return a.localeCompare(b)
})

const palettes = gradientHues.map(name => {
return {
Expand All @@ -14,6 +20,10 @@ const palettes = gradientHues.map(name => {
value: colors[name][5],
values: colors[name].map((value, index) => ({
value,
values: colorModes.reduce((acc, mode) => {
acc[mode] = allModeColors[mode].scale[name][index]
return acc
}, {}),
index,
variable: `--color-scale-${name}-${index}`,
slug: `color-scale-${name}-${index}`,
Expand All @@ -22,7 +32,16 @@ const palettes = gradientHues.map(name => {
}
})

export {colors, gradientHues, palettes, getPaletteByName}
export {colors, colorModes, gradientHues, palettes, getPaletteByName}

export const flattened = colorModes.reduce((acc, mode) => {
acc[mode] = flattenVars(allModeColors[mode])
return acc
}, {})

export const functionalVarNames = Object.keys(flattened.light).filter(
v => !v.startsWith('scale-') && !v.startsWith('auto-')
)

export const allColors = palettes.reduce((all, {values}) => all.concat(values), [])

Expand All @@ -41,3 +60,27 @@ export const allColors = palettes.reduce((all, {values}) => all.concat(values),
function getPaletteByName(name) {
return palettes.find(palette => palette.name === name)
}

function flattenVars(tree, prefix = []) {
let output = {}

for (const key of Object.keys(tree)) {
const val = tree[key]
const varName = [...prefix, key].join('-')
if (Array.isArray(val) && !varName.includes('shadow')) {
for (const i in val) {
const arrayVarName = `${varName}-${i}`
output[arrayVarName] = val[i]
}
} else if (Array.isArray(val)) {
output[varName] = val.join(' ')
} else if (typeof val === 'object') {
const obj = flattenVars(val, [...prefix, key])
output = {...output, ...obj}
} else {
output[varName] = val
}
}

return output
}