Fix up toggles

This commit is contained in:
Piotr Osiewicz 2023-06-16 14:30:16 +02:00 committed by Mikayla Maki
parent ae53c3e623
commit 60b4054b0a
No known key found for this signature in database
16 changed files with 1670 additions and 1620 deletions

View File

@ -326,7 +326,7 @@ impl View for ActivityIndicator {
let mut element = MouseEventHandler::<Self, _>::new(0, cx, |state, cx| {
let theme = &theme::current(cx).workspace.status_bar.lsp_status;
let style = if state.hovered() && on_click.is_some() {
theme.hover.as_ref().unwrap_or(&theme.default)
theme.hovered.as_ref().unwrap_or(&theme.default)
} else {
&theme.default
};

View File

@ -186,11 +186,7 @@ impl PickerDelegate for CommandPaletteDelegate {
let command = &self.actions[mat.candidate_id];
let theme = theme::current(cx);
let style = theme.picker.item.in_state(selected).style_for(mouse_state);
let key_style = &theme
.command_palette
.key
.in_state(selected)
.style_for(mouse_state);
let key_style = &theme.command_palette.key.in_state(selected);
let keystroke_spacing = theme.command_palette.keystroke_spacing;
Flex::row()

View File

@ -498,7 +498,7 @@ pub struct ContextMenuItem {
#[derive(Debug, Deserialize, Default)]
pub struct CommandPalette {
pub key: Toggleable<Interactive<ContainedLabel>>,
pub key: Toggleable<ContainedLabel>,
pub keystroke_spacing: f32,
}
@ -805,7 +805,7 @@ pub struct DiffStyle {
#[derive(Debug, Default, Clone, Copy)]
pub struct Interactive<T> {
pub default: T,
pub hover: Option<T>,
pub hovered: Option<T>,
pub clicked: Option<T>,
pub disabled: Option<T>,
}
@ -855,7 +855,7 @@ impl<T> Interactive<T> {
if state.clicked() == Some(platform::MouseButton::Left) && self.clicked.is_some() {
self.clicked.as_ref().unwrap()
} else if state.hovered() {
self.hover.as_ref().unwrap_or(&self.default)
self.hovered.as_ref().unwrap_or(&self.default)
} else {
&self.default
}
@ -873,7 +873,7 @@ impl<'de, T: DeserializeOwned> Deserialize<'de> for Interactive<T> {
#[derive(Deserialize)]
struct Helper {
default: Value,
hover: Option<Value>,
hovered: Option<Value>,
clicked: Option<Value>,
disabled: Option<Value>,
}
@ -899,14 +899,14 @@ impl<'de, T: DeserializeOwned> Deserialize<'de> for Interactive<T> {
}
};
let hover = deserialize_state(json.hover)?;
let hovered = deserialize_state(json.hovered)?;
let clicked = deserialize_state(json.clicked)?;
let disabled = deserialize_state(json.disabled)?;
let default = serde_json::from_value(json.default).map_err(serde::de::Error::custom)?;
Ok(Interactive {
default,
hover,
hovered,
clicked,
disabled,
})

View File

@ -1,28 +1,29 @@
import merge from "ts-deepmerge"
import { DeepPartial } from "utility-types"
type InteractiveState =
| "default"
| "hovered"
| "clicked"
| "selected"
| "disabled"
| "default"
| "hovered"
| "clicked"
| "selected"
| "disabled"
type Interactive<T> = {
default: T
hovered?: T
clicked?: T
selected?: T
disabled?: T
default: T
hovered?: T
clicked?: T
selected?: T
disabled?: T
}
export const NO_DEFAULT_OR_BASE_ERROR =
"An interactive object must have a default state, or a base property."
"An interactive object must have a default state, or a base property."
export const NOT_ENOUGH_STATES_ERROR =
"An interactive object must have a default and at least one other state."
"An interactive object must have a default and at least one other state."
interface InteractiveProps<T> {
base?: T
state: Partial<Record<InteractiveState, T>>
base?: T
state: Partial<Record<InteractiveState, DeepPartial<T>>>
}
/**
@ -37,60 +38,60 @@ interface InteractiveProps<T> {
* @returns Interactive<T> object with fields from `base` and `state`.
*/
export function interactive<T extends Object>({
base,
state,
base,
state,
}: InteractiveProps<T>): Interactive<T> {
if (!base && !state.default) throw new Error(NO_DEFAULT_OR_BASE_ERROR)
if (!base && !state.default) throw new Error(NO_DEFAULT_OR_BASE_ERROR)
let defaultState: T
let defaultState: T
if (state.default && base) {
defaultState = merge(base, state.default) as T
} else {
defaultState = base ? base : (state.default as T)
}
if (state.default && base) {
defaultState = merge(base, state.default) as T
} else {
defaultState = base ? base : (state.default as T)
}
let interactiveObj: Interactive<T> = {
default: defaultState,
}
let interactiveObj: Interactive<T> = {
default: defaultState,
}
let stateCount = 0
let stateCount = 0
if (state.hovered !== undefined) {
interactiveObj.hovered = merge(
interactiveObj.default,
state.hovered
) as T
stateCount++
}
if (state.hovered !== undefined) {
interactiveObj.hovered = merge(
interactiveObj.default,
state.hovered
) as T
stateCount++
}
if (state.clicked !== undefined) {
interactiveObj.clicked = merge(
interactiveObj.default,
state.clicked
) as T
stateCount++
}
if (state.clicked !== undefined) {
interactiveObj.clicked = merge(
interactiveObj.default,
state.clicked
) as T
stateCount++
}
if (state.selected !== undefined) {
interactiveObj.selected = merge(
interactiveObj.default,
state.selected
) as T
stateCount++
}
if (state.selected !== undefined) {
interactiveObj.selected = merge(
interactiveObj.default,
state.selected
) as T
stateCount++
}
if (state.disabled !== undefined) {
interactiveObj.disabled = merge(
interactiveObj.default,
state.disabled
) as T
stateCount++
}
if (state.disabled !== undefined) {
interactiveObj.disabled = merge(
interactiveObj.default,
state.disabled
) as T
stateCount++
}
if (stateCount < 1) {
throw new Error(NOT_ENOUGH_STATES_ERROR)
}
if (stateCount < 1) {
throw new Error(NOT_ENOUGH_STATES_ERROR)
}
return interactiveObj
return interactiveObj
}

View File

@ -1,16 +1,17 @@
import merge from "ts-deepmerge"
import { DeepPartial } from "utility-types"
type ToggleState = "inactive" | "active"
type Toggleable<T> = Record<ToggleState, T>
export const NO_INACTIVE_OR_BASE_ERROR =
"A toggleable object must have an inactive state, or a base property."
"A toggleable object must have an inactive state, or a base property."
export const NO_ACTIVE_ERROR = "A toggleable object must have an active state."
interface ToggleableProps<T> {
base?: T
state: Partial<Record<ToggleState, T>>
base?: T
state: Partial<Record<ToggleState, DeepPartial<T>>>
}
/**
@ -27,21 +28,20 @@ interface ToggleableProps<T> {
* ```
*/
export function toggleable<T extends object>(
props: ToggleableProps<T>
props: ToggleableProps<T>
): Toggleable<T> {
const { base, state } = props
const { base, state } = props
if (!base && !state.inactive) throw new Error(NO_INACTIVE_OR_BASE_ERROR)
if (!state.active) throw new Error(NO_ACTIVE_ERROR)
if (!base && !state.inactive) throw new Error(NO_INACTIVE_OR_BASE_ERROR)
if (!state.active) throw new Error(NO_ACTIVE_ERROR)
const inactiveState = base
? ((state.inactive ? merge(base, state.inactive) : base) as T)
: (state.inactive as T)
const inactiveState = base
? ((state.inactive ? merge(base, state.inactive) : base) as T)
: (state.inactive as T)
const toggleObj: Toggleable<T> = {
inactive: inactiveState,
active: merge(base ?? {}, state.active) as T,
}
return toggleObj
const toggleObj: Toggleable<T> = {
inactive: inactiveState,
active: merge(base ?? {}, state.active) as T,
}
return toggleObj
}

View File

@ -4,39 +4,39 @@ import { text, background } from "./components"
import { toggleable } from "../element"
export default function commandPalette(colorScheme: ColorScheme) {
let layer = colorScheme.highest
let layer = colorScheme.highest
const key = toggleable({
base: {
text: text(layer, "mono", "variant", "default", { size: "xs" }),
cornerRadius: 2,
background: background(layer, "on"),
padding: {
top: 1,
bottom: 1,
left: 6,
right: 6,
},
margin: {
top: 1,
bottom: 1,
left: 2,
},
},
state: {
active: {
text: text(layer, "mono", "on", "default", { size: "xs" }),
background: withOpacity(background(layer, "on"), 0.2),
}
}
})
return {
keystrokeSpacing: 8,
// TODO: This should be a Toggle<ContainedText> on the rust side so we don't have to do this
key: {
...key.inactive,
active: key.active,
}
const key = toggleable({
base: {
text: text(layer, "mono", "variant", "default", { size: "xs" }),
cornerRadius: 2,
background: background(layer, "on"),
padding: {
top: 1,
bottom: 1,
left: 6,
right: 6,
},
margin: {
top: 1,
bottom: 1,
left: 2,
},
},
state: {
active: {
text: text(layer, "mono", "on", "default", { size: "xs" }),
background: withOpacity(background(layer, "on"), 0.2),
}
}
})
return {
keystrokeSpacing: 8,
// TODO: This should be a Toggle<ContainedText> on the rust side so we don't have to do this
key: {
inactive: { ...key.inactive },
active: key.active,
}
}
}

View File

@ -2,224 +2,232 @@ import { ColorScheme } from "../theme/colorScheme"
import { background, border, borderColor, foreground, text } from "./components"
import { interactive, toggleable } from "../element"
export default function contactsPanel(colorScheme: ColorScheme) {
const nameMargin = 8
const sidePadding = 12
const nameMargin = 8
const sidePadding = 12
let layer = colorScheme.middle
let layer = colorScheme.middle
const contactButton = {
background: background(layer, "on"),
color: foreground(layer, "on"),
iconWidth: 8,
buttonWidth: 16,
cornerRadius: 8,
}
const projectRow = {
guestAvatarSpacing: 4,
height: 24,
guestAvatar: {
cornerRadius: 8,
width: 14,
},
name: {
...text(layer, "mono", { size: "sm" }),
margin: {
left: nameMargin,
right: 6,
},
},
guests: {
margin: {
left: nameMargin,
right: nameMargin,
},
},
padding: {
const contactButton = {
background: background(layer, "on"),
color: foreground(layer, "on"),
iconWidth: 8,
buttonWidth: 16,
cornerRadius: 8,
}
const projectRow = {
guestAvatarSpacing: 4,
height: 24,
guestAvatar: {
cornerRadius: 8,
width: 14,
},
name: {
...text(layer, "mono", { size: "sm" }),
margin: {
left: nameMargin,
right: 6,
},
},
guests: {
margin: {
left: nameMargin,
right: nameMargin,
},
},
padding: {
left: sidePadding,
right: sidePadding,
},
}
return {
background: background(layer),
padding: { top: 12 },
userQueryEditor: {
background: background(layer, "on"),
cornerRadius: 6,
text: text(layer, "mono", "on"),
placeholderText: text(layer, "mono", "on", "disabled", {
size: "xs",
}),
selection: colorScheme.players[0],
border: border(layer, "on"),
padding: {
bottom: 4,
left: 8,
right: 8,
top: 4,
},
margin: {
left: 6,
},
},
userQueryEditorHeight: 33,
addContactButton: {
margin: { left: 6, right: 12 },
color: foreground(layer, "on"),
buttonWidth: 28,
iconWidth: 16,
},
rowHeight: 28,
sectionIconSize: 8,
headerRow: toggleable({
base: interactive({
base: {
...text(layer, "mono", { size: "sm" }),
margin: { top: 14 },
padding: {
left: sidePadding,
right: sidePadding,
},
background: background(layer, "default"), // posiewic: breaking change
},
}
return {
state: {
hovered: { background: background(layer, "default") },
}, // hack, we want headerRow to be interactive for whatever reason. It probably shouldn't be interactive in the first place.
}),
state: {
active: {
default: {
...text(layer, "mono", "active", { size: "sm" }),
background: background(layer, "active"),
},
}
}
}),
leaveCall: interactive({
base: {
background: background(layer),
padding: { top: 12 },
userQueryEditor: {
background: background(layer, "on"),
cornerRadius: 6,
text: text(layer, "mono", "on"),
placeholderText: text(layer, "mono", "on", "disabled", {
size: "xs",
}),
selection: colorScheme.players[0],
border: border(layer, "on"),
padding: {
bottom: 4,
left: 8,
right: 8,
top: 4,
},
margin: {
left: 6,
},
border: border(layer),
cornerRadius: 6,
margin: {
top: 1,
},
userQueryEditorHeight: 33,
addContactButton: {
margin: { left: 6, right: 12 },
color: foreground(layer, "on"),
buttonWidth: 28,
iconWidth: 16,
padding: {
top: 1,
bottom: 1,
left: 7,
right: 7,
},
rowHeight: 28,
sectionIconSize: 8,
headerRow: toggleable({
base: interactive({
base: {
...text(layer, "mono", { size: "sm" }),
margin: { top: 14 },
padding: {
left: sidePadding,
right: sidePadding,
},
background: background(layer, "default"), // posiewic: breaking change
},
state: {
hovered: { background: background(layer, "default") },
}, // hack, we want headerRow to be interactive for whatever reason. It probably shouldn't be interactive in the first place.
}),
state: {
active: {
default: {
...text(layer, "mono", "active", { size: "sm" }),
background: background(layer, "active"),
},
}
}
}),
leaveCall: interactive({
base: {
background: background(layer),
border: border(layer),
cornerRadius: 6,
margin: {
top: 1,
},
padding: {
top: 1,
bottom: 1,
left: 7,
right: 7,
},
...text(layer, "sans", "variant", { size: "xs" }),
},
state: {
hovered: {
...text(layer, "sans", "hovered", { size: "xs" }),
background: background(layer, "hovered"),
border: border(layer, "hovered"),
},
},
}),
contactRow: {
inactive: {
default: {
padding: {
left: sidePadding,
right: sidePadding,
},
},
},
active: {
default: {
background: background(layer, "active"),
padding: {
left: sidePadding,
right: sidePadding,
},
},
},
...text(layer, "sans", "variant", { size: "xs" }),
},
state: {
hovered: {
...text(layer, "sans", "hovered", { size: "xs" }),
background: background(layer, "hovered"),
border: border(layer, "hovered"),
},
},
}),
contactRow: {
inactive: {
default: {
padding: {
left: sidePadding,
right: sidePadding,
},
},
},
active: {
default: {
background: background(layer, "active"),
padding: {
left: sidePadding,
right: sidePadding,
},
},
},
},
contactAvatar: {
cornerRadius: 10,
width: 18,
contactAvatar: {
cornerRadius: 10,
width: 18,
},
contactStatusFree: {
cornerRadius: 4,
padding: 4,
margin: { top: 12, left: 12 },
background: foreground(layer, "positive"),
},
contactStatusBusy: {
cornerRadius: 4,
padding: 4,
margin: { top: 12, left: 12 },
background: foreground(layer, "negative"),
},
contactUsername: {
...text(layer, "mono", { size: "sm" }),
margin: {
left: nameMargin,
},
},
contactButtonSpacing: nameMargin,
contactButton: interactive({
base: { ...contactButton },
state: {
hovered: {
background: background(layer, "hovered"),
},
contactStatusFree: {
cornerRadius: 4,
padding: 4,
margin: { top: 12, left: 12 },
background: foreground(layer, "positive"),
},
contactStatusBusy: {
cornerRadius: 4,
padding: 4,
margin: { top: 12, left: 12 },
background: foreground(layer, "negative"),
},
contactUsername: {
...text(layer, "mono", { size: "sm" }),
margin: {
left: nameMargin,
},
},
contactButtonSpacing: nameMargin,
contactButton: interactive({
base: { ...contactButton },
state: {
hovered: {
background: background(layer, "hovered"),
},
},
}),
disabledButton: {
...contactButton,
background: background(layer, "on"),
color: foreground(layer, "on"),
},
callingIndicator: {
...text(layer, "mono", "variant", { size: "xs" }),
},
treeBranch: toggleable({
base:
interactive({
base: {
color: borderColor(layer),
width: 1,
},
state: {
hovered: {
color: borderColor(layer),
},
},
}),
disabledButton: {
...contactButton,
background: background(layer, "on"),
color: foreground(layer, "on"),
},
callingIndicator: {
...text(layer, "mono", "variant", { size: "xs" }),
},
treeBranch: toggleable(
interactive({
base: {
color: borderColor(layer),
width: 1,
},
state: {
hovered: {
color: borderColor(layer),
},
},
}),
{
default: {
color: borderColor(layer),
},
}
),
projectRow: toggleable(
interactive({
base: {
...projectRow,
background: background(layer),
icon: {
margin: { left: nameMargin },
color: foreground(layer, "variant"),
width: 12,
},
name: {
...projectRow.name,
...text(layer, "mono", { size: "sm" }),
},
},
state: {
hovered: {
background: background(layer, "hovered"),
},
},
}),
{
default: { background: background(layer, "active") },
}
),
state: {
active: {
default: {
color: borderColor(layer),
},
}
}
}
),
projectRow: toggleable({
base:
interactive({
base: {
...projectRow,
background: background(layer),
icon: {
margin: { left: nameMargin },
color: foreground(layer, "variant"),
width: 12,
},
name: {
...projectRow.name,
...text(layer, "mono", { size: "sm" }),
},
},
state: {
hovered: {
background: background(layer, "hovered"),
},
},
}),
state: {
active: {
default: { background: background(layer, "active") },
}
}
}
),
}
}

View File

@ -3,57 +3,61 @@ import { background, border, borderColor, text } from "./components"
import { interactive, toggleable } from "../element"
export default function contextMenu(colorScheme: ColorScheme) {
let layer = colorScheme.middle
return {
background: background(layer),
cornerRadius: 10,
padding: 4,
shadow: colorScheme.popoverShadow,
border: border(layer),
keystrokeMargin: 30,
item: toggleable(
interactive({
base: {
iconSpacing: 8,
iconWidth: 14,
padding: { left: 6, right: 6, top: 2, bottom: 2 },
cornerRadius: 6,
label: text(layer, "sans", { size: "sm" }),
keystroke: {
...text(layer, "sans", "variant", {
size: "sm",
weight: "bold",
}),
padding: { left: 3, right: 3 },
},
},
state: {
hovered: {
background: background(layer, "hovered"),
label: text(layer, "sans", "hovered", { size: "sm" }),
keystroke: {
...text(layer, "sans", "hovered", {
size: "sm",
weight: "bold",
}),
padding: { left: 3, right: 3 },
},
},
},
}),
{
default: {
background: background(layer, "active"),
},
hovered: {
background: background(layer, "active"),
},
}
),
separator: {
background: borderColor(layer),
margin: { top: 2, bottom: 2 },
},
let layer = colorScheme.middle
return {
background: background(layer),
cornerRadius: 10,
padding: 4,
shadow: colorScheme.popoverShadow,
border: border(layer),
keystrokeMargin: 30,
item: toggleable({
base:
interactive({
base: {
iconSpacing: 8,
iconWidth: 14,
padding: { left: 6, right: 6, top: 2, bottom: 2 },
cornerRadius: 6,
label: text(layer, "sans", { size: "sm" }),
keystroke: {
...text(layer, "sans", "variant", {
size: "sm",
weight: "bold",
}),
padding: { left: 3, right: 3 },
},
},
state: {
hovered: {
background: background(layer, "hovered"),
label: text(layer, "sans", "hovered", { size: "sm" }),
keystroke: {
...text(layer, "sans", "hovered", {
size: "sm",
weight: "bold",
}),
padding: { left: 3, right: 3 },
},
},
},
}),
state: {
active: {
default: {
background: background(layer, "active"),
},
hovered: {
background: background(layer, "active"),
},
}
}
}
),
separator: {
background: borderColor(layer),
margin: { top: 2, bottom: 2 },
},
}
}

View File

@ -7,295 +7,303 @@ import { buildSyntax } from "../theme/syntax"
import { interactive, toggleable } from "../element"
export default function editor(colorScheme: ColorScheme) {
const { isLight } = colorScheme
const { isLight } = colorScheme
let layer = colorScheme.highest
let layer = colorScheme.highest
const autocompleteItem = {
cornerRadius: 6,
padding: {
bottom: 2,
left: 6,
right: 6,
top: 2,
},
}
function diagnostic(layer: Layer, styleSet: StyleSets) {
return {
textScaleFactor: 0.857,
header: {
border: border(layer, {
top: true,
}),
},
message: {
text: text(layer, "sans", styleSet, "default", { size: "sm" }),
highlightText: text(layer, "sans", styleSet, "default", {
size: "sm",
weight: "bold",
}),
},
}
}
const syntax = buildSyntax(colorScheme)
const autocompleteItem = {
cornerRadius: 6,
padding: {
bottom: 2,
left: 6,
right: 6,
top: 2,
},
}
function diagnostic(layer: Layer, styleSet: StyleSets) {
return {
textColor: syntax.primary.color,
background: background(layer),
activeLineBackground: withOpacity(background(layer, "on"), 0.75),
highlightedLineBackground: background(layer, "on"),
// Inline autocomplete suggestions, Co-pilot suggestions, etc.
suggestion: syntax.predictive,
codeActions: {
indicator: toggleable(
interactive({
base: {
color: foreground(layer, "variant"),
},
state: {
clicked: {
color: foreground(layer, "base"),
},
hovered: {
color: foreground(layer, "on"),
},
},
}),
{
default: {
color: foreground(layer, "on"),
},
}
),
textScaleFactor: 0.857,
header: {
border: border(layer, {
top: true,
}),
},
message: {
text: text(layer, "sans", styleSet, "default", { size: "sm" }),
highlightText: text(layer, "sans", styleSet, "default", {
size: "sm",
weight: "bold",
}),
},
}
}
verticalScale: 0.55,
},
folds: {
iconMarginScale: 2.5,
foldedIcon: "icons/chevron_right_8.svg",
foldableIcon: "icons/chevron_down_8.svg",
indicator: toggleable(
interactive({
base: {
color: foreground(layer, "variant"),
},
state: {
clicked: {
color: foreground(layer, "base"),
},
hovered: {
color: foreground(layer, "on"),
},
},
}),
{
default: {
color: foreground(layer, "on"),
},
}
),
ellipses: {
textColor: colorScheme.ramps.neutral(0.71).hex(),
cornerRadiusFactor: 0.15,
background: {
// Copied from hover_popover highlight
default: {
color: colorScheme.ramps.neutral(0.5).alpha(0.0).hex(),
},
const syntax = buildSyntax(colorScheme)
hover: {
color: colorScheme.ramps.neutral(0.5).alpha(0.5).hex(),
},
clicked: {
color: colorScheme.ramps.neutral(0.5).alpha(0.7).hex(),
},
},
},
foldBackground: foreground(layer, "variant"),
},
diff: {
deleted: isLight
? colorScheme.ramps.red(0.5).hex()
: colorScheme.ramps.red(0.4).hex(),
modified: isLight
? colorScheme.ramps.yellow(0.5).hex()
: colorScheme.ramps.yellow(0.5).hex(),
inserted: isLight
? colorScheme.ramps.green(0.4).hex()
: colorScheme.ramps.green(0.5).hex(),
removedWidthEm: 0.275,
widthEm: 0.15,
cornerRadius: 0.05,
},
/** Highlights matching occurrences of what is under the cursor
* as well as matched brackets
*/
documentHighlightReadBackground: withOpacity(
foreground(layer, "accent"),
0.1
),
documentHighlightWriteBackground: colorScheme.ramps
.neutral(0.5)
.alpha(0.4)
.hex(), // TODO: This was blend * 2
errorColor: background(layer, "negative"),
gutterBackground: background(layer),
gutterPaddingFactor: 3.5,
lineNumber: withOpacity(foreground(layer), 0.35),
lineNumberActive: foreground(layer),
renameFade: 0.6,
unnecessaryCodeFade: 0.5,
selection: colorScheme.players[0],
whitespace: colorScheme.ramps.neutral(0.5).hex(),
guestSelections: [
colorScheme.players[1],
colorScheme.players[2],
colorScheme.players[3],
colorScheme.players[4],
colorScheme.players[5],
colorScheme.players[6],
colorScheme.players[7],
],
autocomplete: {
background: background(colorScheme.middle),
cornerRadius: 8,
padding: 4,
margin: {
left: -14,
},
border: border(colorScheme.middle),
shadow: colorScheme.popoverShadow,
matchHighlight: foreground(colorScheme.middle, "accent"),
item: autocompleteItem,
hoveredItem: {
...autocompleteItem,
matchHighlight: foreground(
colorScheme.middle,
"accent",
"hovered"
),
background: background(colorScheme.middle, "hovered"),
},
selectedItem: {
...autocompleteItem,
matchHighlight: foreground(
colorScheme.middle,
"accent",
"active"
),
background: background(colorScheme.middle, "active"),
},
},
diagnosticHeader: {
background: background(colorScheme.middle),
iconWidthFactor: 1.5,
textScaleFactor: 0.857,
border: border(colorScheme.middle, {
bottom: true,
top: true,
}),
code: {
...text(colorScheme.middle, "mono", { size: "sm" }),
margin: {
left: 10,
},
},
source: {
text: text(colorScheme.middle, "sans", {
size: "sm",
weight: "bold",
}),
},
message: {
highlightText: text(colorScheme.middle, "sans", {
size: "sm",
weight: "bold",
}),
text: text(colorScheme.middle, "sans", { size: "sm" }),
},
},
diagnosticPathHeader: {
background: background(colorScheme.middle),
textScaleFactor: 0.857,
filename: text(colorScheme.middle, "mono", { size: "sm" }),
path: {
...text(colorScheme.middle, "mono", { size: "sm" }),
margin: {
left: 12,
},
},
},
errorDiagnostic: diagnostic(colorScheme.middle, "negative"),
warningDiagnostic: diagnostic(colorScheme.middle, "warning"),
informationDiagnostic: diagnostic(colorScheme.middle, "accent"),
hintDiagnostic: diagnostic(colorScheme.middle, "warning"),
invalidErrorDiagnostic: diagnostic(colorScheme.middle, "base"),
invalidHintDiagnostic: diagnostic(colorScheme.middle, "base"),
invalidInformationDiagnostic: diagnostic(colorScheme.middle, "base"),
invalidWarningDiagnostic: diagnostic(colorScheme.middle, "base"),
hoverPopover: hoverPopover(colorScheme),
linkDefinition: {
color: syntax.linkUri.color,
underline: syntax.linkUri.underline,
},
jumpIcon: interactive({
return {
textColor: syntax.primary.color,
background: background(layer),
activeLineBackground: withOpacity(background(layer, "on"), 0.75),
highlightedLineBackground: background(layer, "on"),
// Inline autocomplete suggestions, Co-pilot suggestions, etc.
suggestion: syntax.predictive,
codeActions: {
indicator: toggleable({
base:
interactive({
base: {
color: foreground(layer, "on"),
iconWidth: 20,
buttonWidth: 20,
cornerRadius: 6,
padding: {
top: 6,
bottom: 6,
left: 6,
right: 6,
},
color: foreground(layer, "variant"),
},
state: {
hovered: {
background: background(layer, "on", "hovered"),
},
clicked: {
color: foreground(layer, "base"),
},
hovered: {
color: foreground(layer, "on"),
},
},
}),
}),
state: {
active: {
default: {
color: foreground(layer, "on"),
},
}
}
}
),
scrollbar: {
width: 12,
minHeightFactor: 1.0,
track: {
border: border(layer, "variant", { left: true }),
verticalScale: 0.55,
},
folds: {
iconMarginScale: 2.5,
foldedIcon: "icons/chevron_right_8.svg",
foldableIcon: "icons/chevron_down_8.svg",
indicator: toggleable({
base:
interactive({
base: {
color: foreground(layer, "variant"),
},
thumb: {
background: withOpacity(background(layer, "inverted"), 0.3),
border: {
width: 1,
color: borderColor(layer, "variant"),
top: false,
right: true,
left: true,
bottom: false,
},
state: {
clicked: {
color: foreground(layer, "base"),
},
hovered: {
color: foreground(layer, "on"),
},
},
git: {
deleted: isLight
? withOpacity(colorScheme.ramps.red(0.5).hex(), 0.8)
: withOpacity(colorScheme.ramps.red(0.4).hex(), 0.8),
modified: isLight
? withOpacity(colorScheme.ramps.yellow(0.5).hex(), 0.8)
: withOpacity(colorScheme.ramps.yellow(0.4).hex(), 0.8),
inserted: isLight
? withOpacity(colorScheme.ramps.green(0.5).hex(), 0.8)
: withOpacity(colorScheme.ramps.green(0.4).hex(), 0.8),
}),
state: {
active: {
default: {
color: foreground(layer, "on"),
},
}
}
}
),
ellipses: {
textColor: colorScheme.ramps.neutral(0.71).hex(),
cornerRadiusFactor: 0.15,
background: {
// Copied from hover_popover highlight
default: {
color: colorScheme.ramps.neutral(0.5).alpha(0.0).hex(),
},
hovered: {
color: colorScheme.ramps.neutral(0.5).alpha(0.5).hex(),
},
clicked: {
color: colorScheme.ramps.neutral(0.5).alpha(0.7).hex(),
},
},
compositionMark: {
underline: {
thickness: 1.0,
color: borderColor(layer),
},
},
foldBackground: foreground(layer, "variant"),
},
diff: {
deleted: isLight
? colorScheme.ramps.red(0.5).hex()
: colorScheme.ramps.red(0.4).hex(),
modified: isLight
? colorScheme.ramps.yellow(0.5).hex()
: colorScheme.ramps.yellow(0.5).hex(),
inserted: isLight
? colorScheme.ramps.green(0.4).hex()
: colorScheme.ramps.green(0.5).hex(),
removedWidthEm: 0.275,
widthEm: 0.15,
cornerRadius: 0.05,
},
/** Highlights matching occurrences of what is under the cursor
* as well as matched brackets
*/
documentHighlightReadBackground: withOpacity(
foreground(layer, "accent"),
0.1
),
documentHighlightWriteBackground: colorScheme.ramps
.neutral(0.5)
.alpha(0.4)
.hex(), // TODO: This was blend * 2
errorColor: background(layer, "negative"),
gutterBackground: background(layer),
gutterPaddingFactor: 3.5,
lineNumber: withOpacity(foreground(layer), 0.35),
lineNumberActive: foreground(layer),
renameFade: 0.6,
unnecessaryCodeFade: 0.5,
selection: colorScheme.players[0],
whitespace: colorScheme.ramps.neutral(0.5).hex(),
guestSelections: [
colorScheme.players[1],
colorScheme.players[2],
colorScheme.players[3],
colorScheme.players[4],
colorScheme.players[5],
colorScheme.players[6],
colorScheme.players[7],
],
autocomplete: {
background: background(colorScheme.middle),
cornerRadius: 8,
padding: 4,
margin: {
left: -14,
},
border: border(colorScheme.middle),
shadow: colorScheme.popoverShadow,
matchHighlight: foreground(colorScheme.middle, "accent"),
item: autocompleteItem,
hoveredItem: {
...autocompleteItem,
matchHighlight: foreground(
colorScheme.middle,
"accent",
"hovered"
),
background: background(colorScheme.middle, "hovered"),
},
selectedItem: {
...autocompleteItem,
matchHighlight: foreground(
colorScheme.middle,
"accent",
"active"
),
background: background(colorScheme.middle, "active"),
},
},
diagnosticHeader: {
background: background(colorScheme.middle),
iconWidthFactor: 1.5,
textScaleFactor: 0.857,
border: border(colorScheme.middle, {
bottom: true,
top: true,
}),
code: {
...text(colorScheme.middle, "mono", { size: "sm" }),
margin: {
left: 10,
},
syntax,
}
},
source: {
text: text(colorScheme.middle, "sans", {
size: "sm",
weight: "bold",
}),
},
message: {
highlightText: text(colorScheme.middle, "sans", {
size: "sm",
weight: "bold",
}),
text: text(colorScheme.middle, "sans", { size: "sm" }),
},
},
diagnosticPathHeader: {
background: background(colorScheme.middle),
textScaleFactor: 0.857,
filename: text(colorScheme.middle, "mono", { size: "sm" }),
path: {
...text(colorScheme.middle, "mono", { size: "sm" }),
margin: {
left: 12,
},
},
},
errorDiagnostic: diagnostic(colorScheme.middle, "negative"),
warningDiagnostic: diagnostic(colorScheme.middle, "warning"),
informationDiagnostic: diagnostic(colorScheme.middle, "accent"),
hintDiagnostic: diagnostic(colorScheme.middle, "warning"),
invalidErrorDiagnostic: diagnostic(colorScheme.middle, "base"),
invalidHintDiagnostic: diagnostic(colorScheme.middle, "base"),
invalidInformationDiagnostic: diagnostic(colorScheme.middle, "base"),
invalidWarningDiagnostic: diagnostic(colorScheme.middle, "base"),
hoverPopover: hoverPopover(colorScheme),
linkDefinition: {
color: syntax.linkUri.color,
underline: syntax.linkUri.underline,
},
jumpIcon: interactive({
base: {
color: foreground(layer, "on"),
iconWidth: 20,
buttonWidth: 20,
cornerRadius: 6,
padding: {
top: 6,
bottom: 6,
left: 6,
right: 6,
},
},
state: {
hovered: {
background: background(layer, "on", "hovered"),
},
},
}),
scrollbar: {
width: 12,
minHeightFactor: 1.0,
track: {
border: border(layer, "variant", { left: true }),
},
thumb: {
background: withOpacity(background(layer, "inverted"), 0.3),
border: {
width: 1,
color: borderColor(layer, "variant"),
top: false,
right: true,
left: true,
bottom: false,
},
},
git: {
deleted: isLight
? withOpacity(colorScheme.ramps.red(0.5).hex(), 0.8)
: withOpacity(colorScheme.ramps.red(0.4).hex(), 0.8),
modified: isLight
? withOpacity(colorScheme.ramps.yellow(0.5).hex(), 0.8)
: withOpacity(colorScheme.ramps.yellow(0.4).hex(), 0.8),
inserted: isLight
? withOpacity(colorScheme.ramps.green(0.5).hex(), 0.8)
: withOpacity(colorScheme.ramps.green(0.4).hex(), 0.8),
},
},
compositionMark: {
underline: {
thickness: 1.0,
color: borderColor(layer),
},
},
syntax,
}
}

View File

@ -4,91 +4,95 @@ import { background, border, text } from "./components"
import { interactive, toggleable } from "../element"
export default function picker(colorScheme: ColorScheme): any {
let layer = colorScheme.lowest
const container = {
background: background(layer),
border: border(layer),
shadow: colorScheme.modalShadow,
cornerRadius: 12,
padding: {
bottom: 4,
},
}
const inputEditor = {
placeholderText: text(layer, "sans", "on", "disabled"),
selection: colorScheme.players[0],
text: text(layer, "mono", "on"),
border: border(layer, { bottom: true }),
padding: {
bottom: 8,
left: 16,
right: 16,
top: 8,
},
margin: {
bottom: 4,
},
}
const emptyInputEditor: any = { ...inputEditor }
delete emptyInputEditor.border
delete emptyInputEditor.margin
let layer = colorScheme.lowest
const container = {
background: background(layer),
border: border(layer),
shadow: colorScheme.modalShadow,
cornerRadius: 12,
padding: {
bottom: 4,
},
}
const inputEditor = {
placeholderText: text(layer, "sans", "on", "disabled"),
selection: colorScheme.players[0],
text: text(layer, "mono", "on"),
border: border(layer, { bottom: true }),
padding: {
bottom: 8,
left: 16,
right: 16,
top: 8,
},
margin: {
bottom: 4,
},
}
const emptyInputEditor: any = { ...inputEditor }
delete emptyInputEditor.border
delete emptyInputEditor.margin
return {
...container,
emptyContainer: {
...container,
padding: {},
},
item: toggleable(
interactive({
base: {
padding: {
bottom: 4,
left: 12,
right: 12,
top: 4,
},
margin: {
top: 1,
left: 4,
right: 4,
},
cornerRadius: 8,
text: text(layer, "sans", "variant"),
highlightText: text(layer, "sans", "accent", {
weight: "bold",
}),
},
state: {
hovered: {
background: withOpacity(
background(layer, "hovered"),
0.5
),
},
},
}),
{
default: {
background: withOpacity(
background(layer, "base", "active"),
0.5
),
//text: text(layer, "sans", "base", "active"),
},
}
),
inputEditor,
emptyInputEditor,
noMatches: {
text: text(layer, "sans", "variant"),
return {
...container,
emptyContainer: {
...container,
padding: {},
},
item: toggleable({
base:
interactive({
base: {
padding: {
bottom: 8,
left: 16,
right: 16,
top: 8,
bottom: 4,
left: 12,
right: 12,
top: 4,
},
},
margin: {
top: 1,
left: 4,
right: 4,
},
cornerRadius: 8,
text: text(layer, "sans", "variant"),
highlightText: text(layer, "sans", "accent", {
weight: "bold",
}),
},
state: {
hovered: {
background: withOpacity(
background(layer, "hovered"),
0.5
),
},
},
}),
state: {
active: {
default: {
background: withOpacity(
background(layer, "base", "active"),
0.5
),
//text: text(layer, "sans", "base", "active"),
},
}
}
}
),
inputEditor,
emptyInputEditor,
noMatches: {
text: text(layer, "sans", "variant"),
padding: {
bottom: 8,
left: 16,
right: 16,
top: 8,
},
},
}
}

View File

@ -3,121 +3,125 @@ import { withOpacity } from "../theme/color"
import { background, border, foreground, text } from "./components"
import { interactive, toggleable } from "../element"
export default function projectPanel(colorScheme: ColorScheme) {
const { isLight } = colorScheme
const { isLight } = colorScheme
let layer = colorScheme.middle
let layer = colorScheme.middle
let baseEntry = {
height: 22,
iconColor: foreground(layer, "variant"),
iconSize: 7,
iconSpacing: 5,
}
let baseEntry = {
height: 22,
iconColor: foreground(layer, "variant"),
iconSize: 7,
iconSpacing: 5,
}
let status = {
git: {
modified: isLight
? colorScheme.ramps.yellow(0.6).hex()
: colorScheme.ramps.yellow(0.5).hex(),
inserted: isLight
? colorScheme.ramps.green(0.45).hex()
: colorScheme.ramps.green(0.5).hex(),
conflict: isLight
? colorScheme.ramps.red(0.6).hex()
: colorScheme.ramps.red(0.5).hex(),
let status = {
git: {
modified: isLight
? colorScheme.ramps.yellow(0.6).hex()
: colorScheme.ramps.yellow(0.5).hex(),
inserted: isLight
? colorScheme.ramps.green(0.45).hex()
: colorScheme.ramps.green(0.5).hex(),
conflict: isLight
? colorScheme.ramps.red(0.6).hex()
: colorScheme.ramps.red(0.5).hex(),
},
}
let entry = toggleable({
base:
interactive({
base: {
...baseEntry,
text: text(layer, "mono", "variant", { size: "sm" }),
status,
},
state: {
hovered: {
background: background(layer, "variant", "hovered"),
},
},
}),
state: {
active: {
default: {
/*background: colorScheme.isLight
? withOpacity(background(layer, "active"), 0.5)
: background(layer, "active") ,*/ // todo posiewic
text: text(layer, "mono", "active", { size: "sm" }),
},
hovered: {
//background: background(layer, "active"),
text: text(layer, "mono", "active", { size: "sm" }),
},
}
}
}
)
let entry = toggleable(
interactive({
base: {
...baseEntry,
text: text(layer, "mono", "variant", { size: "sm" }),
status,
},
state: {
hovered: {
background: background(layer, "variant", "hovered"),
},
},
}),
{
default: {
/*background: colorScheme.isLight
? withOpacity(background(layer, "active"), 0.5)
: background(layer, "active") ,*/ // todo posiewic
text: text(layer, "mono", "active", { size: "sm" }),
},
hovered: {
//background: background(layer, "active"),
text: text(layer, "mono", "active", { size: "sm" }),
},
}
)
return {
openProjectButton: interactive({
base: {
background: background(layer),
border: border(layer, "active"),
cornerRadius: 4,
margin: {
top: 16,
left: 16,
right: 16,
},
padding: {
top: 3,
bottom: 3,
left: 7,
right: 7,
},
...text(layer, "sans", "default", { size: "sm" }),
},
state: {
hovered: {
...text(layer, "sans", "default", { size: "sm" }),
background: background(layer, "hovered"),
border: border(layer, "active"),
},
},
}),
return {
openProjectButton: interactive({
base: {
background: background(layer),
padding: { left: 6, right: 6, top: 0, bottom: 6 },
indentWidth: 12,
entry,
draggedEntry: {
...baseEntry,
text: text(layer, "mono", "on", { size: "sm" }),
background: withOpacity(background(layer, "on"), 0.9),
border: border(layer),
status,
border: border(layer, "active"),
cornerRadius: 4,
margin: {
top: 16,
left: 16,
right: 16,
},
ignoredEntry: {
...entry,
iconColor: foreground(layer, "disabled"),
text: text(layer, "mono", "disabled"),
active: {
...entry.active,
iconColor: foreground(layer, "variant"),
},
padding: {
top: 3,
bottom: 3,
left: 7,
right: 7,
},
cutEntry: {
...entry,
text: text(layer, "mono", "disabled"),
active: {
...entry.active,
default: {
...entry.active.default,
background: background(layer, "active"),
text: text(layer, "mono", "disabled", { size: "sm" }),
},
},
...text(layer, "sans", "default", { size: "sm" }),
},
state: {
hovered: {
...text(layer, "sans", "default", { size: "sm" }),
background: background(layer, "hovered"),
border: border(layer, "active"),
},
filenameEditor: {
background: background(layer, "on"),
text: text(layer, "mono", "on", { size: "sm" }),
selection: colorScheme.players[0],
},
}),
background: background(layer),
padding: { left: 6, right: 6, top: 0, bottom: 6 },
indentWidth: 12,
entry,
draggedEntry: {
...baseEntry,
text: text(layer, "mono", "on", { size: "sm" }),
background: withOpacity(background(layer, "on"), 0.9),
border: border(layer),
status,
},
ignoredEntry: {
...entry,
iconColor: foreground(layer, "disabled"),
text: text(layer, "mono", "disabled"),
active: {
...entry.active,
iconColor: foreground(layer, "variant"),
},
},
cutEntry: {
...entry,
text: text(layer, "mono", "disabled"),
active: {
...entry.active,
default: {
...entry.active.default,
background: background(layer, "active"),
text: text(layer, "mono", "disabled", { size: "sm" }),
},
}
},
},
filenameEditor: {
background: background(layer, "on"),
text: text(layer, "mono", "on", { size: "sm" }),
selection: colorScheme.players[0],
},
}
}

View File

@ -4,123 +4,127 @@ import { background, border, foreground, text } from "./components"
import { interactive, toggleable } from "../element"
export default function search(colorScheme: ColorScheme) {
let layer = colorScheme.highest
let layer = colorScheme.highest
// Search input
const editor = {
background: background(layer),
cornerRadius: 8,
minWidth: 200,
maxWidth: 500,
placeholderText: text(layer, "mono", "disabled"),
selection: colorScheme.players[0],
text: text(layer, "mono", "default"),
border: border(layer),
margin: {
right: 12,
},
padding: {
top: 3,
bottom: 3,
left: 12,
right: 8,
},
}
// Search input
const editor = {
background: background(layer),
cornerRadius: 8,
minWidth: 200,
maxWidth: 500,
placeholderText: text(layer, "mono", "disabled"),
selection: colorScheme.players[0],
text: text(layer, "mono", "default"),
border: border(layer),
margin: {
right: 12,
},
padding: {
top: 3,
bottom: 3,
left: 12,
right: 8,
},
}
const includeExcludeEditor = {
...editor,
minWidth: 100,
maxWidth: 250,
}
const includeExcludeEditor = {
...editor,
minWidth: 100,
maxWidth: 250,
}
return {
// TODO: Add an activeMatchBackground on the rust side to differentiate between active and inactive
matchBackground: withOpacity(foreground(layer, "accent"), 0.4),
optionButton: toggleable(
interactive({
base: {
...text(layer, "mono", "on"),
background: background(layer, "on"),
cornerRadius: 6,
border: border(layer, "on"),
margin: {
right: 4,
},
padding: {
bottom: 2,
left: 10,
right: 10,
top: 2,
},
},
state: {
clicked: {
...text(layer, "mono", "on", "pressed"),
background: background(layer, "on", "pressed"),
border: border(layer, "on", "pressed"),
},
hovered: {
...text(layer, "mono", "on", "hovered"),
background: background(layer, "on", "hovered"),
border: border(layer, "on", "hovered"),
},
},
}),
{
default: {
...text(layer, "mono", "on", "inverted"),
background: background(layer, "on", "inverted"),
border: border(layer, "on", "inverted"),
},
}
),
editor,
invalidEditor: {
...editor,
border: border(layer, "negative"),
},
includeExcludeEditor,
invalidIncludeExcludeEditor: {
...includeExcludeEditor,
border: border(layer, "negative"),
},
matchIndex: {
...text(layer, "mono", "variant"),
padding: {
left: 6,
},
},
optionButtonGroup: {
padding: {
left: 12,
right: 12,
},
},
includeExcludeInputs: {
...text(layer, "mono", "variant"),
padding: {
right: 6,
},
},
resultsStatus: {
return {
// TODO: Add an activeMatchBackground on the rust side to differentiate between active and inactive
matchBackground: withOpacity(foreground(layer, "accent"), 0.4),
optionButton: toggleable({
base:
interactive({
base: {
...text(layer, "mono", "on"),
size: 18,
},
dismissButton: interactive({
base: {
color: foreground(layer, "variant"),
iconWidth: 12,
buttonWidth: 14,
padding: {
left: 10,
right: 10,
},
background: background(layer, "on"),
cornerRadius: 6,
border: border(layer, "on"),
margin: {
right: 4,
},
state: {
hovered: {
color: foreground(layer, "hovered"),
},
padding: {
bottom: 2,
left: 10,
right: 10,
top: 2,
},
},
state: {
clicked: {
...text(layer, "mono", "on", "pressed"),
background: background(layer, "on", "pressed"),
border: border(layer, "on", "pressed"),
},
hovered: {
...text(layer, "mono", "on", "hovered"),
background: background(layer, "on", "hovered"),
border: border(layer, "on", "hovered"),
},
},
}),
state: {
active: {
default: {
...text(layer, "mono", "on", "inverted"),
background: background(layer, "on", "inverted"),
border: border(layer, "on", "inverted"),
},
}
}
}
),
editor,
invalidEditor: {
...editor,
border: border(layer, "negative"),
},
includeExcludeEditor,
invalidIncludeExcludeEditor: {
...includeExcludeEditor,
border: border(layer, "negative"),
},
matchIndex: {
...text(layer, "mono", "variant"),
padding: {
left: 6,
},
},
optionButtonGroup: {
padding: {
left: 12,
right: 12,
},
},
includeExcludeInputs: {
...text(layer, "mono", "variant"),
padding: {
right: 6,
},
},
resultsStatus: {
...text(layer, "mono", "on"),
size: 18,
},
dismissButton: interactive({
base: {
color: foreground(layer, "variant"),
iconWidth: 12,
buttonWidth: 14,
padding: {
left: 10,
right: 10,
},
},
state: {
hovered: {
color: foreground(layer, "hovered"),
},
},
}),
}
}

View File

@ -2,143 +2,147 @@ import { ColorScheme } from "../theme/colorScheme"
import { background, border, foreground, text } from "./components"
import { interactive, toggleable } from "../element"
export default function statusBar(colorScheme: ColorScheme) {
let layer = colorScheme.lowest
let layer = colorScheme.lowest
const statusContainer = {
cornerRadius: 6,
padding: { top: 3, bottom: 3, left: 6, right: 6 },
}
const statusContainer = {
cornerRadius: 6,
padding: { top: 3, bottom: 3, left: 6, right: 6 },
}
const diagnosticStatusContainer = {
cornerRadius: 6,
padding: { top: 1, bottom: 1, left: 6, right: 6 },
}
const diagnosticStatusContainer = {
cornerRadius: 6,
padding: { top: 1, bottom: 1, left: 6, right: 6 },
}
return {
height: 30,
itemSpacing: 8,
padding: {
top: 1,
bottom: 1,
left: 6,
right: 6,
return {
height: 30,
itemSpacing: 8,
padding: {
top: 1,
bottom: 1,
left: 6,
right: 6,
},
border: border(layer, { top: true, overlay: true }),
cursorPosition: text(layer, "sans", "variant"),
activeLanguage: interactive({
base: {
padding: { left: 6, right: 6 },
...text(layer, "sans", "variant"),
},
state: {
hovered: {
...text(layer, "sans", "on"),
},
border: border(layer, { top: true, overlay: true }),
cursorPosition: text(layer, "sans", "variant"),
activeLanguage: interactive({
base: {
padding: { left: 6, right: 6 },
...text(layer, "sans", "variant"),
},
state: {
hovered: {
...text(layer, "sans", "on"),
},
},
}),
autoUpdateProgressMessage: text(layer, "sans", "variant"),
autoUpdateDoneMessage: text(layer, "sans", "variant"),
lspStatus: interactive({
base: {
...diagnosticStatusContainer,
iconSpacing: 4,
iconWidth: 14,
height: 18,
message: text(layer, "sans"),
iconColor: foreground(layer),
},
state: {
hovered: {
message: text(layer, "sans"),
iconColor: foreground(layer),
background: background(layer, "hovered"),
},
},
}),
diagnosticMessage: interactive({
base: {
...text(layer, "sans"),
},
state: { hovered: text(layer, "sans", "hovered") },
}),
diagnosticSummary: interactive({
base: {
height: 20,
iconWidth: 16,
iconSpacing: 2,
summarySpacing: 6,
text: text(layer, "sans", { size: "sm" }),
iconColorOk: foreground(layer, "variant"),
iconColorWarning: foreground(layer, "warning"),
iconColorError: foreground(layer, "negative"),
containerOk: {
cornerRadius: 6,
padding: { top: 3, bottom: 3, left: 7, right: 7 },
},
containerWarning: {
...diagnosticStatusContainer,
background: background(layer, "warning"),
border: border(layer, "warning"),
},
containerError: {
...diagnosticStatusContainer,
background: background(layer, "negative"),
border: border(layer, "negative"),
},
},
state: {
hovered: {
iconColorOk: foreground(layer, "on"),
containerOk: {
background: background(layer, "on", "hovered"),
},
containerWarning: {
background: background(layer, "warning", "hovered"),
border: border(layer, "warning", "hovered"),
},
containerError: {
background: background(layer, "negative", "hovered"),
border: border(layer, "negative", "hovered"),
},
},
},
}),
panelButtons: {
groupLeft: {},
groupBottom: {},
groupRight: {},
button: toggleable(
interactive({
base: {
...statusContainer,
iconSize: 16,
iconColor: foreground(layer, "variant"),
label: {
margin: { left: 6 },
...text(layer, "sans", { size: "sm" }),
},
},
state: {
hovered: {
iconColor: foreground(layer, "hovered"),
background: background(layer, "variant"),
},
},
}),
{
default: {
iconColor: foreground(layer, "active"),
background: background(layer, "active"),
},
}
),
badge: {
cornerRadius: 3,
padding: 2,
margin: { bottom: -1, right: -1 },
border: border(layer),
background: background(layer, "accent"),
},
},
}),
autoUpdateProgressMessage: text(layer, "sans", "variant"),
autoUpdateDoneMessage: text(layer, "sans", "variant"),
lspStatus: interactive({
base: {
...diagnosticStatusContainer,
iconSpacing: 4,
iconWidth: 14,
height: 18,
message: text(layer, "sans"),
iconColor: foreground(layer),
},
state: {
hovered: {
message: text(layer, "sans"),
iconColor: foreground(layer),
background: background(layer, "hovered"),
},
}
},
}),
diagnosticMessage: interactive({
base: {
...text(layer, "sans"),
},
state: { hovered: text(layer, "sans", "hovered") },
}),
diagnosticSummary: interactive({
base: {
height: 20,
iconWidth: 16,
iconSpacing: 2,
summarySpacing: 6,
text: text(layer, "sans", { size: "sm" }),
iconColorOk: foreground(layer, "variant"),
iconColorWarning: foreground(layer, "warning"),
iconColorError: foreground(layer, "negative"),
containerOk: {
cornerRadius: 6,
padding: { top: 3, bottom: 3, left: 7, right: 7 },
},
containerWarning: {
...diagnosticStatusContainer,
background: background(layer, "warning"),
border: border(layer, "warning"),
},
containerError: {
...diagnosticStatusContainer,
background: background(layer, "negative"),
border: border(layer, "negative"),
},
},
state: {
hovered: {
iconColorOk: foreground(layer, "on"),
containerOk: {
background: background(layer, "on", "hovered"),
},
containerWarning: {
background: background(layer, "warning", "hovered"),
border: border(layer, "warning", "hovered"),
},
containerError: {
background: background(layer, "negative", "hovered"),
border: border(layer, "negative", "hovered"),
},
},
},
}),
panelButtons: {
groupLeft: {},
groupBottom: {},
groupRight: {},
button: toggleable({
base:
interactive({
base: {
...statusContainer,
iconSize: 16,
iconColor: foreground(layer, "variant"),
label: {
margin: { left: 6 },
...text(layer, "sans", { size: "sm" }),
},
},
state: {
hovered: {
iconColor: foreground(layer, "hovered"),
background: background(layer, "variant"),
},
},
}), state:
{
active: {
default: {
iconColor: foreground(layer, "active"),
background: background(layer, "active"),
},
}
}
}
),
badge: {
cornerRadius: 3,
padding: 2,
margin: { bottom: -1, right: -1 },
border: border(layer),
background: background(layer, "accent"),
},
},
}
}

View File

@ -4,115 +4,120 @@ import { text, border, background, foreground } from "./components"
import { interactive, toggleable } from "../element"
export default function tabBar(colorScheme: ColorScheme) {
const height = 32
const height = 32
let activeLayer = colorScheme.highest
let layer = colorScheme.middle
let activeLayer = colorScheme.highest
let layer = colorScheme.middle
const tab = {
height,
text: text(layer, "sans", "variant", { size: "sm" }),
background: background(layer),
border: border(layer, {
right: true,
bottom: true,
overlay: true,
}),
padding: {
left: 8,
right: 12,
},
spacing: 8,
const tab = {
height,
text: text(layer, "sans", "variant", { size: "sm" }),
background: background(layer),
border: border(layer, {
right: true,
bottom: true,
overlay: true,
}),
padding: {
left: 8,
right: 12,
},
spacing: 8,
// Tab type icons (e.g. Project Search)
typeIconWidth: 14,
// Tab type icons (e.g. Project Search)
typeIconWidth: 14,
// Close icons
closeIconWidth: 8,
iconClose: foreground(layer, "variant"),
iconCloseActive: foreground(layer, "hovered"),
// Close icons
closeIconWidth: 8,
iconClose: foreground(layer, "variant"),
iconCloseActive: foreground(layer, "hovered"),
// Indicators
iconConflict: foreground(layer, "warning"),
iconDirty: foreground(layer, "accent"),
// Indicators
iconConflict: foreground(layer, "warning"),
iconDirty: foreground(layer, "accent"),
// When two tabs of the same name are open, a label appears next to them
description: {
margin: { left: 8 },
...text(layer, "sans", "disabled", { size: "2xs" }),
},
}
// When two tabs of the same name are open, a label appears next to them
description: {
margin: { left: 8 },
...text(layer, "sans", "disabled", { size: "2xs" }),
},
}
const activePaneActiveTab = {
...tab,
background: background(activeLayer),
text: text(activeLayer, "sans", "active", { size: "sm" }),
border: {
...tab.border,
bottom: false,
},
}
const activePaneActiveTab = {
...tab,
background: background(activeLayer),
text: text(activeLayer, "sans", "active", { size: "sm" }),
border: {
...tab.border,
bottom: false,
},
}
const inactivePaneInactiveTab = {
...tab,
background: background(layer),
text: text(layer, "sans", "variant", { size: "sm" }),
}
const inactivePaneInactiveTab = {
...tab,
background: background(layer),
text: text(layer, "sans", "variant", { size: "sm" }),
}
const inactivePaneActiveTab = {
...tab,
background: background(activeLayer),
text: text(layer, "sans", "variant", { size: "sm" }),
border: {
...tab.border,
bottom: false,
},
}
const inactivePaneActiveTab = {
...tab,
background: background(activeLayer),
text: text(layer, "sans", "variant", { size: "sm" }),
border: {
...tab.border,
bottom: false,
},
}
const draggedTab = {
...activePaneActiveTab,
background: withOpacity(tab.background, 0.9),
border: undefined as any,
shadow: colorScheme.popoverShadow,
}
const draggedTab = {
...activePaneActiveTab,
background: withOpacity(tab.background, 0.9),
border: undefined as any,
shadow: colorScheme.popoverShadow,
}
return {
height,
background: background(layer),
activePane: {
activeTab: activePaneActiveTab,
inactiveTab: tab,
},
inactivePane: {
activeTab: inactivePaneActiveTab,
inactiveTab: inactivePaneInactiveTab,
},
draggedTab,
paneButton: toggleable(
interactive({
base: {
color: foreground(layer, "variant"),
iconWidth: 12,
buttonWidth: activePaneActiveTab.height,
},
state: {
hovered: {
color: foreground(layer, "hovered"),
},
},
}),
{
default: {
color: foreground(layer, "accent"),
},
}
),
paneButtonContainer: {
background: tab.background,
border: {
...tab.border,
right: false,
return {
height,
background: background(layer),
activePane: {
activeTab: activePaneActiveTab,
inactiveTab: tab,
},
inactivePane: {
activeTab: inactivePaneActiveTab,
inactiveTab: inactivePaneInactiveTab,
},
draggedTab,
paneButton: toggleable({
base:
interactive({
base: {
color: foreground(layer, "variant"),
iconWidth: 12,
buttonWidth: activePaneActiveTab.height,
},
state: {
hovered: {
color: foreground(layer, "hovered"),
},
},
},
}),
state:
{
active: {
default: {
color: foreground(layer, "accent"),
},
}
}
}
),
paneButtonContainer: {
background: tab.background,
border: {
...tab.border,
right: false,
},
},
}
}

View File

@ -2,60 +2,64 @@ import { ColorScheme } from "../theme/colorScheme"
import { background, border, text } from "./components"
import { interactive, toggleable } from "../element"
export default function dropdownMenu(colorScheme: ColorScheme) {
let layer = colorScheme.middle
let layer = colorScheme.middle
return {
rowHeight: 30,
background: background(layer),
border: border(layer),
shadow: colorScheme.popoverShadow,
header: interactive({
base: {
...text(layer, "sans", { size: "sm" }),
secondaryText: text(layer, "sans", {
size: "sm",
color: "#aaaaaa",
}),
secondaryTextSpacing: 10,
padding: { left: 8, right: 8, top: 2, bottom: 2 },
cornerRadius: 6,
background: background(layer, "on"),
border: border(layer, "on", { overlay: true }),
},
state: {
hovered: {
background: background(layer, "hovered"),
...text(layer, "sans", "hovered", { size: "sm" }),
},
},
return {
rowHeight: 30,
background: background(layer),
border: border(layer),
shadow: colorScheme.popoverShadow,
header: interactive({
base: {
...text(layer, "sans", { size: "sm" }),
secondaryText: text(layer, "sans", {
size: "sm",
color: "#aaaaaa",
}),
sectionHeader: {
...text(layer, "sans", { size: "sm" }),
padding: { left: 8, right: 8, top: 8, bottom: 8 },
secondaryTextSpacing: 10,
padding: { left: 8, right: 8, top: 2, bottom: 2 },
cornerRadius: 6,
background: background(layer, "on"),
border: border(layer, "on", { overlay: true }),
},
state: {
hovered: {
background: background(layer, "hovered"),
...text(layer, "sans", "hovered", { size: "sm" }),
},
item: toggleable(
interactive({
base: {
...text(layer, "sans", { size: "sm" }),
secondaryTextSpacing: 10,
secondaryText: text(layer, "sans", { size: "sm" }),
padding: { left: 18, right: 18, top: 2, bottom: 2 },
},
state: {
hovered: {
background: background(layer, "hovered"),
...text(layer, "sans", "hovered", { size: "sm" }),
},
},
}),
{
default: {
background: background(layer, "active"),
},
hovered: {
background: background(layer, "active"),
},
}
),
},
}),
sectionHeader: {
...text(layer, "sans", { size: "sm" }),
padding: { left: 8, right: 8, top: 8, bottom: 8 },
},
item: toggleable({
base:
interactive({
base: {
...text(layer, "sans", { size: "sm" }),
secondaryTextSpacing: 10,
secondaryText: text(layer, "sans", { size: "sm" }),
padding: { left: 18, right: 18, top: 2, bottom: 2 },
},
state: {
hovered: {
background: background(layer, "hovered"),
...text(layer, "sans", "hovered", { size: "sm" }),
},
},
}),
state: {
active: {
default: {
background: background(layer, "active"),
},
hovered: {
background: background(layer, "active"),
},
}
}
}
),
}
}

View File

@ -2,398 +2,406 @@ import { ColorScheme } from "../theme/colorScheme"
import { withOpacity } from "../theme/color"
import { toggleable } from "../element"
import {
background,
border,
borderColor,
foreground,
svg,
text,
background,
border,
borderColor,
foreground,
svg,
text,
} from "./components"
import statusBar from "./statusBar"
import tabBar from "./tabBar"
import { interactive } from "../element"
import merge from "ts-deepmerge"
export default function workspace(colorScheme: ColorScheme) {
const layer = colorScheme.lowest
const isLight = colorScheme.isLight
const itemSpacing = 8
const titlebarButton = toggleable(
interactive({
base: {
cornerRadius: 6,
padding: {
top: 1,
bottom: 1,
left: 8,
right: 8,
},
...text(layer, "sans", "variant", { size: "xs" }),
background: background(layer, "variant"),
border: border(layer),
},
state: {
hovered: {
...text(layer, "sans", "variant", "hovered", {
size: "xs",
}),
background: background(layer, "variant", "hovered"),
border: border(layer, "variant", "hovered"),
},
clicked: {
...text(layer, "sans", "variant", "pressed", {
size: "xs",
}),
background: background(layer, "variant", "pressed"),
border: border(layer, "variant", "pressed"),
},
},
}),
{
default: {
...text(layer, "sans", "variant", "active", { size: "xs" }),
background: background(layer, "variant", "active"),
border: border(layer, "variant", "active"),
},
}
)
const avatarWidth = 18
const avatarOuterWidth = avatarWidth + 4
const followerAvatarWidth = 14
const followerAvatarOuterWidth = followerAvatarWidth + 4
return {
background: background(colorScheme.lowest),
blankPane: {
logoContainer: {
width: 256,
height: 256,
},
logo: svg(
withOpacity("#000000", colorScheme.isLight ? 0.6 : 0.8),
"icons/logo_96.svg",
256,
256
),
logoShadow: svg(
withOpacity(
colorScheme.isLight
? "#FFFFFF"
: colorScheme.lowest.base.default.background,
colorScheme.isLight ? 1 : 0.6
),
"icons/logo_96.svg",
256,
256
),
keyboardHints: {
margin: {
top: 96,
},
cornerRadius: 4,
},
keyboardHint: interactive({
base: {
...text(layer, "sans", "variant", { size: "sm" }),
padding: {
top: 3,
left: 8,
right: 8,
bottom: 3,
},
cornerRadius: 8,
},
state: {
hovered: {
...text(layer, "sans", "active", { size: "sm" }),
},
},
const layer = colorScheme.lowest
const isLight = colorScheme.isLight
const itemSpacing = 8
const titlebarButton = toggleable({
base:
interactive({
base: {
cornerRadius: 6,
padding: {
top: 1,
bottom: 1,
left: 8,
right: 8,
},
...text(layer, "sans", "variant", { size: "xs" }),
background: background(layer, "variant"),
border: border(layer),
},
state: {
hovered: {
...text(layer, "sans", "variant", "hovered", {
size: "xs",
}),
keyboardHintWidth: 320,
},
joiningProjectAvatar: {
cornerRadius: 40,
width: 80,
},
joiningProjectMessage: {
padding: 12,
...text(layer, "sans", { size: "lg" }),
},
externalLocationMessage: {
background: background(colorScheme.middle, "accent"),
border: border(colorScheme.middle, "accent"),
cornerRadius: 6,
padding: 12,
margin: { bottom: 8, right: 8 },
...text(colorScheme.middle, "sans", "accent", { size: "xs" }),
},
leaderBorderOpacity: 0.7,
leaderBorderWidth: 2.0,
tabBar: tabBar(colorScheme),
modal: {
margin: {
bottom: 52,
top: 52,
},
cursor: "Arrow",
},
zoomedBackground: {
cursor: "Arrow",
background: isLight
? withOpacity(background(colorScheme.lowest), 0.8)
: withOpacity(background(colorScheme.highest), 0.6),
},
zoomedPaneForeground: {
margin: 16,
shadow: colorScheme.modalShadow,
border: border(colorScheme.lowest, { overlay: true }),
},
zoomedPanelForeground: {
margin: 16,
border: border(colorScheme.lowest, { overlay: true }),
},
dock: {
left: {
border: border(layer, { right: true }),
},
bottom: {
border: border(layer, { top: true }),
},
right: {
border: border(layer, { left: true }),
},
},
paneDivider: {
color: borderColor(layer),
width: 1,
},
statusBar: statusBar(colorScheme),
titlebar: {
itemSpacing,
facePileSpacing: 2,
height: 33, // 32px + 1px border. It's important the content area of the titlebar is evenly sized to vertically center avatar images.
background: background(layer),
border: border(layer, { bottom: true }),
padding: {
left: 80,
right: itemSpacing,
},
// Project
title: text(layer, "sans", "variant"),
highlight_color: text(layer, "sans", "active").color,
// Collaborators
leaderAvatar: {
width: avatarWidth,
outerWidth: avatarOuterWidth,
cornerRadius: avatarWidth / 2,
outerCornerRadius: avatarOuterWidth / 2,
},
followerAvatar: {
width: followerAvatarWidth,
outerWidth: followerAvatarOuterWidth,
cornerRadius: followerAvatarWidth / 2,
outerCornerRadius: followerAvatarOuterWidth / 2,
},
inactiveAvatarGrayscale: true,
followerAvatarOverlap: 8,
leaderSelection: {
margin: {
top: 4,
bottom: 4,
},
padding: {
left: 2,
right: 2,
top: 2,
bottom: 2,
},
cornerRadius: 6,
},
avatarRibbon: {
height: 3,
width: 12,
// TODO: Chore: Make avatarRibbon colors driven by the theme rather than being hard coded.
},
// Sign in buttom
// FlatButton, Variant
signInPrompt: merge(titlebarButton, {
inactive: {
default: {
margin: {
left: itemSpacing,
},
},
},
background: background(layer, "variant", "hovered"),
border: border(layer, "variant", "hovered"),
},
clicked: {
...text(layer, "sans", "variant", "pressed", {
size: "xs",
}),
// Offline Indicator
offlineIcon: {
color: foreground(layer, "variant"),
width: 16,
margin: {
left: itemSpacing,
},
padding: {
right: 4,
},
},
// Notice that the collaboration server is out of date
outdatedWarning: {
...text(layer, "sans", "warning", { size: "xs" }),
background: withOpacity(background(layer, "warning"), 0.3),
border: border(layer, "warning"),
margin: {
left: itemSpacing,
},
padding: {
left: 8,
right: 8,
},
cornerRadius: 6,
},
callControl: interactive({
base: {
cornerRadius: 6,
color: foreground(layer, "variant"),
iconWidth: 12,
buttonWidth: 20,
},
state: {
hovered: {
background: background(layer, "variant", "hovered"),
color: foreground(layer, "variant", "hovered"),
},
},
}),
toggleContactsButton: toggleable(
interactive({
base: {
margin: { left: itemSpacing },
cornerRadius: 6,
color: foreground(layer, "variant"),
iconWidth: 14,
buttonWidth: 20,
},
state: {
clicked: {
background: background(layer, "variant", "pressed"),
color: foreground(layer, "variant", "pressed"),
},
hovered: {
background: background(layer, "variant", "hovered"),
color: foreground(layer, "variant", "hovered"),
},
},
}),
{
default: {
background: background(layer, "variant", "active"),
color: foreground(layer, "variant", "active"),
},
}
),
userMenuButton: merge(titlebarButton, {
inactive: {
default: {
buttonWidth: 20,
iconWidth: 12,
},
},
active: {
// posiewic: these properties are not currently set on main
default: {
iconWidth: 12,
button_width: 20,
},
},
}),
toggleContactsBadge: {
cornerRadius: 3,
padding: 2,
margin: { top: 3, left: 3 },
border: border(layer),
background: foreground(layer, "accent"),
},
shareButton: {
...titlebarButton,
},
background: background(layer, "variant", "pressed"),
border: border(layer, "variant", "pressed"),
},
},
toolbar: {
height: 34,
background: background(colorScheme.highest),
border: border(colorScheme.highest, { bottom: true }),
itemSpacing: 8,
navButton: interactive({
base: {
color: foreground(colorScheme.highest, "on"),
iconWidth: 12,
buttonWidth: 24,
cornerRadius: 6,
},
state: {
hovered: {
color: foreground(colorScheme.highest, "on", "hovered"),
background: background(
colorScheme.highest,
"on",
"hovered"
),
},
disabled: {
color: foreground(
colorScheme.highest,
"on",
"disabled"
),
},
},
}),
padding: { left: 8, right: 8, top: 4, bottom: 4 },
}),
state: {
active: {
default: {
...text(layer, "sans", "variant", "active", { size: "xs" }),
background: background(layer, "variant", "active"),
border: border(layer, "variant", "active"),
},
breadcrumbHeight: 24,
breadcrumbs: interactive({
base: {
...text(colorScheme.highest, "sans", "variant"),
cornerRadius: 6,
padding: {
left: 6,
right: 6,
},
},
state: {
hovered: {
color: foreground(colorScheme.highest, "on", "hovered"),
background: background(
colorScheme.highest,
"on",
"hovered"
),
},
},
}),
disconnectedOverlay: {
...text(layer, "sans"),
background: withOpacity(background(layer), 0.8),
},
notification: {
margin: { top: 10 },
background: background(colorScheme.middle),
cornerRadius: 6,
padding: 12,
border: border(colorScheme.middle),
shadow: colorScheme.popoverShadow,
},
notifications: {
width: 400,
margin: { right: 10, bottom: 10 },
},
dropTargetOverlayColor: withOpacity(foreground(layer, "variant"), 0.5),
}
}
}
)
const avatarWidth = 18
const avatarOuterWidth = avatarWidth + 4
const followerAvatarWidth = 14
const followerAvatarOuterWidth = followerAvatarWidth + 4
return {
background: background(colorScheme.lowest),
blankPane: {
logoContainer: {
width: 256,
height: 256,
},
logo: svg(
withOpacity("#000000", colorScheme.isLight ? 0.6 : 0.8),
"icons/logo_96.svg",
256,
256
),
logoShadow: svg(
withOpacity(
colorScheme.isLight
? "#FFFFFF"
: colorScheme.lowest.base.default.background,
colorScheme.isLight ? 1 : 0.6
),
"icons/logo_96.svg",
256,
256
),
keyboardHints: {
margin: {
top: 96,
},
cornerRadius: 4,
},
keyboardHint: interactive({
base: {
...text(layer, "sans", "variant", { size: "sm" }),
padding: {
top: 3,
left: 8,
right: 8,
bottom: 3,
},
cornerRadius: 8,
},
state: {
hovered: {
...text(layer, "sans", "active", { size: "sm" }),
},
},
}),
keyboardHintWidth: 320,
},
joiningProjectAvatar: {
cornerRadius: 40,
width: 80,
},
joiningProjectMessage: {
padding: 12,
...text(layer, "sans", { size: "lg" }),
},
externalLocationMessage: {
background: background(colorScheme.middle, "accent"),
border: border(colorScheme.middle, "accent"),
cornerRadius: 6,
padding: 12,
margin: { bottom: 8, right: 8 },
...text(colorScheme.middle, "sans", "accent", { size: "xs" }),
},
leaderBorderOpacity: 0.7,
leaderBorderWidth: 2.0,
tabBar: tabBar(colorScheme),
modal: {
margin: {
bottom: 52,
top: 52,
},
cursor: "Arrow",
},
zoomedBackground: {
cursor: "Arrow",
background: isLight
? withOpacity(background(colorScheme.lowest), 0.8)
: withOpacity(background(colorScheme.highest), 0.6),
},
zoomedPaneForeground: {
margin: 16,
shadow: colorScheme.modalShadow,
border: border(colorScheme.lowest, { overlay: true }),
},
zoomedPanelForeground: {
margin: 16,
border: border(colorScheme.lowest, { overlay: true }),
},
dock: {
left: {
border: border(layer, { right: true }),
},
bottom: {
border: border(layer, { top: true }),
},
right: {
border: border(layer, { left: true }),
},
},
paneDivider: {
color: borderColor(layer),
width: 1,
},
statusBar: statusBar(colorScheme),
titlebar: {
itemSpacing,
facePileSpacing: 2,
height: 33, // 32px + 1px border. It's important the content area of the titlebar is evenly sized to vertically center avatar images.
background: background(layer),
border: border(layer, { bottom: true }),
padding: {
left: 80,
right: itemSpacing,
},
// Project
title: text(layer, "sans", "variant"),
highlight_color: text(layer, "sans", "active").color,
// Collaborators
leaderAvatar: {
width: avatarWidth,
outerWidth: avatarOuterWidth,
cornerRadius: avatarWidth / 2,
outerCornerRadius: avatarOuterWidth / 2,
},
followerAvatar: {
width: followerAvatarWidth,
outerWidth: followerAvatarOuterWidth,
cornerRadius: followerAvatarWidth / 2,
outerCornerRadius: followerAvatarOuterWidth / 2,
},
inactiveAvatarGrayscale: true,
followerAvatarOverlap: 8,
leaderSelection: {
margin: {
top: 4,
bottom: 4,
},
padding: {
left: 2,
right: 2,
top: 2,
bottom: 2,
},
cornerRadius: 6,
},
avatarRibbon: {
height: 3,
width: 12,
// TODO: Chore: Make avatarRibbon colors driven by the theme rather than being hard coded.
},
// Sign in buttom
// FlatButton, Variant
signInPrompt: merge(titlebarButton, {
inactive: {
default: {
margin: {
left: itemSpacing,
},
},
},
}),
// Offline Indicator
offlineIcon: {
color: foreground(layer, "variant"),
width: 16,
margin: {
left: itemSpacing,
},
padding: {
right: 4,
},
},
// Notice that the collaboration server is out of date
outdatedWarning: {
...text(layer, "sans", "warning", { size: "xs" }),
background: withOpacity(background(layer, "warning"), 0.3),
border: border(layer, "warning"),
margin: {
left: itemSpacing,
},
padding: {
left: 8,
right: 8,
},
cornerRadius: 6,
},
callControl: interactive({
base: {
cornerRadius: 6,
color: foreground(layer, "variant"),
iconWidth: 12,
buttonWidth: 20,
},
state: {
hovered: {
background: background(layer, "variant", "hovered"),
color: foreground(layer, "variant", "hovered"),
},
},
}),
toggleContactsButton: toggleable({
base:
interactive({
base: {
margin: { left: itemSpacing },
cornerRadius: 6,
color: foreground(layer, "variant"),
iconWidth: 14,
buttonWidth: 20,
},
state: {
clicked: {
background: background(layer, "variant", "pressed"),
color: foreground(layer, "variant", "pressed"),
},
hovered: {
background: background(layer, "variant", "hovered"),
color: foreground(layer, "variant", "hovered"),
},
},
}), state:
{
active: {
default: {
background: background(layer, "variant", "active"),
color: foreground(layer, "variant", "active"),
},
}
}
}
),
userMenuButton: merge(titlebarButton, {
inactive: {
default: {
buttonWidth: 20,
iconWidth: 12,
},
},
active: {
// posiewic: these properties are not currently set on main
default: {
iconWidth: 12,
button_width: 20,
},
},
}),
toggleContactsBadge: {
cornerRadius: 3,
padding: 2,
margin: { top: 3, left: 3 },
border: border(layer),
background: foreground(layer, "accent"),
},
shareButton: {
...titlebarButton,
},
},
toolbar: {
height: 34,
background: background(colorScheme.highest),
border: border(colorScheme.highest, { bottom: true }),
itemSpacing: 8,
navButton: interactive({
base: {
color: foreground(colorScheme.highest, "on"),
iconWidth: 12,
buttonWidth: 24,
cornerRadius: 6,
},
state: {
hovered: {
color: foreground(colorScheme.highest, "on", "hovered"),
background: background(
colorScheme.highest,
"on",
"hovered"
),
},
disabled: {
color: foreground(
colorScheme.highest,
"on",
"disabled"
),
},
},
}),
padding: { left: 8, right: 8, top: 4, bottom: 4 },
},
breadcrumbHeight: 24,
breadcrumbs: interactive({
base: {
...text(colorScheme.highest, "sans", "variant"),
cornerRadius: 6,
padding: {
left: 6,
right: 6,
},
},
state: {
hovered: {
color: foreground(colorScheme.highest, "on", "hovered"),
background: background(
colorScheme.highest,
"on",
"hovered"
),
},
},
}),
disconnectedOverlay: {
...text(layer, "sans"),
background: withOpacity(background(layer), 0.8),
},
notification: {
margin: { top: 10 },
background: background(colorScheme.middle),
cornerRadius: 6,
padding: 12,
border: border(colorScheme.middle),
shadow: colorScheme.popoverShadow,
},
notifications: {
width: 400,
margin: { right: 10, bottom: 10 },
},
dropTargetOverlayColor: withOpacity(foreground(layer, "variant"), 0.5),
}
}