flattened layers and elevations

This commit is contained in:
K Simmons 2022-10-19 13:02:51 -07:00
parent 0d9eecd2ed
commit e3809c267d
26 changed files with 203 additions and 398 deletions

16
Cargo.lock generated
View file

@ -855,22 +855,6 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chat_panel"
version = "0.1.0"
dependencies = [
"client",
"editor",
"gpui",
"menu",
"postage",
"settings",
"theme",
"time 0.3.15",
"util",
"workspace",
]
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.22" version = "0.4.22"

View file

@ -797,22 +797,16 @@ pub struct ColorScheme {
pub name: String, pub name: String,
pub is_light: bool, pub is_light: bool,
pub lowest: Elevation,
pub middle: Elevation,
pub highest: Elevation,
pub players: Vec<Player>,
}
#[derive(Clone, Deserialize, Default)]
pub struct Elevation {
pub ramps: RampSet, pub ramps: RampSet,
pub bottom: Layer, pub lowest: Layer,
pub middle: Layer, pub middle: Layer,
pub top: Layer, pub highest: Layer,
pub shadow: Option<Shadow>, pub popover_shadow: Shadow,
pub modal_shadow: Shadow,
pub players: Vec<Player>,
} }
#[derive(Clone, Deserialize, Default)] #[derive(Clone, Deserialize, Default)]

View file

@ -11,7 +11,7 @@ use gpui::{
use project::{Project, ProjectEntryId, ProjectPath}; use project::{Project, ProjectEntryId, ProjectPath};
use settings::Settings; use settings::Settings;
use smallvec::SmallVec; use smallvec::SmallVec;
use theme::{ColorScheme, Elevation, Layer, Style, StyleSet}; use theme::{ColorScheme, Layer, Style, StyleSet};
use workspace::{Item, Workspace}; use workspace::{Item, Workspace};
actions!(theme, [DeployThemeTestbench]); actions!(theme, [DeployThemeTestbench]);
@ -51,38 +51,15 @@ impl ThemeTestbench {
} }
Flex::column() Flex::column()
.with_child(display_ramp(&color_scheme.lowest.ramps.neutral)) .with_child(display_ramp(&color_scheme.ramps.neutral))
.with_child(display_ramp(&color_scheme.lowest.ramps.red)) .with_child(display_ramp(&color_scheme.ramps.red))
.with_child(display_ramp(&color_scheme.lowest.ramps.orange)) .with_child(display_ramp(&color_scheme.ramps.orange))
.with_child(display_ramp(&color_scheme.lowest.ramps.yellow)) .with_child(display_ramp(&color_scheme.ramps.yellow))
.with_child(display_ramp(&color_scheme.lowest.ramps.green)) .with_child(display_ramp(&color_scheme.ramps.green))
.with_child(display_ramp(&color_scheme.lowest.ramps.cyan)) .with_child(display_ramp(&color_scheme.ramps.cyan))
.with_child(display_ramp(&color_scheme.lowest.ramps.blue)) .with_child(display_ramp(&color_scheme.ramps.blue))
.with_child(display_ramp(&color_scheme.lowest.ramps.violet)) .with_child(display_ramp(&color_scheme.ramps.violet))
.with_child(display_ramp(&color_scheme.lowest.ramps.magenta)) .with_child(display_ramp(&color_scheme.ramps.magenta))
}
fn render_elevation(
elevation_index: usize,
elevation: &Elevation,
cx: &mut RenderContext<'_, Self>,
) -> Flex {
Flex::column()
.with_child(
Self::render_layer(elevation_index * 1000 + 100, &elevation.bottom, cx)
.flex(1., true)
.boxed(),
)
.with_child(
Self::render_layer(elevation_index * 1000 + 200, &elevation.middle, cx)
.flex(1., true)
.boxed(),
)
.with_child(
Self::render_layer(elevation_index * 1000 + 300, &elevation.top, cx)
.flex(1., true)
.boxed(),
)
} }
fn render_layer( fn render_layer(
@ -272,44 +249,6 @@ impl ThemeTestbench {
Label::new(text, text_style) Label::new(text, text_style)
} }
fn elevation_style(elevation: &Elevation) -> ContainerStyle {
let style = ContainerStyle {
margin: Margin {
top: 10.,
bottom: 10.,
left: 10.,
right: 10.,
},
background_color: Some(elevation.bottom.base.default.background),
..Default::default()
};
if elevation.shadow.is_some() {
ContainerStyle {
padding: Padding {
top: 10.,
bottom: 10.,
left: 10.,
right: 10.,
},
border: Border {
width: 1.,
color: elevation.bottom.base.default.border,
overlay: false,
top: true,
bottom: true,
left: true,
right: true,
},
corner_radius: 32.,
shadow: elevation.shadow,
..style
}
} else {
style
}
}
} }
impl Entity for ThemeTestbench { impl Entity for ThemeTestbench {
@ -333,32 +272,24 @@ impl View for ThemeTestbench {
.boxed(), .boxed(),
) )
.with_child( .with_child(
Self::render_elevation(0, &color_scheme.lowest, cx) Flex::column()
.flex(1., true)
.boxed(),
)
.with_child(
Flex::row()
.with_child( .with_child(
Self::render_elevation(1, &color_scheme.middle, cx) Self::render_layer(100, &color_scheme.lowest, cx)
.flex(1., true) .flex(1., true)
.boxed(), .boxed(),
) )
.with_child( .with_child(
Container::new( Self::render_layer(200, &color_scheme.middle, cx)
Self::render_elevation(2, &color_scheme.highest, cx).boxed(), .flex(1., true)
) .boxed(),
.with_style(Self::elevation_style(&color_scheme.highest)) )
.flex(1., true) .with_child(
.boxed(), Self::render_layer(300, &color_scheme.highest, cx)
.flex(1., true)
.boxed(),
) )
.contained()
.with_style(Self::elevation_style(&color_scheme.middle))
.flex(2., true)
.boxed(), .boxed(),
) )
.contained()
.with_style(Self::elevation_style(&color_scheme.lowest))
.boxed() .boxed()
} }
} }

