Files
oak-gpui/styles/src/themes/common/base16.ts
T
2022-05-25 10:57:10 -04:00

249 lines
7.2 KiB
TypeScript

import chroma, { Color, Scale } from "chroma-js";
import { color, ColorToken, fontWeights, NumberToken } from "../../tokens";
import { withOpacity } from "../../utils/color";
import Theme, { buildPlayer, Syntax } from "./theme";
export function colorRamp(color: Color): Scale {
let hue = color.hsl()[0];
let endColor = chroma.hsl(hue, 0.88, 0.96);
let startColor = chroma.hsl(hue, 0.68, 0.12);
return chroma.scale([startColor, color, endColor]).mode("hsl");
}
export function createTheme(
name: string,
isLight: boolean,
ramps: { [rampName: string]: Scale },
blend?: number
): Theme {
if (isLight) {
for (var rampName in ramps) {
ramps[rampName] = ramps[rampName].domain([1, 0]);
}
ramps.neutral = ramps.neutral.domain([7, 0]);
} else {
ramps.neutral = ramps.neutral.domain([0, 7]);
}
if (blend === undefined) {
blend = isLight ? 0.12 : 0.24;
}
function rampColor(ramp: Scale, index: number): ColorToken {
return color(ramp(index).hex());
}
const backgroundColor = {
// Title bar
100: {
base: rampColor(ramps.neutral, 1.25),
hovered: rampColor(ramps.neutral, 1.5),
active: rampColor(ramps.neutral, 1.75),
},
// Midground (panels, etc)
300: {
base: rampColor(ramps.neutral, 1),
hovered: rampColor(ramps.neutral, 1.25),
active: rampColor(ramps.neutral, 1.5),
},
// Editor
500: {
base: rampColor(ramps.neutral, 0),
hovered: rampColor(ramps.neutral, 0.25),
active: rampColor(ramps.neutral, 0.5),
},
on300: {
base: rampColor(ramps.neutral, 0),
hovered: rampColor(ramps.neutral, 0.25),
active: rampColor(ramps.neutral, 0.5),
},
on500: {
base: rampColor(ramps.neutral, 1.25),
hovered: rampColor(ramps.neutral, 1.5),
active: rampColor(ramps.neutral, 1.75),
},
ok: {
base: withOpacity(rampColor(ramps.green, 0.5), 0.15),
hovered: withOpacity(rampColor(ramps.green, 0.5), 0.2),
active: withOpacity(rampColor(ramps.green, 0.5), 0.25),
},
error: {
base: withOpacity(rampColor(ramps.red, 0.5), 0.15),
hovered: withOpacity(rampColor(ramps.red, 0.5), 0.2),
active: withOpacity(rampColor(ramps.red, 0.5), 0.25),
},
warning: {
base: withOpacity(rampColor(ramps.yellow, 0.5), 0.15),
hovered: withOpacity(rampColor(ramps.yellow, 0.5), 0.2),
active: withOpacity(rampColor(ramps.yellow, 0.5), 0.25),
},
info: {
base: withOpacity(rampColor(ramps.blue, 0.5), 0.15),
hovered: withOpacity(rampColor(ramps.blue, 0.5), 0.2),
active: withOpacity(rampColor(ramps.blue, 0.5), 0.25),
},
};
const borderColor = {
primary: rampColor(ramps.neutral, isLight ? 1.5 : 0),
secondary: rampColor(ramps.neutral, isLight ? 1.25 : 1),
muted: rampColor(ramps.neutral, isLight ? 1 : 3),
active: rampColor(ramps.neutral, isLight ? 4 : 3),
onMedia: withOpacity(rampColor(ramps.neutral, 0), 0.1),
ok: withOpacity(rampColor(ramps.green, 0.5), 0.15),
error: withOpacity(rampColor(ramps.red, 0.5), 0.15),
warning: withOpacity(rampColor(ramps.yellow, 0.5), 0.15),
info: withOpacity(rampColor(ramps.blue, 0.5), 0.15),
};
const textColor = {
primary: rampColor(ramps.neutral, 6),
secondary: rampColor(ramps.neutral, 5),
muted: rampColor(ramps.neutral, 5),
placeholder: rampColor(ramps.neutral, 4),
active: rampColor(ramps.neutral, 7),
feature: rampColor(ramps.blue, 0.5),
ok: rampColor(ramps.green, 0.5),
error: rampColor(ramps.red, 0.5),
warning: rampColor(ramps.yellow, 0.5),
info: rampColor(ramps.blue, 0.5),
onMedia: rampColor(ramps.neutral, isLight ? 0 : 7),
};
const player = {
1: buildPlayer(rampColor(ramps.blue, 0.5)),
2: buildPlayer(rampColor(ramps.green, 0.5)),
3: buildPlayer(rampColor(ramps.magenta, 0.5)),
4: buildPlayer(rampColor(ramps.orange, 0.5)),
5: buildPlayer(rampColor(ramps.violet, 0.5)),
6: buildPlayer(rampColor(ramps.cyan, 0.5)),
7: buildPlayer(rampColor(ramps.red, 0.5)),
8: buildPlayer(rampColor(ramps.yellow, 0.5)),
};
const editor = {
background: backgroundColor[500].base,
indent_guide: borderColor.muted,
indent_guide_active: borderColor.secondary,
line: {
active: rampColor(ramps.neutral, 1),
highlighted: rampColor(ramps.neutral, 1.25), // TODO: Where is this used?
},
highlight: {
selection: player[1].selectionColor,
occurrence: withOpacity(rampColor(ramps.neutral, 3.5), blend),
activeOccurrence: withOpacity(rampColor(ramps.neutral, 3.5), blend * 2), // TODO: Not hooked up - https://github.com/zed-industries/zed/issues/751
matchingBracket: backgroundColor[500].active, // TODO: Not hooked up
match: rampColor(ramps.violet, 0.15),
activeMatch: withOpacity(rampColor(ramps.violet, 0.4), blend * 2), // TODO: Not hooked up - https://github.com/zed-industries/zed/issues/751
related: backgroundColor[500].hovered,
},
gutter: {
primary: textColor.placeholder,
active: textColor.active,
},
};
const syntax: Syntax = {
primary: {
color: rampColor(ramps.neutral, 7),
weight: fontWeights.normal,
},
comment: {
color: rampColor(ramps.neutral, 5),
weight: fontWeights.normal,
},
punctuation: {
color: rampColor(ramps.neutral, 6),
weight: fontWeights.normal,
},
constant: {
color: rampColor(ramps.neutral, 4),
weight: fontWeights.normal,
},
keyword: {
color: rampColor(ramps.blue, 0.5),
weight: fontWeights.normal,
},
function: {
color: rampColor(ramps.yellow, 0.5),
weight: fontWeights.normal,
},
type: {
color: rampColor(ramps.cyan, 0.5),
weight: fontWeights.normal,
},
variant: {
color: rampColor(ramps.blue, 0.5),
weight: fontWeights.normal,
},
property: {
color: rampColor(ramps.blue, 0.5),
weight: fontWeights.normal,
},
enum: {
color: rampColor(ramps.orange, 0.5),
weight: fontWeights.normal,
},
operator: {
color: rampColor(ramps.orange, 0.5),
weight: fontWeights.normal,
},
string: {
color: rampColor(ramps.orange, 0.5),
weight: fontWeights.normal,
},
number: {
color: rampColor(ramps.green, 0.5),
weight: fontWeights.normal,
},
boolean: {
color: rampColor(ramps.green, 0.5),
weight: fontWeights.normal,
},
predictive: {
color: textColor.muted,
weight: fontWeights.normal,
},
title: {
color: rampColor(ramps.yellow, 0.5),
weight: fontWeights.bold,
},
emphasis: {
color: textColor.feature,
weight: fontWeights.normal,
},
"emphasis.strong": {
color: textColor.feature,
weight: fontWeights.bold,
},
linkUri: {
color: rampColor(ramps.green, 0.5),
weight: fontWeights.normal,
underline: true,
},
linkText: {
color: rampColor(ramps.orange, 0.5),
weight: fontWeights.normal,
italic: true,
},
};
const shadowAlpha: NumberToken = {
value: blend,
type: "number",
};
return {
name,
backgroundColor,
borderColor,
textColor,
iconColor: textColor,
editor,
syntax,
player,
shadowAlpha,
};
}