View file

@ -18,10 +18,6 @@ import contactList from "./contactList";
import incomingCallNotification from "./incomingCallNotification"; import incomingCallNotification from "./incomingCallNotification";
import { ColorScheme } from "../themes/common/colorScheme"; import { ColorScheme } from "../themes/common/colorScheme";
// export const panel = {
// padding: { top: 12, bottom: 12 },
// };
export default function app(colorScheme: ColorScheme): Object { export default function app(colorScheme: ColorScheme): Object {
return { return {
meta: { meta: {
@ -43,68 +39,28 @@ export default function app(colorScheme: ColorScheme): Object {
contactList: contactList(colorScheme), contactList: contactList(colorScheme),
search: search(colorScheme), search: search(colorScheme),
breadcrumbs: { breadcrumbs: {
...text(colorScheme.lowest.top, "sans", "variant"), ...text(colorScheme.highest, "sans", "variant"),
padding: { padding: {
left: 6, left: 6,
}, },
}, },
updateNotification: updateNotification(colorScheme), updateNotification: updateNotification(colorScheme),
tooltip: tooltip(colorScheme), tooltip: tooltip(colorScheme),
terminal: terminal(colorScheme.lowest, colorScheme.players[0].cursor), terminal: terminal(colorScheme),
colorScheme: { colorScheme: {
...colorScheme, ...colorScheme,
lowest: { players: Object.values(colorScheme.players),
...colorScheme.lowest, ramps: {
ramps: { neutral: colorScheme.ramps.neutral.colors(100, "hex"),
neutral: colorScheme.lowest.ramps.neutral.colors(100, "hex"), red: colorScheme.ramps.red.colors(100, "hex"),
red: colorScheme.lowest.ramps.red.colors(100, "hex"), orange: colorScheme.ramps.orange.colors(100, "hex"),
orange: colorScheme.lowest.ramps.orange.colors(100, "hex"), yellow: colorScheme.ramps.yellow.colors(100, "hex"),
yellow: colorScheme.lowest.ramps.yellow.colors(100, "hex"), green: colorScheme.ramps.green.colors(100, "hex"),
green: colorScheme.lowest.ramps.green.colors(100, "hex"), cyan: colorScheme.ramps.cyan.colors(100, "hex"),
cyan: colorScheme.lowest.ramps.cyan.colors(100, "hex"), blue: colorScheme.ramps.blue.colors(100, "hex"),
blue: colorScheme.lowest.ramps.blue.colors(100, "hex"), violet: colorScheme.ramps.violet.colors(100, "hex"),
violet: colorScheme.lowest.ramps.violet.colors(100, "hex"), magenta: colorScheme.ramps.magenta.colors(100, "hex"),
magenta: colorScheme.lowest.ramps.magenta.colors(100, "hex"),
},
}, },
middle: {
...colorScheme.middle,
ramps: {
neutral: colorScheme.middle.ramps.neutral.colors(100, "hex"),
red: colorScheme.middle.ramps.red.colors(100, "hex"),
orange: colorScheme.middle.ramps.orange.colors(100, "hex"),
yellow: colorScheme.middle.ramps.yellow.colors(100, "hex"),
green: colorScheme.middle.ramps.green.colors(100, "hex"),
cyan: colorScheme.middle.ramps.cyan.colors(100, "hex"),
blue: colorScheme.middle.ramps.blue.colors(100, "hex"),
violet: colorScheme.middle.ramps.violet.colors(100, "hex"),
magenta: colorScheme.middle.ramps.magenta.colors(100, "hex"),
},
},
highest: {
...colorScheme.highest,
ramps: {
neutral: colorScheme.highest.ramps.neutral.colors(100, "hex"),
red: colorScheme.highest.ramps.red.colors(100, "hex"),
orange: colorScheme.highest.ramps.orange.colors(100, "hex"),
yellow: colorScheme.highest.ramps.yellow.colors(100, "hex"),
green: colorScheme.highest.ramps.green.colors(100, "hex"),
cyan: colorScheme.highest.ramps.cyan.colors(100, "hex"),
blue: colorScheme.highest.ramps.blue.colors(100, "hex"),
violet: colorScheme.highest.ramps.violet.colors(100, "hex"),
magenta: colorScheme.highest.ramps.magenta.colors(100, "hex"),
},
},
players: [
colorScheme.players["0"],
colorScheme.players["1"],
colorScheme.players["2"],
colorScheme.players["3"],
colorScheme.players["4"],
colorScheme.players["5"],
colorScheme.players["6"],
colorScheme.players["7"],
],
}, },
}; };
} }

View file

@ -3,7 +3,7 @@ import { withOpacity } from "../utils/color";
import { text, background } from "./components"; import { text, background } from "./components";
export default function commandPalette(colorScheme: ColorScheme) { export default function commandPalette(colorScheme: ColorScheme) {
let layer = colorScheme.highest.top; let layer = colorScheme.highest;
return { return {
keystrokeSpacing: 8, keystrokeSpacing: 8,
key: { key: {

View file

@ -3,7 +3,7 @@ import { ColorScheme } from "../themes/common/colorScheme";
import { background, border, foreground, text } from "./components"; import { background, border, foreground, text } from "./components";
export default function contactFinder(colorScheme: ColorScheme) { export default function contactFinder(colorScheme: ColorScheme) {
let layer = colorScheme.highest.top; let layer = colorScheme.highest;
const sideMargin = 6; const sideMargin = 6;
const contactButton = { const contactButton = {

View file

@ -11,7 +11,7 @@ export default function contactsPanel(colorScheme: ColorScheme) {
const nameMargin = 8; const nameMargin = 8;
const sidePadding = 12; const sidePadding = 12;
let layer = colorScheme.lowest.middle; let layer = colorScheme.middle;
const contactButton = { const contactButton = {
background: background(layer, "on"), background: background(layer, "on"),

View file

@ -5,7 +5,7 @@ const avatarSize = 12;
const headerPadding = 8; const headerPadding = 8;
export default function contactNotification(colorScheme: ColorScheme): Object { export default function contactNotification(colorScheme: ColorScheme): Object {
let layer = colorScheme.middle.bottom; let layer = colorScheme.lowest;
return { return {
headerAvatar: { headerAvatar: {
height: avatarSize, height: avatarSize,

View file

@ -2,14 +2,14 @@ import { ColorScheme } from "../themes/common/colorScheme";
import { background, border, text } from "./components"; import { background, border, text } from "./components";
export default function contactsPopover(colorScheme: ColorScheme) { export default function contactsPopover(colorScheme: ColorScheme) {
let layer = colorScheme.middle.middle; let layer = colorScheme.middle;
const sidePadding = 12; const sidePadding = 12;
return { return {
background: background(layer), background: background(layer),
cornerRadius: 6, cornerRadius: 6,
padding: { top: 6 }, padding: { top: 6 },
margin: { top: -6 }, margin: { top: -6 },
shadow: colorScheme.middle.shadow, shadow: colorScheme.popoverShadow,
border: border(layer), border: border(layer),
width: 300, width: 300,
height: 400, height: 400,

View file

@ -2,13 +2,12 @@ import { ColorScheme } from "../themes/common/colorScheme";
import { background, border, borderColor, text } from "./components"; import { background, border, borderColor, text } from "./components";
export default function contextMenu(colorScheme: ColorScheme) { export default function contextMenu(colorScheme: ColorScheme) {
let elevation = colorScheme.middle; let layer = colorScheme.lowest;
let layer = elevation.bottom;
return { return {
background: background(layer), background: background(layer),
cornerRadius: 10, cornerRadius: 10,
padding: 4, padding: 4,
shadow: elevation.shadow, shadow: colorScheme.popoverShadow,
border: border(layer), border: border(layer),
keystrokeMargin: 30, keystrokeMargin: 30,
item: { item: {

View file

@ -15,8 +15,7 @@ import {
import hoverPopover from "./hoverPopover"; import hoverPopover from "./hoverPopover";
export default function editor(colorScheme: ColorScheme) { export default function editor(colorScheme: ColorScheme) {
let elevation = colorScheme.lowest; let layer = colorScheme.highest;
let layer = elevation.top;
const autocompleteItem = { const autocompleteItem = {
cornerRadius: 6, cornerRadius: 6,
@ -48,88 +47,88 @@ export default function editor(colorScheme: ColorScheme) {
const syntax = { const syntax = {
primary: { primary: {
color: elevation.ramps.neutral(1).hex(), color: colorScheme.ramps.neutral(1).hex(),
weight: fontWeights.normal, weight: fontWeights.normal,
}, },
comment: { comment: {
color: elevation.ramps.neutral(0.71).hex(), color: colorScheme.ramps.neutral(0.71).hex(),
weight: fontWeights.normal, weight: fontWeights.normal,
}, },
punctuation: { punctuation: {
color: elevation.ramps.neutral(0.86).hex(), color: colorScheme.ramps.neutral(0.86).hex(),
weight: fontWeights.normal, weight: fontWeights.normal,
}, },
constant: { constant: {
color: elevation.ramps.green(0.5).hex(), color: colorScheme.ramps.green(0.5).hex(),
weight: fontWeights.normal, weight: fontWeights.normal,
}, },
keyword: { keyword: {
color: elevation.ramps.blue(0.5).hex(), color: colorScheme.ramps.blue(0.5).hex(),
weight: fontWeights.normal, weight: fontWeights.normal,
}, },
function: { function: {
color: elevation.ramps.yellow(0.5).hex(), color: colorScheme.ramps.yellow(0.5).hex(),
weight: fontWeights.normal, weight: fontWeights.normal,
}, },
type: { type: {
color: elevation.ramps.cyan(0.5).hex(), color: colorScheme.ramps.cyan(0.5).hex(),
weight: fontWeights.normal, weight: fontWeights.normal,
}, },
constructor: { constructor: {
color: elevation.ramps.blue(0.5).hex(), color: colorScheme.ramps.blue(0.5).hex(),
weight: fontWeights.normal, weight: fontWeights.normal,
}, },
variant: { variant: {
color: elevation.ramps.blue(0.5).hex(), color: colorScheme.ramps.blue(0.5).hex(),
weight: fontWeights.normal, weight: fontWeights.normal,
}, },
property: { property: {
color: elevation.ramps.blue(0.5).hex(), color: colorScheme.ramps.blue(0.5).hex(),
weight: fontWeights.normal, weight: fontWeights.normal,
}, },
enum: { enum: {
color: elevation.ramps.orange(0.5).hex(), color: colorScheme.ramps.orange(0.5).hex(),
weight: fontWeights.normal, weight: fontWeights.normal,
}, },
operator: { operator: {
color: elevation.ramps.orange(0.5).hex(), color: colorScheme.ramps.orange(0.5).hex(),
weight: fontWeights.normal, weight: fontWeights.normal,
}, },
string: { string: {
color: elevation.ramps.orange(0.5).hex(), color: colorScheme.ramps.orange(0.5).hex(),
weight: fontWeights.normal, weight: fontWeights.normal,
}, },
number: { number: {
color: elevation.ramps.green(0.5).hex(), color: colorScheme.ramps.green(0.5).hex(),
weight: fontWeights.normal, weight: fontWeights.normal,
}, },
boolean: { boolean: {
color: elevation.ramps.green(0.5).hex(), color: colorScheme.ramps.green(0.5).hex(),
weight: fontWeights.normal, weight: fontWeights.normal,
}, },
predictive: { predictive: {
color: elevation.ramps.neutral(0.57).hex(), color: colorScheme.ramps.neutral(0.57).hex(),
weight: fontWeights.normal, weight: fontWeights.normal,
}, },
title: { title: {
color: elevation.ramps.yellow(0.5).hex(), color: colorScheme.ramps.yellow(0.5).hex(),
weight: fontWeights.bold, weight: fontWeights.bold,
}, },
emphasis: { emphasis: {
color: elevation.ramps.blue(0.5).hex(), color: colorScheme.ramps.blue(0.5).hex(),
weight: fontWeights.normal, weight: fontWeights.normal,
}, },
"emphasis.strong": { "emphasis.strong": {
color: elevation.ramps.blue(0.5).hex(), color: colorScheme.ramps.blue(0.5).hex(),
weight: fontWeights.bold, weight: fontWeights.bold,
}, },
linkUri: { linkUri: {
color: elevation.ramps.green(0.5).hex(), color: colorScheme.ramps.green(0.5).hex(),
weight: fontWeights.normal, weight: fontWeights.normal,
underline: true, underline: true,
}, },
linkText: { linkText: {
color: elevation.ramps.orange(0.5).hex(), color: colorScheme.ramps.orange(0.5).hex(),
weight: fontWeights.normal, weight: fontWeights.normal,
italic: true, italic: true,
}, },
@ -152,11 +151,11 @@ export default function editor(colorScheme: ColorScheme) {
widthEm: 0.16, widthEm: 0.16,
cornerRadius: 0.05, cornerRadius: 0.05,
}, },
documentHighlightReadBackground: elevation.ramps documentHighlightReadBackground: colorScheme.ramps
.neutral(0.5) .neutral(0.5)
.alpha(0.2) .alpha(0.2)
.hex(), // TODO: This was blend .hex(), // TODO: This was blend
documentHighlightWriteBackground: elevation.ramps documentHighlightWriteBackground: colorScheme.ramps
.neutral(0.5) .neutral(0.5)
.alpha(0.4) .alpha(0.4)
.hex(), // TODO: This was blend * 2 .hex(), // TODO: This was blend * 2
@ -178,67 +177,69 @@ export default function editor(colorScheme: ColorScheme) {
colorScheme.players[7], colorScheme.players[7],
], ],
autocomplete: { autocomplete: {
background: background(elevation.bottom), background: background(colorScheme.lowest),
cornerRadius: 8, cornerRadius: 8,
padding: 4, padding: 4,
margin: { margin: {
left: -14, left: -14,
}, },
border: border(elevation.bottom), border: border(colorScheme.lowest),
shadow: elevation.above.shadow, shadow: colorScheme.popoverShadow,
matchHighlight: elevation.above.ramps.blue(0.5).hex(), matchHighlight: foreground(colorScheme.lowest, "accent"),
item: autocompleteItem, item: autocompleteItem,
hoveredItem: { hoveredItem: {
...autocompleteItem, ...autocompleteItem,
background: background(elevation.bottom, "hovered"), matchHighlight: foreground(colorScheme.lowest, "accent", "hovered"),
background: background(colorScheme.lowest, "hovered"),
}, },
selectedItem: { selectedItem: {
...autocompleteItem, ...autocompleteItem,
background: background(elevation.bottom, "active"), matchHighlight: foreground(colorScheme.lowest, "accent", "active"),
background: background(colorScheme.lowest, "active"),
}, },
}, },
diagnosticHeader: { diagnosticHeader: {
background: background(elevation.middle), background: background(colorScheme.middle),
iconWidthFactor: 1.5, iconWidthFactor: 1.5,
textScaleFactor: 0.857, textScaleFactor: 0.857,
border: border(elevation.middle, { border: border(colorScheme.middle, {
bottom: true, bottom: true,
top: true, top: true,
}), }),
code: { code: {
...text(elevation.middle, "mono", { size: "sm" }), ...text(colorScheme.middle, "mono", { size: "sm" }),
margin: { margin: {
left: 10, left: 10,
}, },
}, },
message: { message: {
highlightText: text(elevation.middle, "sans", { highlightText: text(colorScheme.middle, "sans", {
size: "sm", size: "sm",
weight: "bold", weight: "bold",
}), }),
text: text(elevation.middle, "sans", { size: "sm" }), text: text(colorScheme.middle, "sans", { size: "sm" }),
}, },
}, },
diagnosticPathHeader: { diagnosticPathHeader: {
background: background(elevation.middle), background: background(colorScheme.middle),
textScaleFactor: 0.857, textScaleFactor: 0.857,
filename: text(elevation.middle, "mono", { size: "sm" }), filename: text(colorScheme.middle, "mono", { size: "sm" }),
path: { path: {
...text(elevation.middle, "mono", { size: "sm" }), ...text(colorScheme.middle, "mono", { size: "sm" }),
margin: { margin: {
left: 12, left: 12,
}, },
}, },
}, },
errorDiagnostic: diagnostic(elevation.middle, "negative"), errorDiagnostic: diagnostic(colorScheme.middle, "negative"),
warningDiagnostic: diagnostic(elevation.middle, "warning"), warningDiagnostic: diagnostic(colorScheme.middle, "warning"),
informationDiagnostic: diagnostic(elevation.middle, "accent"), informationDiagnostic: diagnostic(colorScheme.middle, "accent"),
hintDiagnostic: diagnostic(elevation.middle, "warning"), hintDiagnostic: diagnostic(colorScheme.middle, "warning"),
invalidErrorDiagnostic: diagnostic(elevation.middle, "base"), invalidErrorDiagnostic: diagnostic(colorScheme.middle, "base"),
invalidHintDiagnostic: diagnostic(elevation.middle, "base"), invalidHintDiagnostic: diagnostic(colorScheme.middle, "base"),
invalidInformationDiagnostic: diagnostic(elevation.middle, "base"), invalidInformationDiagnostic: diagnostic(colorScheme.middle, "base"),
invalidWarningDiagnostic: diagnostic(elevation.middle, "base"), invalidWarningDiagnostic: diagnostic(colorScheme.middle, "base"),
hoverPopover: hoverPopover(elevation.above), hoverPopover: hoverPopover(colorScheme),
linkDefinition: { linkDefinition: {
color: syntax.linkUri.color, color: syntax.linkUri.color,
underline: syntax.linkUri.underline, underline: syntax.linkUri.underline,

View file

@ -1,8 +1,8 @@
import { Elevation } from "../themes/common/colorScheme"; import { ColorScheme } from "../themes/common/colorScheme";
import { background, border, text } from "./components"; import { background, border, text } from "./components";
export default function HoverPopover(elevation: Elevation) { export default function HoverPopover(colorScheme: ColorScheme) {
let layer = elevation.middle; let layer = colorScheme.middle;
let baseContainer = { let baseContainer = {
background: background(layer), background: background(layer),
cornerRadius: 8, cornerRadius: 8,
@ -12,7 +12,7 @@ export default function HoverPopover(elevation: Elevation) {
top: 4, top: 4,
bottom: 4, bottom: 4,
}, },
shadow: elevation.shadow, shadow: colorScheme.popoverShadow,
border: border(layer), border: border(layer),
margin: { margin: {
left: -8, left: -8,
@ -40,6 +40,6 @@ export default function HoverPopover(elevation: Elevation) {
padding: { top: 4 }, padding: { top: 4 },
}, },
prose: text(layer, "sans", { size: "sm" }), prose: text(layer, "sans", { size: "sm" }),
highlight: elevation.ramps.neutral(0.5).alpha(0.2).hex(), // TODO: blend was used here. Replace with something better highlight: colorScheme.ramps.neutral(0.5).alpha(0.2).hex(), // TODO: blend was used here. Replace with something better
}; };
} }

View file

@ -2,7 +2,7 @@ import { ColorScheme } from "../themes/common/colorScheme";
import { background, border, text } from "./components"; import { background, border, text } from "./components";
export default function incomingCallNotification(colorScheme: ColorScheme): Object { export default function incomingCallNotification(colorScheme: ColorScheme): Object {
let layer = colorScheme.middle.middle; let layer = colorScheme.middle;
const avatarSize = 48; const avatarSize = 48;
return { return {
windowHeight: 74, windowHeight: 74,

View file

@ -2,12 +2,11 @@ import { ColorScheme } from "../themes/common/colorScheme";
import { background, border, text } from "./components"; import { background, border, text } from "./components";
export default function picker(colorScheme: ColorScheme) { export default function picker(colorScheme: ColorScheme) {
let elevation = colorScheme.highest; let layer = colorScheme.highest;
let layer = elevation.top;
return { return {
background: background(layer), background: background(layer),
border: border(layer), border: border(layer),
shadow: elevation.shadow, shadow: colorScheme.modalShadow,
cornerRadius: 12, cornerRadius: 12,
padding: { padding: {
bottom: 4, bottom: 4,

View file

@ -2,7 +2,7 @@ import { ColorScheme } from "../themes/common/colorScheme";
import { background, text } from "./components"; import { background, text } from "./components";
export default function projectDiagnostics(colorScheme: ColorScheme) { export default function projectDiagnostics(colorScheme: ColorScheme) {
let layer = colorScheme.lowest.top; let layer = colorScheme.highest;
return { return {
background: background(layer), background: background(layer),
tabIconSpacing: 4, tabIconSpacing: 4,

View file

@ -2,7 +2,7 @@ import { ColorScheme } from "../themes/common/colorScheme";
import { background, foreground, text } from "./components"; import { background, foreground, text } from "./components";
export default function projectPanel(colorScheme: ColorScheme) { export default function projectPanel(colorScheme: ColorScheme) {
let layer = colorScheme.lowest.middle; let layer = colorScheme.middle;
return { return {
background: background(layer), background: background(layer),
padding: { left: 12, right: 12, top: 6, bottom: 6 }, padding: { left: 12, right: 12, top: 6, bottom: 6 },

View file

@ -2,14 +2,13 @@ import { ColorScheme } from "../themes/common/colorScheme";
import { background, border, text } from "./components"; import { background, border, text } from "./components";
export default function projectSharedNotification(colorScheme: ColorScheme): Object { export default function projectSharedNotification(colorScheme: ColorScheme): Object {
let elevation = colorScheme.middle; let layer = colorScheme.middle;
let layer = elevation.middle;
const avatarSize = 48; const avatarSize = 48;
return { return {
windowHeight: 74, windowHeight: 74,
windowWidth: 380, windowWidth: 380,
background: background(layer,), background: background(layer),
ownerContainer: { ownerContainer: {
padding: 12, padding: 12,
}, },

View file

@ -2,7 +2,7 @@ import { ColorScheme } from "../themes/common/colorScheme";
import { background, border, text } from "./components"; import { background, border, text } from "./components";
export default function search(colorScheme: ColorScheme) { export default function search(colorScheme: ColorScheme) {
let layer = colorScheme.lowest.top; let layer = colorScheme.highest;
// Search input // Search input
const editor = { const editor = {

View file

@ -2,7 +2,7 @@ import { ColorScheme } from "../themes/common/colorScheme";
import { background, border, foreground, text } from "./components"; import { background, border, foreground, text } from "./components";
export default function statusBar(colorScheme: ColorScheme) { export default function statusBar(colorScheme: ColorScheme) {
let layer = colorScheme.lowest.bottom; let layer = colorScheme.lowest;
const statusContainer = { const statusContainer = {
cornerRadius: 6, cornerRadius: 6,

View file

@ -5,9 +5,8 @@ import { text, border, background, foreground } from "./components";
export default function tabBar(colorScheme: ColorScheme) { export default function tabBar(colorScheme: ColorScheme) {
const height = 32; const height = 32;
let elevation = colorScheme.lowest; let activeLayer = colorScheme.highest;
let activeLayer = elevation.top; let layer = colorScheme.middle;
let layer = elevation.middle;
const tab = { const tab = {
height, height,
@ -70,7 +69,7 @@ export default function tabBar(colorScheme: ColorScheme) {
...activePaneActiveTab, ...activePaneActiveTab,
background: withOpacity(tab.background, 0.95), background: withOpacity(tab.background, 0.95),
border: undefined as any, border: undefined as any,
shadow: elevation.above.shadow, shadow: colorScheme.popoverShadow,
}; };
return { return {

View file

@ -1,6 +1,6 @@
import { Elevation } from "../themes/common/colorScheme"; import { ColorScheme } from "../themes/common/colorScheme";
export default function terminal(elevation: Elevation, cursor_color: string) { export default function terminal(colorScheme: ColorScheme) {
/** /**
* Colors are controlled per-cell in the terminal grid. * Colors are controlled per-cell in the terminal grid.
* Cells can be set to any of these more 'theme-capable' colors * Cells can be set to any of these more 'theme-capable' colors
@ -9,44 +9,44 @@ export default function terminal(elevation: Elevation, cursor_color: string) {
* https://en.wikipedia.org/wiki/ANSI_escape_code#Colors * https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
*/ */
return { return {
black: elevation.ramps.neutral(0).hex(), black: colorScheme.ramps.neutral(0).hex(),
red: elevation.ramps.red(0.5).hex(), red: colorScheme.ramps.red(0.5).hex(),
green: elevation.ramps.green(0.5).hex(), green: colorScheme.ramps.green(0.5).hex(),
yellow: elevation.ramps.yellow(0.5).hex(), yellow: colorScheme.ramps.yellow(0.5).hex(),
blue: elevation.ramps.blue(0.5).hex(), blue: colorScheme.ramps.blue(0.5).hex(),
magenta: elevation.ramps.magenta(0.5).hex(), magenta: colorScheme.ramps.magenta(0.5).hex(),
cyan: elevation.ramps.cyan(0.5).hex(), cyan: colorScheme.ramps.cyan(0.5).hex(),
white: elevation.ramps.neutral(1).hex(), white: colorScheme.ramps.neutral(1).hex(),
brightBlack: elevation.ramps.neutral(0.4).hex(), brightBlack: colorScheme.ramps.neutral(0.4).hex(),
brightRed: elevation.ramps.red(0.25).hex(), brightRed: colorScheme.ramps.red(0.25).hex(),
brightGreen: elevation.ramps.green(0.25).hex(), brightGreen: colorScheme.ramps.green(0.25).hex(),
brightYellow: elevation.ramps.yellow(0.25).hex(), brightYellow: colorScheme.ramps.yellow(0.25).hex(),
brightBlue: elevation.ramps.blue(0.25).hex(), brightBlue: colorScheme.ramps.blue(0.25).hex(),
brightMagenta: elevation.ramps.magenta(0.25).hex(), brightMagenta: colorScheme.ramps.magenta(0.25).hex(),
brightCyan: elevation.ramps.cyan(0.25).hex(), brightCyan: colorScheme.ramps.cyan(0.25).hex(),
brightWhite: elevation.ramps.neutral(1).hex(), brightWhite: colorScheme.ramps.neutral(1).hex(),
/** /**
* Default color for characters * Default color for characters
*/ */
foreground: elevation.ramps.neutral(1).hex(), foreground: colorScheme.ramps.neutral(1).hex(),
/** /**
* Default color for the rectangle background of a cell * Default color for the rectangle background of a cell
*/ */
background: elevation.ramps.neutral(0).hex(), background: colorScheme.ramps.neutral(0).hex(),
modalBackground: elevation.ramps.neutral(0.1).hex(), modalBackground: colorScheme.ramps.neutral(0.1).hex(),
/** /**
* Default color for the cursor * Default color for the cursor
*/ */
cursor: cursor_color, cursor: colorScheme.players[0].cursor,
dimBlack: elevation.ramps.neutral(1).hex(), dimBlack: colorScheme.ramps.neutral(1).hex(),
dimRed: elevation.ramps.red(0.75).hex(), dimRed: colorScheme.ramps.red(0.75).hex(),
dimGreen: elevation.ramps.green(0.75).hex(), dimGreen: colorScheme.ramps.green(0.75).hex(),
dimYellow: elevation.ramps.yellow(0.75).hex(), dimYellow: colorScheme.ramps.yellow(0.75).hex(),
dimBlue: elevation.ramps.blue(0.75).hex(), dimBlue: colorScheme.ramps.blue(0.75).hex(),
dimMagenta: elevation.ramps.magenta(0.75).hex(), dimMagenta: colorScheme.ramps.magenta(0.75).hex(),
dimCyan: elevation.ramps.cyan(0.75).hex(), dimCyan: colorScheme.ramps.cyan(0.75).hex(),
dimWhite: elevation.ramps.neutral(0.6).hex(), dimWhite: colorScheme.ramps.neutral(0.6).hex(),
brightForeground: elevation.ramps.neutral(1).hex(), brightForeground: colorScheme.ramps.neutral(1).hex(),
dimForeground: elevation.ramps.neutral(0).hex(), dimForeground: colorScheme.ramps.neutral(0).hex(),
}; };
} }

View file

@ -2,14 +2,13 @@ import { ColorScheme } from "../themes/common/colorScheme";
import { background, border, text } from "./components"; import { background, border, text } from "./components";
export default function tooltip(colorScheme: ColorScheme) { export default function tooltip(colorScheme: ColorScheme) {
let elevation = colorScheme.middle; let layer = colorScheme.middle;
let layer = colorScheme.middle.middle;
return { return {
background: background(layer), background: background(layer),
border: border(layer), border: border(layer),
padding: { top: 4, bottom: 4, left: 8, right: 8 }, padding: { top: 4, bottom: 4, left: 8, right: 8 },
margin: { top: 6, left: 6 }, margin: { top: 6, left: 6 },
shadow: elevation.shadow, shadow: colorScheme.popoverShadow,
cornerRadius: 6, cornerRadius: 6,
text: text(layer, "sans", { size: "xs" }), text: text(layer, "sans", { size: "xs" }),
keystroke: { keystroke: {

View file

@ -4,7 +4,7 @@ import { foreground, text } from "./components";
const headerPadding = 8; const headerPadding = 8;
export default function updateNotification(colorScheme: ColorScheme): Object { export default function updateNotification(colorScheme: ColorScheme): Object {
let layer = colorScheme.middle.middle; let layer = colorScheme.middle;
return { return {
message: { message: {
...text(layer, "sans", { size: "xs" }), ...text(layer, "sans", { size: "xs" }),

View file

@ -11,8 +11,7 @@ import statusBar from "./statusBar";
import tabBar from "./tabBar"; import tabBar from "./tabBar";
export default function workspace(colorScheme: ColorScheme) { export default function workspace(colorScheme: ColorScheme) {
const elevation = colorScheme.lowest; const layer = colorScheme.lowest;
const layer = elevation.bottom;
const titlebarPadding = 6; const titlebarPadding = 6;
const titlebarButton = { const titlebarButton = {
cornerRadius: 6, cornerRadius: 6,
@ -28,7 +27,7 @@ export default function workspace(colorScheme: ColorScheme) {
hover: { hover: {
...text(layer, "sans", "hovered", { size: "xs" }), ...text(layer, "sans", "hovered", { size: "xs" }),
background: background(layer, "hovered"), background: background(layer, "hovered"),
border: border(elevation.top, "hovered"), border: border(layer, "hovered"),
}, },
}; };
const avatarWidth = 18; const avatarWidth = 18;
@ -44,12 +43,12 @@ export default function workspace(colorScheme: ColorScheme) {
...text(layer, "sans", { size: "lg" }), ...text(layer, "sans", { size: "lg" }),
}, },
externalLocationMessage: { externalLocationMessage: {
background: background(elevation.middle, "accent"), background: background(colorScheme.middle, "accent"),
border: border(elevation.middle, "accent"), border: border(colorScheme.middle, "accent"),
cornerRadius: 6, cornerRadius: 6,
padding: 12, padding: 12,
margin: { bottom: 8, right: 8 }, margin: { bottom: 8, right: 8 },
...text(elevation.middle, "sans", "accent", { size: "xs" }), ...text(colorScheme.middle, "sans", "accent", { size: "xs" }),
}, },
leaderBorderOpacity: 0.7, leaderBorderOpacity: 0.7,
leaderBorderWidth: 2.0, leaderBorderWidth: 2.0,
@ -166,20 +165,20 @@ export default function workspace(colorScheme: ColorScheme) {
toolbar: { toolbar: {
height: 34, height: 34,
background: background(elevation.top), background: background(colorScheme.highest),
border: border(elevation.top, { bottom: true }), border: border(colorScheme.highest, { bottom: true }),
itemSpacing: 8, itemSpacing: 8,
navButton: { navButton: {
color: foreground(elevation.top, "on"), color: foreground(colorScheme.highest, "on"),
iconWidth: 12, iconWidth: 12,
buttonWidth: 24, buttonWidth: 24,
cornerRadius: 6, cornerRadius: 6,
hover: { hover: {
color: foreground(elevation.top, "on", "hovered"), color: foreground(colorScheme.highest, "on", "hovered"),
background: background(elevation.top, "on", "hovered"), background: background(colorScheme.highest, "on", "hovered"),
}, },
disabled: { disabled: {
color: foreground(elevation.top, "on", "disabled"), color: foreground(colorScheme.highest, "on", "disabled"),
}, },
}, },
padding: { left: 8, right: 8, top: 4, bottom: 4 }, padding: { left: 8, right: 8, top: 4, bottom: 4 },
@ -194,11 +193,11 @@ export default function workspace(colorScheme: ColorScheme) {
}, },
notification: { notification: {
margin: { top: 10 }, margin: { top: 10 },
background: background(elevation.above.middle), background: background(colorScheme.middle),
cornerRadius: 6, cornerRadius: 6,
padding: 12, padding: 12,
border: border(elevation.above.middle), border: border(colorScheme.middle),
shadow: elevation.above.shadow, shadow: colorScheme.popoverShadow,
}, },
notifications: { notifications: {
width: 400, width: 400,
@ -207,14 +206,14 @@ export default function workspace(colorScheme: ColorScheme) {
dock: { dock: {
initialSizeRight: 640, initialSizeRight: 640,
initialSizeBottom: 480, initialSizeBottom: 480,
wash_color: withOpacity(background(elevation.top), 0.5), wash_color: withOpacity(background(colorScheme.highest), 0.5),
panel: { panel: {
border: border(elevation.top), border: border(colorScheme.highest),
}, },
maximized: { maximized: {
margin: 32, margin: 32,
border: border(elevation.above.top, { overlay: true }), border: border(colorScheme.highest, { overlay: true }),
shadow: elevation.above.shadow, shadow: colorScheme.modalShadow,
}, },
}, },
}; };

View file

@ -4,9 +4,14 @@ export interface ColorScheme {
name: string; name: string;
isLight: boolean; isLight: boolean;
lowest: Elevation; lowest: Layer;
middle: Elevation; middle: Layer;
highest: Elevation; highest: Layer;
ramps: RampSet;
popoverShadow: Shadow;
modalShadow: Shadow;
players: Players; players: Players;
} }
@ -27,17 +32,6 @@ export interface Players {
"7": Player; "7": Player;
} }
export interface Elevation {
ramps: RampSet;
bottom: Layer;
middle: Layer;
top: Layer;
above?: Elevation;
shadow?: Shadow;
}
export interface Shadow { export interface Shadow {
blur: number; blur: number;
color: string; color: string;

View file

@ -1,11 +1,9 @@
import chroma, { Color, Scale } from "chroma-js"; import chroma, { Color, Scale } from "chroma-js";
import { import {
ColorScheme, ColorScheme,
Elevation,
Layer, Layer,
Player, Player,
RampSet, RampSet,
Shadow,
Style, Style,
Styles, Styles,
StyleSet, StyleSet,
@ -23,7 +21,7 @@ export function createColorScheme(
colorRamps: { [rampName: string]: Scale } colorRamps: { [rampName: string]: Scale }
): ColorScheme { ): ColorScheme {
// Chromajs scales from 0 to 1 flipped if isLight is true // Chromajs scales from 0 to 1 flipped if isLight is true
let baseRamps: typeof colorRamps = {}; let ramps: RampSet = {} as any;
// Chromajs mutates the underlying ramp when you call domain. This causes problems because // Chromajs mutates the underlying ramp when you call domain. This causes problems because
// we now store the ramps object in the theme so that we can pull colors out of them. // we now store the ramps object in the theme so that we can pull colors out of them.
@ -33,73 +31,66 @@ export function createColorScheme(
// function to any in order to get the colors back out from the original ramps. // function to any in order to get the colors back out from the original ramps.
if (isLight) { if (isLight) {
for (var rampName in colorRamps) { for (var rampName in colorRamps) {
baseRamps[rampName] = chroma.scale( (ramps as any)[rampName] = chroma.scale(
colorRamps[rampName].colors(100).reverse() colorRamps[rampName].colors(100).reverse()
); );
} }
baseRamps.neutral = chroma.scale(colorRamps.neutral.colors(100).reverse()); ramps.neutral = chroma.scale(colorRamps.neutral.colors(100).reverse());
} else { } else {
for (var rampName in colorRamps) { for (var rampName in colorRamps) {
baseRamps[rampName] = chroma.scale(colorRamps[rampName].colors(100)); (ramps as any)[rampName] = chroma.scale(colorRamps[rampName].colors(100));
} }
baseRamps.neutral = chroma.scale(colorRamps.neutral.colors(100)); ramps.neutral = chroma.scale(colorRamps.neutral.colors(100));
} }
let baseSet = { let lowest = lowestLayer(ramps);
neutral: baseRamps.neutral, let middle = middleLayer(ramps);
red: baseRamps.red, let highest = highestLayer(ramps);
orange: baseRamps.orange,
yellow: baseRamps.yellow,
green: baseRamps.green,
cyan: baseRamps.cyan,
blue: baseRamps.blue,
violet: baseRamps.violet,
magenta: baseRamps.magenta,
};
let lowest = elevation(resampleSet(baseSet, evenSamples(0, 1))); let popoverShadow = {
let middle = elevation(resampleSet(baseSet, evenSamples(0.08, 1)), {
blur: 4, blur: 4,
color: baseSet color: ramps
.neutral(isLight ? 7 : 0) .neutral(isLight ? 7 : 0)
.darken() .darken()
.alpha(0.2) .alpha(0.2)
.hex(), // TODO used blend previously. Replace with something else .hex(), // TODO used blend previously. Replace with something else
offset: [1, 2], offset: [1, 2],
}); };
lowest.above = middle;
let highest = elevation(resampleSet(baseSet, evenSamples(0.16, 1)), { let modalShadow = {
blur: 16, blur: 16,
color: baseSet color: ramps
.neutral(isLight ? 7 : 0) .neutral(isLight ? 7 : 0)
.darken() .darken()
.alpha(0.2) .alpha(0.2)
.hex(), // TODO used blend previously. Replace with something else .hex(), // TODO used blend previously. Replace with something else
offset: [0, 2], offset: [0, 2],
}); };
middle.above = highest;
let players = { let players = {
"0": player(baseSet.blue), "0": player(ramps.blue),
"1": player(baseSet.green), "1": player(ramps.green),
"2": player(baseSet.magenta), "2": player(ramps.magenta),
"3": player(baseSet.orange), "3": player(ramps.orange),
"4": player(baseSet.violet), "4": player(ramps.violet),
"5": player(baseSet.cyan), "5": player(ramps.cyan),
"6": player(baseSet.red), "6": player(ramps.red),
"7": player(baseSet.yellow), "7": player(ramps.yellow),
}; };
return { return {
name, name,
isLight, isLight,
ramps,
lowest, lowest,
middle, middle,
highest, highest,
popoverShadow,
modalShadow,
players, players,
}; };
} }
@ -111,47 +102,7 @@ function player(ramp: Scale): Player {
}; };
} }
function evenSamples(min: number, max: number): number[] { function lowestLayer(ramps: RampSet): Layer {
return Array.from(Array(101).keys()).map(
(i) => (i / 100) * (max - min) + min
);
}
function resampleSet(ramps: RampSet, samples: number[]): RampSet {
return {
neutral: resample(ramps.neutral, samples),
red: resample(ramps.red, samples),
orange: resample(ramps.orange, samples),
yellow: resample(ramps.yellow, samples),
green: resample(ramps.green, samples),
cyan: resample(ramps.cyan, samples),
blue: resample(ramps.blue, samples),
violet: resample(ramps.violet, samples),
magenta: resample(ramps.magenta, samples),
};
}
function resample(scale: Scale, samples: number[]): Scale {
let newColors = samples.map((sample) => scale(sample));
return chroma.scale(newColors);
}
function elevation(
ramps: RampSet,
shadow?: Shadow
): Elevation {
return {
ramps,
bottom: bottomLayer(ramps),
middle: middleLayer(ramps),
top: topLayer(ramps),
shadow,
};
}
function bottomLayer(ramps: RampSet): Layer {
return { return {
base: buildStyleSet(ramps.neutral, 0.2, 1), base: buildStyleSet(ramps.neutral, 0.2, 1),
variant: buildStyleSet(ramps.neutral, 0.2, 0.7), variant: buildStyleSet(ramps.neutral, 0.2, 0.7),
@ -175,7 +126,7 @@ function middleLayer(ramps: RampSet): Layer {
}; };
} }
function topLayer(ramps: RampSet): Layer { function highestLayer(ramps: RampSet): Layer {
return { return {
base: buildStyleSet(ramps.neutral, 0, 1), base: buildStyleSet(ramps.neutral, 0, 1),
variant: buildStyleSet(ramps.neutral, 0, 0.7), variant: buildStyleSet(ramps.neutral, 0, 0.7),