Merge branch 'main' into multi-server-completions-tailwind

This commit is contained in:
Julia
2023-08-30 22:58:37 -04:00
427 changed files with 43121 additions and 12859 deletions
+2 -7
View File
@@ -21,9 +21,7 @@ function clear_themes(theme_directory: string) {
}
}
const all_themes: Theme[] = themes.map((theme) =>
create_theme(theme)
)
const all_themes: Theme[] = themes.map((theme) => create_theme(theme))
function write_themes(themes: Theme[], output_directory: string) {
clear_themes(output_directory)
@@ -34,10 +32,7 @@ function write_themes(themes: Theme[], output_directory: string) {
const style_tree = app()
const style_tree_json = JSON.stringify(style_tree, null, 2)
const temp_path = path.join(temp_directory, `${theme.name}.json`)
const out_path = path.join(
output_directory,
`${theme.name}.json`
)
const out_path = path.join(output_directory, `${theme.name}.json`)
fs.writeFileSync(temp_path, style_tree_json)
fs.renameSync(temp_path, out_path)
console.log(`- ${out_path} created`)
+1 -3
View File
@@ -83,8 +83,6 @@ function write_tokens(themes: Theme[], tokens_directory: string) {
console.log(`- ${METADATA_FILE} created`)
}
const all_themes: Theme[] = themes.map((theme) =>
create_theme(theme)
)
const all_themes: Theme[] = themes.map((theme) => create_theme(theme))
write_tokens(all_themes, TOKENS_DIRECTORY)
+1
View File
@@ -1,5 +1,6 @@
import chroma from "chroma-js"
export * from "./theme"
export * from "./theme/theme_config"
export { chroma }
export const font_families = {
+127
View File
@@ -0,0 +1,127 @@
import { font_sizes, useTheme } from "../common"
import { Layer, Theme } from "../theme"
import { TextStyle, background } from "../style_tree/components"
// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace Button {
export type Options = {
layer: Layer
background: keyof Theme["lowest"]
color: keyof Theme["lowest"]
variant: Button.Variant
size: Button.Size
shape: Button.Shape
margin: {
top?: number
bottom?: number
left?: number
right?: number
}
states: {
enabled?: boolean
hovered?: boolean
pressed?: boolean
focused?: boolean
disabled?: boolean
}
}
export type ToggleableOptions = Options & {
active_background: keyof Theme["lowest"]
active_color: keyof Theme["lowest"]
}
/** Padding added to each side of a Shape.Rectangle button */
export const RECTANGLE_PADDING = 2
export const FONT_SIZE = font_sizes.sm
export const ICON_SIZE = 14
export const CORNER_RADIUS = 6
export const variant = {
Default: "filled",
Outline: "outline",
Ghost: "ghost",
} as const
export type Variant = (typeof variant)[keyof typeof variant]
export const shape = {
Rectangle: "rectangle",
Square: "square",
} as const
export type Shape = (typeof shape)[keyof typeof shape]
export const size = {
Small: "sm",
Medium: "md",
} as const
export type Size = (typeof size)[keyof typeof size]
export type BaseStyle = {
corder_radius: number
background: string | null
padding: {
top: number
bottom: number
left: number
right: number
}
margin: Button.Options["margin"]
button_height: number
}
export type LabelButtonStyle = BaseStyle & TextStyle
// export type IconButtonStyle = ButtonStyle
export const button_base = (
options: Partial<Button.Options> = {
variant: Button.variant.Default,
shape: Button.shape.Rectangle,
states: {
hovered: true,
pressed: true,
},
}
): BaseStyle => {
const theme = useTheme()
const layer = options.layer ?? theme.middle
const color = options.color ?? "base"
const background_color =
options.variant === Button.variant.Ghost
? null
: background(layer, options.background ?? color)
const m = {
top: options.margin?.top ?? 0,
bottom: options.margin?.bottom ?? 0,
left: options.margin?.left ?? 0,
right: options.margin?.right ?? 0,
}
const size = options.size || Button.size.Medium
const padding = 2
const base: BaseStyle = {
background: background_color,
corder_radius: Button.CORNER_RADIUS,
padding: {
top: padding,
bottom: padding,
left:
options.shape === Button.shape.Rectangle
? padding + Button.RECTANGLE_PADDING
: padding,
right:
options.shape === Button.shape.Rectangle
? padding + Button.RECTANGLE_PADDING
: padding,
},
margin: m,
button_height: 16,
}
return base
}
}
+49 -23
View File
@@ -1,6 +1,7 @@
import { interactive, toggleable } from "../element"
import { background, foreground } from "../style_tree/components"
import { useTheme, Theme } from "../theme"
import { useTheme, Theme, Layer } from "../theme"
import { Button } from "./button"
export type Margin = {
top: number
@@ -10,23 +11,36 @@ export type Margin = {
}
interface IconButtonOptions {
layer?:
| Theme["lowest"]
| Theme["middle"]
| Theme["highest"]
layer?: Theme["lowest"] | Theme["middle"] | Theme["highest"]
color?: keyof Theme["lowest"]
background_color?: keyof Theme["lowest"]
margin?: Partial<Margin>
variant?: Button.Variant
size?: Button.Size
}
type ToggleableIconButtonOptions = IconButtonOptions & {
active_color?: keyof Theme["lowest"]
active_background_color?: keyof Theme["lowest"]
active_layer?: Layer
active_variant?: Button.Variant
}
export function icon_button({ color, margin, layer }: IconButtonOptions) {
export function icon_button(
{ color, background_color, margin, layer, variant, size }: IconButtonOptions = {
variant: Button.variant.Default,
size: Button.size.Medium,
}
) {
const theme = useTheme()
if (!color) color = "base"
const default_background =
variant === Button.variant.Ghost
? null
: background(layer ?? theme.lowest, background_color ?? color)
const m = {
top: margin?.top ?? 0,
bottom: margin?.bottom ?? 0,
@@ -34,51 +48,63 @@ export function icon_button({ color, margin, layer }: IconButtonOptions) {
right: margin?.right ?? 0,
}
const padding = {
top: size === Button.size.Small ? 2 : 2,
bottom: size === Button.size.Small ? 2 : 2,
left: size === Button.size.Small ? 2 : 4,
right: size === Button.size.Small ? 2 : 4,
}
return interactive({
base: {
corner_radius: 6,
padding: {
top: 2,
bottom: 2,
left: 4,
right: 4,
},
padding: padding,
margin: m,
icon_width: 14,
icon_height: 14,
button_width: 20,
button_height: 16,
button_width: size === Button.size.Small ? 16 : 20,
button_height: 14,
},
state: {
default: {
background: background(layer ?? theme.lowest, color),
background: default_background,
color: foreground(layer ?? theme.lowest, color),
},
hovered: {
background: background(layer ?? theme.lowest, color, "hovered"),
background: background(layer ?? theme.lowest, background_color ?? color, "hovered"),
color: foreground(layer ?? theme.lowest, color, "hovered"),
},
clicked: {
background: background(layer ?? theme.lowest, color, "pressed"),
background: background(layer ?? theme.lowest, background_color ?? color, "pressed"),
color: foreground(layer ?? theme.lowest, color, "pressed"),
},
},
})
}
export function toggleable_icon_button(
theme: Theme,
{ color, active_color, margin }: ToggleableIconButtonOptions
) {
export function toggleable_icon_button({
color,
background_color,
active_color,
active_background_color,
active_variant,
margin,
variant,
size,
active_layer,
}: ToggleableIconButtonOptions) {
if (!color) color = "base"
return toggleable({
state: {
inactive: icon_button({ color, margin }),
inactive: icon_button({ color, background_color, margin, variant, size }),
active: icon_button({
color: active_color ? active_color : color,
background_color: active_background_color ? active_background_color : background_color,
margin,
layer: theme.middle,
layer: active_layer,
variant: active_variant || variant,
size,
}),
},
})
+6
View File
@@ -0,0 +1,6 @@
export * from "./icon_button"
export * from "./indicator"
export * from "./input"
export * from "./tab"
export * from "./tab_bar_button"
export * from "./text_button"
+15
View File
@@ -0,0 +1,15 @@
import { foreground } from "../style_tree/components"
import { Layer, StyleSets } from "../theme"
export const indicator = ({
layer,
color,
}: {
layer: Layer
color: StyleSets
}) => ({
corner_radius: 4,
padding: 4,
margin: { top: 12, left: 12 },
background: foreground(layer, color),
})
+23
View File
@@ -0,0 +1,23 @@
import { useTheme } from "../common"
import { background, border, text } from "../style_tree/components"
export const input = () => {
const theme = useTheme()
return {
background: background(theme.highest),
corner_radius: 8,
min_width: 200,
max_width: 500,
placeholder_text: text(theme.highest, "mono", "disabled"),
selection: theme.players[0],
text: text(theme.highest, "mono", "default"),
border: border(theme.highest),
padding: {
top: 3,
bottom: 3,
left: 12,
right: 8,
},
}
}
+73
View File
@@ -0,0 +1,73 @@
import { Layer } from "../common"
import { interactive, toggleable } from "../element"
import { Border, text } from "../style_tree/components"
type TabProps = {
layer: Layer
}
export const tab = ({ layer }: TabProps) => {
const active_color = text(layer, "sans", "base").color
const inactive_border: Border = {
color: "#FFFFFF00",
width: 1,
bottom: true,
left: false,
right: false,
top: false,
}
const active_border: Border = {
...inactive_border,
color: active_color,
}
const base = {
...text(layer, "sans", "variant"),
padding: {
top: 8,
left: 8,
right: 8,
bottom: 6,
},
border: inactive_border,
}
const i = interactive({
state: {
default: {
...base,
},
hovered: {
...base,
...text(layer, "sans", "base", "hovered"),
},
clicked: {
...base,
...text(layer, "sans", "base", "pressed"),
},
},
})
return toggleable({
base: i,
state: {
active: {
default: {
...i,
...text(layer, "sans", "base"),
border: active_border,
},
hovered: {
...i,
...text(layer, "sans", "base", "hovered"),
border: active_border,
},
clicked: {
...i,
...text(layer, "sans", "base", "pressed"),
border: active_border,
},
},
},
})
}
+35 -32
View File
@@ -12,44 +12,47 @@ type TabBarButtonProps = TabBarButtonOptions & {
state?: Partial<Record<InteractiveState, Partial<TabBarButtonOptions>>>
}
export function tab_bar_button(theme: Theme, { icon, color = "base" }: TabBarButtonProps) {
export function tab_bar_button(
theme: Theme,
{ icon, color = "base" }: TabBarButtonProps
) {
const button_spacing = 8
return (
interactive({
base: {
icon: {
color: foreground(theme.middle, color),
asset: icon,
dimensions: {
width: 15,
height: 15,
},
return interactive({
base: {
icon: {
color: foreground(theme.middle, color),
asset: icon,
dimensions: {
width: 15,
height: 15,
},
},
container: {
corner_radius: 4,
padding: {
top: 4,
bottom: 4,
left: 4,
right: 4,
},
margin: {
left: button_spacing / 2,
right: button_spacing / 2,
},
},
},
state: {
hovered: {
container: {
corner_radius: 4,
padding: {
top: 4, bottom: 4, left: 4, right: 4
},
margin: {
left: button_spacing / 2,
right: button_spacing / 2,
},
background: background(theme.middle, color, "hovered"),
},
},
state: {
hovered: {
container: {
background: background(theme.middle, color, "hovered"),
}
},
clicked: {
container: {
background: background(theme.middle, color, "pressed"),
}
clicked: {
container: {
background: background(theme.middle, color, "pressed"),
},
},
})
)
},
})
}
+47 -17
View File
@@ -6,15 +6,15 @@ import {
text,
} from "../style_tree/components"
import { useTheme, Theme } from "../theme"
import { Button } from "./button"
import { Margin } from "./icon_button"
interface TextButtonOptions {
layer?:
| Theme["lowest"]
| Theme["middle"]
| Theme["highest"]
layer?: Theme["lowest"] | Theme["middle"] | Theme["highest"]
variant?: Button.Variant
color?: keyof Theme["lowest"]
margin?: Partial<Margin>
disabled?: boolean
text_properties?: TextProperties
}
@@ -23,14 +23,21 @@ type ToggleableTextButtonOptions = TextButtonOptions & {
}
export function text_button({
variant = Button.variant.Default,
color,
layer,
margin,
disabled,
text_properties,
}: TextButtonOptions) {
}: TextButtonOptions = {}) {
const theme = useTheme()
if (!color) color = "base"
const background_color =
variant === Button.variant.Ghost
? null
: background(layer ?? theme.lowest, color)
const text_options: TextProperties = {
size: "xs",
weight: "normal",
@@ -59,31 +66,54 @@ export function text_button({
},
state: {
default: {
background: background(layer ?? theme.lowest, color),
color: foreground(layer ?? theme.lowest, color),
},
hovered: {
background: background(layer ?? theme.lowest, color, "hovered"),
color: foreground(layer ?? theme.lowest, color, "hovered"),
},
clicked: {
background: background(layer ?? theme.lowest, color, "pressed"),
color: foreground(layer ?? theme.lowest, color, "pressed"),
background: background_color,
color: disabled
? foreground(layer ?? theme.lowest, "disabled")
: foreground(layer ?? theme.lowest, color),
},
hovered: disabled
? {}
: {
background: background(
layer ?? theme.lowest,
color,
"hovered"
),
color: foreground(
layer ?? theme.lowest,
color,
"hovered"
),
},
clicked: disabled
? {}
: {
background: background(
layer ?? theme.lowest,
color,
"pressed"
),
color: foreground(
layer ?? theme.lowest,
color,
"pressed"
),
},
},
})
}
export function toggleable_text_button(
theme: Theme,
{ color, active_color, margin }: ToggleableTextButtonOptions
{ variant, color, active_color, margin }: ToggleableTextButtonOptions = {}
) {
if (!color) color = "base"
return toggleable({
state: {
inactive: text_button({ color, margin }),
inactive: text_button({ variant, color, margin }),
active: text_button({
variant,
color: active_color ? active_color : color,
margin,
layer: theme.middle,
+4 -2
View File
@@ -1,4 +1,6 @@
import { interactive, Interactive } from "./interactive"
import { toggleable } from "./toggle"
import { toggleable, Toggleable } from "./toggle"
export { interactive, Interactive, toggleable }
export * from "./padding"
export * from "./margin"
export { interactive, Interactive, toggleable, Toggleable }
+41
View File
@@ -0,0 +1,41 @@
type MarginOptions = {
all?: number
left?: number
right?: number
top?: number
bottom?: number
}
export type MarginStyle = {
top: number
bottom: number
left: number
right: number
}
export const margin_style = (options: MarginOptions): MarginStyle => {
const { all, top, bottom, left, right } = options
if (all !== undefined)
return {
top: all,
bottom: all,
left: all,
right: all,
}
if (
top === undefined &&
bottom === undefined &&
left === undefined &&
right === undefined
)
throw new Error("Margin must have at least one value")
return {
top: top || 0,
bottom: bottom || 0,
left: left || 0,
right: right || 0,
}
}
+41
View File
@@ -0,0 +1,41 @@
type PaddingOptions = {
all?: number
left?: number
right?: number
top?: number
bottom?: number
}
export type PaddingStyle = {
top: number
bottom: number
left: number
right: number
}
export const padding_style = (options: PaddingOptions): PaddingStyle => {
const { all, top, bottom, left, right } = options
if (all !== undefined)
return {
top: all,
bottom: all,
left: all,
right: all,
}
if (
top === undefined &&
bottom === undefined &&
left === undefined &&
right === undefined
)
throw new Error("Padding must have at least one value")
return {
top: top || 0,
bottom: bottom || 0,
left: left || 0,
right: right || 0,
}
}
+1 -1
View File
@@ -3,7 +3,7 @@ import { DeepPartial } from "utility-types"
type ToggleState = "inactive" | "active"
type Toggleable<T> = Record<ToggleState, T>
export 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."
+5 -7
View File
@@ -1,5 +1,3 @@
import contact_finder from "./contact_finder"
import contacts_popover from "./contacts_popover"
import command_palette from "./command_palette"
import project_panel from "./project_panel"
import search from "./search"
@@ -14,7 +12,7 @@ import simple_message_notification from "./simple_message_notification"
import project_shared_notification from "./project_shared_notification"
import tooltip from "./tooltip"
import terminal from "./terminal"
import contact_list from "./contact_list"
import collab_panel from "./collab_panel"
import toolbar_dropdown_menu from "./toolbar_dropdown_menu"
import incoming_call_notification from "./incoming_call_notification"
import welcome from "./welcome"
@@ -23,6 +21,7 @@ import assistant from "./assistant"
import { titlebar } from "./titlebar"
import editor from "./editor"
import feedback from "./feedback"
import component_test from "./component_test"
import { useTheme } from "../common"
export default function app(): any {
@@ -46,9 +45,7 @@ export default function app(): any {
editor: editor(),
project_diagnostics: project_diagnostics(),
project_panel: project_panel(),
contacts_popover: contacts_popover(),
contact_finder: contact_finder(),
contact_list: contact_list(),
collab_panel: collab_panel(),
toolbar_dropdown_menu: toolbar_dropdown_menu(),
search: search(),
shared_screen: shared_screen(),
@@ -57,6 +54,7 @@ export default function app(): any {
tooltip: tooltip(),
terminal: terminal(),
assistant: assistant(),
feedback: feedback()
feedback: feedback(),
component_test: component_test(),
}
}
+115 -35
View File
@@ -1,5 +1,5 @@
import { text, border, background, foreground, TextStyle } from "./components"
import { Interactive, interactive } from "../element"
import { Interactive, interactive, toggleable } from "../element"
import { tab_bar_button } from "../component/tab_bar_button"
import { StyleSets, useTheme } from "../theme"
@@ -8,50 +8,48 @@ type RoleCycleButton = TextStyle & {
}
// TODO: Replace these with zed types
type RemainingTokens = TextStyle & {
background: string,
margin: { top: number, right: number },
background: string
margin: { top: number; right: number }
padding: {
right: number,
left: number,
top: number,
bottom: number,
},
corner_radius: number,
right: number
left: number
top: number
bottom: number
}
corner_radius: number
}
export default function assistant(): any {
const theme = useTheme()
const interactive_role = (color: StyleSets): Interactive<RoleCycleButton> => {
return (
interactive({
base: {
const interactive_role = (
color: StyleSets
): Interactive<RoleCycleButton> => {
return interactive({
base: {
...text(theme.highest, "sans", color, { size: "sm" }),
},
state: {
hovered: {
...text(theme.highest, "sans", color, { size: "sm" }),
background: background(theme.highest, color, "hovered"),
},
state: {
hovered: {
...text(theme.highest, "sans", color, { size: "sm" }),
background: background(theme.highest, color, "hovered"),
},
clicked: {
...text(theme.highest, "sans", color, { size: "sm" }),
background: background(theme.highest, color, "pressed"),
}
clicked: {
...text(theme.highest, "sans", color, { size: "sm" }),
background: background(theme.highest, color, "pressed"),
},
})
)
},
})
}
const tokens_remaining = (color: StyleSets): RemainingTokens => {
return (
{
...text(theme.highest, "mono", color, { size: "xs" }),
background: background(theme.highest, "on", "default"),
margin: { top: 12, right: 20 },
padding: { right: 4, left: 4, top: 1, bottom: 1 },
corner_radius: 6,
}
)
return {
...text(theme.highest, "mono", color, { size: "xs" }),
background: background(theme.highest, "on", "default"),
margin: { top: 12, right: 20 },
padding: { right: 4, left: 4, top: 1, bottom: 1 },
corner_radius: 6,
}
}
return {
@@ -59,6 +57,85 @@ export default function assistant(): any {
background: background(theme.highest),
padding: { left: 12 },
},
inline: {
background: background(theme.highest),
margin: { top: 3, bottom: 3 },
border: border(theme.lowest, "on", {
top: true,
bottom: true,
overlay: true,
}),
editor: {
text: text(theme.highest, "mono", "default", { size: "sm" }),
placeholder_text: text(theme.highest, "sans", "on", "disabled"),
selection: theme.players[0],
},
disabled_editor: {
text: text(theme.highest, "mono", "disabled", { size: "sm" }),
placeholder_text: text(theme.highest, "sans", "on", "disabled"),
selection: {
cursor: text(theme.highest, "mono", "disabled").color,
selection: theme.players[0].selection,
},
},
pending_edit_background: background(theme.highest, "positive"),
include_conversation: toggleable({
base: interactive({
base: {
icon_size: 12,
color: foreground(theme.highest, "variant"),
button_width: 12,
background: background(theme.highest, "on"),
corner_radius: 2,
border: {
width: 1., color: background(theme.highest, "on")
},
padding: {
left: 4,
right: 4,
top: 4,
bottom: 4,
},
},
state: {
hovered: {
...text(theme.highest, "mono", "variant", "hovered"),
background: background(theme.highest, "on", "hovered"),
border: {
width: 1., color: background(theme.highest, "on", "hovered")
},
},
clicked: {
...text(theme.highest, "mono", "variant", "pressed"),
background: background(theme.highest, "on", "pressed"),
border: {
width: 1., color: background(theme.highest, "on", "pressed")
},
},
},
}),
state: {
active: {
default: {
icon_size: 12,
button_width: 12,
color: foreground(theme.highest, "variant"),
background: background(theme.highest, "accent"),
border: border(theme.highest, "accent"),
},
hovered: {
background: background(theme.highest, "accent", "hovered"),
border: border(theme.highest, "accent", "hovered"),
},
clicked: {
background: background(theme.highest, "accent", "pressed"),
border: border(theme.highest, "accent", "pressed"),
},
},
},
}),
},
message_header: {
margin: { bottom: 4, top: 4 },
background: background(theme.highest),
@@ -93,7 +170,10 @@ export default function assistant(): any {
base: {
background: background(theme.middle),
padding: { top: 4, bottom: 4 },
border: border(theme.middle, "default", { top: true, overlay: true }),
border: border(theme.middle, "default", {
top: true,
overlay: true,
}),
},
state: {
hovered: {
@@ -101,7 +181,7 @@ export default function assistant(): any {
},
clicked: {
background: background(theme.middle, "pressed"),
}
},
},
}),
saved_at: {
+155
View File
@@ -0,0 +1,155 @@
import { useTheme } from "../theme"
import { background, border, foreground, text } from "./components"
import picker from "./picker"
import { input } from "../component/input"
import contact_finder from "./contact_finder"
import { tab } from "../component/tab"
import { icon_button } from "../component/icon_button"
export default function channel_modal(): any {
const theme = useTheme()
const SPACING = 12 as const
const BUTTON_OFFSET = 6 as const
const ITEM_HEIGHT = 36 as const
const contact_button = {
background: background(theme.middle, "variant"),
color: foreground(theme.middle, "variant"),
icon_width: 8,
button_width: 16,
corner_radius: 8,
}
const picker_style = picker()
delete picker_style.shadow
delete picker_style.border
const picker_input = input()
const member_icon_style = icon_button({
variant: "ghost",
size: "sm",
}).default
return {
contact_finder: contact_finder(),
tabbed_modal: {
tab_button: tab({ layer: theme.middle }),
row_height: ITEM_HEIGHT,
header: {
background: background(theme.lowest),
border: border(theme.middle, {
bottom: true,
top: false,
left: false,
right: false,
}),
padding: {
top: SPACING,
left: SPACING - BUTTON_OFFSET,
right: SPACING - BUTTON_OFFSET,
},
corner_radii: {
top_right: 12,
top_left: 12,
},
},
body: {
background: background(theme.middle),
padding: {
top: SPACING - 4,
left: SPACING,
right: SPACING,
bottom: SPACING,
},
corner_radii: {
bottom_right: 12,
bottom_left: 12,
},
},
modal: {
background: background(theme.middle),
shadow: theme.modal_shadow,
corner_radius: 12,
padding: {
bottom: 0,
left: 0,
right: 0,
top: 0,
},
},
// FIXME: due to a bug in the picker's size calculation, this must be 600
max_height: 600,
max_width: 540,
title: {
...text(theme.middle, "sans", "on", { size: "lg" }),
padding: {
left: BUTTON_OFFSET,
},
},
picker: {
empty_container: {},
item: {
...picker_style.item,
margin: { left: SPACING, right: SPACING },
},
no_matches: picker_style.no_matches,
input_editor: picker_input,
empty_input_editor: picker_input,
header: picker_style.header,
footer: picker_style.footer,
},
},
channel_modal: {
// This is used for the icons that are rendered to the right of channel Members in both UIs
member_icon: member_icon_style,
// This is used for the icons that are rendered to the right of channel invites in both UIs
invitee_icon: member_icon_style,
remove_member_button: {
...text(theme.middle, "sans", { size: "xs" }),
background: background(theme.middle),
padding: {
left: 7,
right: 7,
},
},
cancel_invite_button: {
...text(theme.middle, "sans", { size: "xs" }),
background: background(theme.middle),
},
member_tag: {
...text(theme.middle, "sans", { size: "xs" }),
border: border(theme.middle, "active"),
background: background(theme.middle),
margin: {
left: 8,
},
padding: {
left: 4,
right: 4,
},
},
contact_avatar: {
corner_radius: 10,
width: 18,
},
contact_username: {
padding: {
left: 8,
},
},
contact_button: {
...contact_button,
hover: {
background: background(theme.middle, "variant", "hovered"),
},
},
disabled_contact_button: {
...contact_button,
background: background(theme.middle, "disabled"),
color: foreground(theme.middle, "disabled"),
},
},
}
}
+410
View File
@@ -0,0 +1,410 @@
import {
background,
border,
border_color,
foreground,
text,
} from "./components"
import { interactive, toggleable } from "../element"
import { useTheme } from "../theme"
import collab_modals from "./collab_modals"
import { icon_button, toggleable_icon_button } from "../component/icon_button"
import { indicator } from "../component/indicator"
export default function contacts_panel(): any {
const theme = useTheme()
const CHANNEL_SPACING = 4 as const
const NAME_MARGIN = 6 as const
const SPACING = 12 as const
const INDENT_SIZE = 8 as const
const ITEM_HEIGHT = 28 as const
const layer = theme.middle
const contact_button = {
background: background(layer, "on"),
color: foreground(layer, "on"),
icon_width: 14,
button_width: 16,
corner_radius: 8,
}
const project_row = {
guest_avatar_spacing: 4,
height: 24,
guest_avatar: {
corner_radius: 8,
width: 14,
},
name: {
...text(layer, "sans", { size: "sm" }),
margin: {
left: NAME_MARGIN,
right: 4,
},
},
guests: {
margin: {
left: NAME_MARGIN,
right: NAME_MARGIN,
},
},
padding: {
left: SPACING,
right: SPACING,
},
}
const icon_style = {
color: foreground(layer, "variant"),
width: 14,
}
const header_icon_button = toggleable_icon_button({
variant: "ghost",
size: "sm",
active_layer: theme.lowest,
})
const subheader_row = toggleable({
base: interactive({
base: {
...text(layer, "sans", { size: "sm" }),
padding: {
left: SPACING,
right: SPACING,
},
},
state: {
hovered: {
background: background(layer, "hovered"),
},
clicked: {
background: background(layer, "pressed"),
},
},
}),
state: {
active: {
default: {
...text(theme.lowest, "sans", { size: "sm" }),
background: background(theme.lowest),
},
clicked: {
background: background(layer, "pressed"),
},
},
},
})
const filter_input = {
background: background(layer, "on"),
corner_radius: 6,
text: text(layer, "sans", "base"),
placeholder_text: text(layer, "sans", "base", "disabled", {
size: "xs",
}),
selection: theme.players[0],
border: border(layer, "on"),
padding: {
bottom: 4,
left: 8,
right: 8,
top: 4,
},
margin: {
left: SPACING,
right: SPACING,
},
}
const item_row = toggleable({
base: interactive({
base: {
padding: {
left: SPACING,
right: SPACING,
},
},
state: {
clicked: {
background: background(layer, "pressed"),
},
},
}),
state: {
inactive: {
hovered: {
background: background(layer, "hovered"),
},
},
active: {
default: {
...text(theme.lowest, "sans", { size: "sm" }),
background: background(theme.lowest),
},
clicked: {
background: background(layer, "pressed"),
},
},
},
})
return {
...collab_modals(),
disclosure: {
button: icon_button({ variant: "ghost", size: "sm" }),
spacing: CHANNEL_SPACING,
},
log_in_button: interactive({
base: {
background: background(theme.middle),
border: border(theme.middle, "active"),
corner_radius: 4,
margin: {
top: 4,
left: 16,
right: 16,
},
padding: {
top: 3,
bottom: 3,
left: 7,
right: 7,
},
...text(theme.middle, "sans", "default", { size: "sm" }),
},
state: {
hovered: {
...text(theme.middle, "sans", "default", { size: "sm" }),
background: background(theme.middle, "hovered"),
border: border(theme.middle, "active"),
},
clicked: {
...text(theme.middle, "sans", "default", { size: "sm" }),
background: background(theme.middle, "pressed"),
border: border(theme.middle, "active"),
},
},
}),
background: background(layer),
padding: {
top: SPACING,
},
user_query_editor: filter_input,
channel_hash: icon_style,
user_query_editor_height: 33,
add_contact_button: header_icon_button,
add_channel_button: header_icon_button,
leave_call_button: header_icon_button,
row_height: ITEM_HEIGHT,
channel_indent: INDENT_SIZE * 2 + 2,
section_icon_size: 14,
header_row: {
...text(layer, "sans", { size: "sm", weight: "bold" }),
margin: { top: SPACING },
padding: {
left: SPACING,
right: SPACING,
},
},
subheader_row,
leave_call: interactive({
base: {
background: background(layer),
border: border(layer),
corner_radius: 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"),
},
},
}),
contact_row: toggleable({
base: interactive({
base: {
padding: {
left: SPACING,
right: SPACING,
},
},
state: {
clicked: {
background: background(layer, "pressed"),
},
},
}),
state: {
inactive: {
hovered: {
background: background(layer, "hovered"),
},
},
active: {
default: {
...text(theme.lowest, "sans", { size: "sm" }),
background: background(theme.lowest),
},
clicked: {
background: background(layer, "pressed"),
},
},
},
}),
channel_row: item_row,
channel_name: {
...text(layer, "sans", { size: "sm" }),
margin: {
left: CHANNEL_SPACING,
},
},
list_empty_label_container: {
margin: {
left: NAME_MARGIN,
},
},
list_empty_icon: {
color: foreground(layer, "variant"),
width: 14,
},
list_empty_state: toggleable({
base: interactive({
base: {
...text(layer, "sans", "variant", { size: "sm" }),
padding: {
top: SPACING / 2,
bottom: SPACING / 2,
left: SPACING,
right: SPACING,
},
},
state: {
clicked: {
background: background(layer, "pressed"),
},
},
}),
state: {
inactive: {
hovered: {
background: background(layer, "hovered"),
},
},
active: {
default: {
...text(theme.lowest, "sans", { size: "sm" }),
background: background(theme.lowest),
},
clicked: {
background: background(layer, "pressed"),
},
},
},
}),
contact_avatar: {
corner_radius: 10,
width: 20,
},
channel_avatar: {
corner_radius: 10,
width: 20,
},
extra_participant_label: {
corner_radius: 10,
padding: {
left: 10,
right: 4,
},
background: background(layer, "hovered"),
...text(layer, "sans", "hovered", { size: "xs" }),
},
contact_status_free: indicator({ layer, color: "positive" }),
contact_status_busy: indicator({ layer, color: "negative" }),
contact_username: {
...text(layer, "sans", { size: "sm" }),
margin: {
left: NAME_MARGIN,
},
},
contact_button_spacing: NAME_MARGIN,
contact_button: icon_button({
variant: "ghost",
color: "variant",
size: "sm",
}),
disabled_button: {
...contact_button,
background: background(layer, "on"),
color: foreground(layer, "on"),
},
calling_indicator: {
...text(layer, "sans", "variant", { size: "xs" }),
},
tree_branch: toggleable({
base: interactive({
base: {
color: border_color(layer),
width: 1,
},
state: {
hovered: {
color: border_color(layer),
},
},
}),
state: {
active: {
default: {
color: border_color(layer),
},
},
},
}),
project_row: toggleable({
base: interactive({
base: {
...project_row,
icon: {
margin: { left: NAME_MARGIN },
color: foreground(layer, "variant"),
width: 14,
},
name: {
...project_row.name,
...text(layer, "sans", { size: "sm" }),
},
},
state: {
hovered: {
background: background(layer, "hovered"),
},
},
}),
state: {
active: {
default: { background: background(theme.lowest) },
},
},
}),
face_overlap: 8,
channel_editor: {
padding: {
left: NAME_MARGIN,
},
},
}
}
+26
View File
@@ -0,0 +1,26 @@
import { useTheme } from "../common"
import { text_button } from "../component/text_button"
import { icon_button } from "../component/icon_button"
import { text } from "./components"
import { toggleable } from "../element"
export default function contacts_panel(): any {
const theme = useTheme()
return {
button: text_button({}),
toggle: toggleable({
base: text_button({}),
state: {
active: {
...text_button({ color: "accent" }),
},
},
}),
disclosure: {
...text(theme.lowest, "sans", "base"),
button: icon_button({ variant: "ghost" }),
spacing: 4,
},
}
}
+36 -36
View File
@@ -1,11 +1,11 @@
import picker from "./picker"
// import picker from "./picker"
import { background, border, foreground, text } from "./components"
import { useTheme } from "../theme"
export default function contact_finder(): any {
const theme = useTheme()
const side_margin = 6
// const side_margin = 6
const contact_button = {
background: background(theme.middle, "variant"),
color: foreground(theme.middle, "variant"),
@@ -14,42 +14,42 @@ export default function contact_finder(): any {
corner_radius: 8,
}
const picker_style = picker()
const picker_input = {
background: background(theme.middle, "on"),
corner_radius: 6,
text: text(theme.middle, "mono"),
placeholder_text: text(theme.middle, "mono", "on", "disabled", {
size: "xs",
}),
selection: theme.players[0],
border: border(theme.middle),
padding: {
bottom: 4,
left: 8,
right: 8,
top: 4,
},
margin: {
left: side_margin,
right: side_margin,
},
}
// const picker_style = picker()
// const picker_input = {
// background: background(theme.middle, "on"),
// corner_radius: 6,
// text: text(theme.middle, "mono"),
// placeholder_text: text(theme.middle, "mono", "on", "disabled", {
// size: "xs",
// }),
// selection: theme.players[0],
// border: border(theme.middle),
// padding: {
// bottom: 4,
// left: 8,
// right: 8,
// top: 4,
// },
// margin: {
// left: side_margin,
// right: side_margin,
// },
// }
return {
picker: {
empty_container: {},
item: {
...picker_style.item,
margin: { left: side_margin, right: side_margin },
},
no_matches: picker_style.no_matches,
input_editor: picker_input,
empty_input_editor: picker_input,
header: picker_style.header,
footer: picker_style.footer,
},
row_height: 28,
// picker: {
// empty_container: {},
// item: {
// ...picker_style.item,
// margin: { left: side_margin, right: side_margin },
// },
// no_matches: picker_style.no_matches,
// input_editor: picker_input,
// empty_input_editor: picker_input,
// header: picker_style.header,
// footer: picker_style.footer,
// },
// row_height: 28,
contact_avatar: {
corner_radius: 10,
width: 18,
-247
View File
@@ -1,247 +0,0 @@
import {
background,
border,
border_color,
foreground,
text,
} from "./components"
import { interactive, toggleable } from "../element"
import { useTheme } from "../theme"
export default function contacts_panel(): any {
const theme = useTheme()
const name_margin = 8
const side_padding = 12
const layer = theme.middle
const contact_button = {
background: background(layer, "on"),
color: foreground(layer, "on"),
icon_width: 8,
button_width: 16,
corner_radius: 8,
}
const project_row = {
guest_avatar_spacing: 4,
height: 24,
guest_avatar: {
corner_radius: 8,
width: 14,
},
name: {
...text(layer, "mono", { size: "sm" }),
margin: {
left: name_margin,
right: 6,
},
},
guests: {
margin: {
left: name_margin,
right: name_margin,
},
},
padding: {
left: side_padding,
right: side_padding,
},
}
return {
background: background(layer),
padding: { top: 12 },
user_query_editor: {
background: background(layer, "on"),
corner_radius: 6,
text: text(layer, "mono", "on"),
placeholder_text: text(layer, "mono", "on", "disabled", {
size: "xs",
}),
selection: theme.players[0],
border: border(layer, "on"),
padding: {
bottom: 4,
left: 8,
right: 8,
top: 4,
},
margin: {
left: 6,
},
},
user_query_editor_height: 33,
add_contact_button: {
margin: { left: 6, right: 12 },
color: foreground(layer, "on"),
button_width: 28,
icon_width: 16,
},
row_height: 28,
section_icon_size: 8,
header_row: toggleable({
base: interactive({
base: {
...text(layer, "mono", { size: "sm" }),
margin: { top: 14 },
padding: {
left: side_padding,
right: side_padding,
},
background: background(layer, "default"), // posiewic: breaking change
},
state: {
hovered: {
background: background(layer, "hovered"),
},
clicked: {
background: background(layer, "pressed"),
},
}, // 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"),
},
hovered: {
background: background(layer, "hovered"),
},
clicked: {
background: background(layer, "pressed"),
},
},
},
}),
leave_call: interactive({
base: {
background: background(layer),
border: border(layer),
corner_radius: 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"),
},
},
}),
contact_row: {
inactive: {
default: {
padding: {
left: side_padding,
right: side_padding,
},
},
},
active: {
default: {
background: background(layer, "active"),
padding: {
left: side_padding,
right: side_padding,
},
},
},
},
contact_avatar: {
corner_radius: 10,
width: 18,
},
contact_status_free: {
corner_radius: 4,
padding: 4,
margin: { top: 12, left: 12 },
background: foreground(layer, "positive"),
},
contact_status_busy: {
corner_radius: 4,
padding: 4,
margin: { top: 12, left: 12 },
background: foreground(layer, "negative"),
},
contact_username: {
...text(layer, "mono", { size: "sm" }),
margin: {
left: name_margin,
},
},
contact_button_spacing: name_margin,
contact_button: interactive({
base: { ...contact_button },
state: {
hovered: {
background: background(layer, "hovered"),
},
},
}),
disabled_button: {
...contact_button,
background: background(layer, "on"),
color: foreground(layer, "on"),
},
calling_indicator: {
...text(layer, "mono", "variant", { size: "xs" }),
},
tree_branch: toggleable({
base: interactive({
base: {
color: border_color(layer),
width: 1,
},
state: {
hovered: {
color: border_color(layer),
},
},
}),
state: {
active: {
default: {
color: border_color(layer),
},
},
},
}),
project_row: toggleable({
base: interactive({
base: {
...project_row,
background: background(layer),
icon: {
margin: { left: name_margin },
color: foreground(layer, "variant"),
width: 12,
},
name: {
...project_row.name,
...text(layer, "mono", { size: "sm" }),
},
},
state: {
hovered: {
background: background(layer, "hovered"),
},
},
}),
state: {
active: {
default: { background: background(layer, "active") },
},
},
}),
}
}
-10
View File
@@ -3,14 +3,4 @@ import { background, border } from "./components"
export default function contacts_popover(): any {
const theme = useTheme()
return {
background: background(theme.middle),
corner_radius: 6,
padding: { top: 6, bottom: 6 },
shadow: theme.popover_shadow,
border: border(theme.middle),
width: 300,
height: 400,
}
}
-10
View File
@@ -31,16 +31,6 @@ export default function context_menu(): any {
state: {
hovered: {
background: background(theme.middle, "hovered"),
label: text(theme.middle, "sans", "hovered", {
size: "sm",
}),
keystroke: {
...text(theme.middle, "sans", "hovered", {
size: "sm",
weight: "bold",
}),
padding: { left: 3, right: 3 },
},
},
clicked: {
background: background(theme.middle, "pressed"),
+2 -1
View File
@@ -184,6 +184,7 @@ export default function editor(): any {
theme.players[6],
theme.players[7],
],
absent_selection: theme.players[7],
autocomplete: {
background: background(theme.middle),
corner_radius: 8,
@@ -309,7 +310,7 @@ export default function editor(): any {
? with_opacity(theme.ramps.green(0.5).hex(), 0.8)
: with_opacity(theme.ramps.green(0.4).hex(), 0.8),
},
selections: foreground(layer, "accent")
selections: foreground(layer, "accent"),
},
composition_mark: {
underline: {
+1 -1
View File
@@ -37,7 +37,7 @@ export default function feedback(): any {
...text(theme.highest, "mono", "on", "disabled"),
background: background(theme.highest, "on", "disabled"),
border: border(theme.highest, "on", "disabled"),
}
},
},
}),
button_margin: 8,
+1 -1
View File
@@ -152,7 +152,7 @@ export default function picker(): any {
0.5
),
},
}
},
}),
}
}
+8 -8
View File
@@ -64,17 +64,17 @@ export default function project_panel(): any {
const unselected_default_style = merge(
base_properties,
unselected?.default ?? {},
{},
{}
)
const unselected_hovered_style = merge(
base_properties,
{ background: background(theme.middle, "hovered") },
unselected?.hovered ?? {},
unselected?.hovered ?? {}
)
const unselected_clicked_style = merge(
base_properties,
{ background: background(theme.middle, "pressed") },
unselected?.clicked ?? {},
unselected?.clicked ?? {}
)
const selected_default_style = merge(
base_properties,
@@ -82,7 +82,7 @@ export default function project_panel(): any {
background: background(theme.lowest),
text: text(theme.lowest, "sans", { size: "sm" }),
},
selected_style?.default ?? {},
selected_style?.default ?? {}
)
const selected_hovered_style = merge(
base_properties,
@@ -90,7 +90,7 @@ export default function project_panel(): any {
background: background(theme.lowest, "hovered"),
text: text(theme.lowest, "sans", { size: "sm" }),
},
selected_style?.hovered ?? {},
selected_style?.hovered ?? {}
)
const selected_clicked_style = merge(
base_properties,
@@ -98,7 +98,7 @@ export default function project_panel(): any {
background: background(theme.lowest, "pressed"),
text: text(theme.lowest, "sans", { size: "sm" }),
},
selected_style?.clicked ?? {},
selected_style?.clicked ?? {}
)
return toggleable({
@@ -175,7 +175,7 @@ export default function project_panel(): any {
default: {
icon_color: foreground(theme.middle, "variant"),
},
},
}
),
cut_entry: entry(
{
@@ -190,7 +190,7 @@ export default function project_panel(): any {
size: "sm",
}),
},
},
}
),
filename_editor: {
background: background(theme.middle, "on"),
+304 -68
View File
@@ -2,9 +2,23 @@ import { with_opacity } from "../theme/color"
import { background, border, foreground, text } from "./components"
import { interactive, toggleable } from "../element"
import { useTheme } from "../theme"
import { text_button } from "../component/text_button"
const search_results = () => {
const theme = useTheme()
return {
// TODO: Add an activeMatchBackground on the rust side to differentiate between active and inactive
match_background: with_opacity(
foreground(theme.highest, "accent"),
0.4
),
}
}
export default function search(): any {
const theme = useTheme()
const SEARCH_ROW_SPACING = 12
// Search input
const editor = {
@@ -17,13 +31,13 @@ export default function search(): any {
text: text(theme.highest, "mono", "default"),
border: border(theme.highest),
margin: {
right: 12,
right: SEARCH_ROW_SPACING,
},
padding: {
top: 3,
bottom: 3,
left: 12,
right: 8,
top: 4,
bottom: 4,
left: 10,
right: 4,
},
}
@@ -34,82 +48,161 @@ export default function search(): any {
}
return {
// TODO: Add an activeMatchBackground on the rust side to differentiate between active and inactive
match_background: with_opacity(
foreground(theme.highest, "accent"),
0.4
),
padding: { top: 0, bottom: 0 },
option_button: toggleable({
base: interactive({
base: {
...text(theme.highest, "mono", "on"),
icon_width: 14,
button_width: 32,
color: foreground(theme.highest, "variant"),
background: background(theme.highest, "on"),
corner_radius: 6,
border: border(theme.highest, "on"),
margin: {
right: 4,
corner_radius: 2,
margin: { right: 2 },
border: {
width: 1,
color: background(theme.highest, "on"),
},
padding: {
bottom: 2,
left: 10,
right: 10,
top: 2,
left: 4,
right: 4,
top: 4,
bottom: 4,
},
},
state: {
hovered: {
...text(theme.highest, "mono", "on", "hovered"),
...text(theme.highest, "mono", "variant", "hovered"),
background: background(theme.highest, "on", "hovered"),
border: border(theme.highest, "on", "hovered"),
border: {
width: 1,
color: background(theme.highest, "on", "hovered"),
},
},
clicked: {
...text(theme.highest, "mono", "on", "pressed"),
...text(theme.highest, "mono", "variant", "pressed"),
background: background(theme.highest, "on", "pressed"),
border: border(theme.highest, "on", "pressed"),
border: {
width: 1,
color: background(theme.highest, "on", "pressed"),
},
},
},
}),
state: {
active: {
default: {
...text(theme.highest, "mono", "accent"),
icon_width: 14,
button_width: 32,
color: foreground(theme.highest, "variant"),
background: background(theme.highest, "accent"),
border: border(theme.highest, "accent"),
},
hovered: {
...text(theme.highest, "mono", "accent", "hovered"),
background: background(
theme.highest,
"accent",
"hovered"
),
border: border(theme.highest, "accent", "hovered"),
},
clicked: {
...text(theme.highest, "mono", "accent", "pressed"),
background: background(
theme.highest,
"accent",
"pressed"
),
border: border(theme.highest, "accent", "pressed"),
},
},
},
}),
action_button: interactive({
base: {
...text(theme.highest, "mono", "on"),
background: background(theme.highest, "on"),
corner_radius: 6,
border: border(theme.highest, "on"),
margin: {
right: 4,
option_button_component: toggleable({
base: interactive({
base: {
icon_size: 14,
color: foreground(theme.highest, "variant"),
button_width: 32,
background: background(theme.highest, "on"),
corner_radius: 2,
margin: { right: 2 },
border: {
width: 1,
color: background(theme.highest, "on"),
},
padding: {
left: 4,
right: 4,
top: 4,
bottom: 4,
},
},
padding: {
bottom: 2,
left: 10,
right: 10,
top: 2,
state: {
hovered: {
...text(theme.highest, "mono", "variant", "hovered"),
background: background(theme.highest, "on", "hovered"),
border: {
width: 1,
color: background(theme.highest, "on", "hovered"),
},
},
clicked: {
...text(theme.highest, "mono", "variant", "pressed"),
background: background(theme.highest, "on", "pressed"),
border: {
width: 1,
color: background(theme.highest, "on", "pressed"),
},
},
},
}),
state: {
active: {
default: {
icon_size: 14,
button_width: 32,
color: foreground(theme.highest, "variant"),
background: background(theme.highest, "accent"),
border: border(theme.highest, "accent"),
},
hovered: {
background: background(
theme.highest,
"accent",
"hovered"
),
border: border(theme.highest, "accent", "hovered"),
},
clicked: {
background: background(
theme.highest,
"accent",
"pressed"
),
border: border(theme.highest, "accent", "pressed"),
},
},
},
}),
// Search tool buttons
// HACK: This is not how disabled elements should be created
// Disabled elements should use a disabled state of an interactive element, not a toggleable element with the inactive state being disabled
action_button: toggleable({
state: {
hovered: {
...text(theme.highest, "mono", "on", "hovered"),
background: background(theme.highest, "on", "hovered"),
border: border(theme.highest, "on", "hovered"),
},
clicked: {
...text(theme.highest, "mono", "on", "pressed"),
background: background(theme.highest, "on", "pressed"),
border: border(theme.highest, "on", "pressed"),
},
inactive: text_button({
variant: "ghost",
layer: theme.highest,
disabled: true,
margin: { right: SEARCH_ROW_SPACING },
text_properties: { size: "sm" },
}),
active: text_button({
variant: "ghost",
layer: theme.highest,
margin: { right: SEARCH_ROW_SPACING },
text_properties: { size: "sm" },
}),
},
}),
editor,
@@ -123,15 +216,15 @@ export default function search(): any {
border: border(theme.highest, "negative"),
},
match_index: {
...text(theme.highest, "mono", "variant"),
...text(theme.highest, "mono", { size: "sm" }),
padding: {
left: 6,
right: SEARCH_ROW_SPACING,
},
},
option_button_group: {
padding: {
left: 12,
right: 12,
left: SEARCH_ROW_SPACING,
right: SEARCH_ROW_SPACING,
},
},
include_exclude_inputs: {
@@ -140,28 +233,171 @@ export default function search(): any {
right: 6,
},
},
results_status: {
major_results_status: {
...text(theme.highest, "mono", "on"),
size: 18,
size: 15,
},
dismiss_button: interactive({
base: {
color: foreground(theme.highest, "variant"),
icon_width: 12,
button_width: 14,
padding: {
left: 10,
right: 10,
minor_results_status: {
...text(theme.highest, "mono", "variant"),
size: 13,
},
// Input Icon
editor_icon: {
icon: {
color: foreground(theme.highest, "disabled"),
asset: "icons/magnifying_glass.svg",
dimensions: {
width: 14,
height: 14,
},
},
state: {
hovered: {
color: foreground(theme.highest, "hovered"),
container: {
margin: { right: 4 },
padding: { left: 1, right: 1 },
},
},
// Toggle group buttons - Text | Regex | Semantic
mode_button: toggleable({
base: interactive({
base: {
...text(theme.highest, "mono", "variant", { size: "sm" }),
background: background(theme.highest, "variant"),
border: {
...border(theme.highest, "on"),
left: false,
right: false,
},
margin: {
top: 1,
bottom: 1,
},
padding: {
left: 10,
right: 10,
},
corner_radius: 6,
},
clicked: {
color: foreground(theme.highest, "pressed"),
state: {
hovered: {
...text(theme.highest, "mono", "variant", "hovered", {
size: "sm",
}),
background: background(
theme.highest,
"variant",
"hovered"
),
border: border(theme.highest, "on", "hovered"),
},
clicked: {
...text(theme.highest, "mono", "variant", "pressed", {
size: "sm",
}),
background: background(
theme.highest,
"variant",
"pressed"
),
border: border(theme.highest, "on", "pressed"),
},
},
}),
state: {
active: {
default: {
...text(theme.highest, "mono", "on", { size: "sm" }),
background: background(theme.highest, "on"),
},
hovered: {
...text(theme.highest, "mono", "on", "hovered", {
size: "sm",
}),
background: background(theme.highest, "on", "hovered"),
},
clicked: {
...text(theme.highest, "mono", "on", "pressed", {
size: "sm",
}),
background: background(theme.highest, "on", "pressed"),
},
},
},
}),
// Next/Previous Match buttons
// HACK: This is not how disabled elements should be created
// Disabled elements should use a disabled state of an interactive element, not a toggleable element with the inactive state being disabled
nav_button: toggleable({
state: {
inactive: interactive({
base: {
background: background(theme.highest, "disabled"),
text: text(theme.highest, "mono", "disabled"),
corner_radius: 6,
border: {
...border(theme.highest, "disabled"),
left: false,
right: false,
},
margin: {
top: 1,
bottom: 1,
},
padding: {
left: 10,
right: 10,
},
},
state: {
hovered: {},
},
}),
active: interactive({
base: {
text: text(theme.highest, "mono", "on"),
background: background(theme.highest, "on"),
corner_radius: 6,
border: {
...border(theme.highest, "on"),
left: false,
right: false,
},
margin: {
top: 1,
bottom: 1,
},
padding: {
left: 10,
right: 10,
},
},
state: {
hovered: {
...text(theme.highest, "mono", "on", "hovered"),
background: background(
theme.highest,
"on",
"hovered"
),
border: border(theme.highest, "on", "hovered"),
},
clicked: {
...text(theme.highest, "mono", "on", "pressed"),
background: background(
theme.highest,
"on",
"pressed"
),
border: border(theme.highest, "on", "pressed"),
},
},
}),
},
}),
search_bar_row_height: 32,
search_row_spacing: 8,
option_button_height: 22,
modes_container: {},
...search_results(),
}
}
+38 -31
View File
@@ -28,16 +28,18 @@ export default function status_bar(): any {
right: 6,
},
border: border(layer, { top: true, overlay: true }),
cursor_position: text(layer, "sans", "variant", { size: "xs" }),
cursor_position: text(layer, "sans", "base", { size: "xs" }),
vim_mode_indicator: {
margin: { left: 6 },
...text(layer, "mono", "variant", { size: "xs" }),
...text(layer, "mono", "base", { size: "xs" }),
},
active_language: text_button({
color: "variant"
color: "base",
}),
auto_update_progress_message: text(layer, "sans", "variant", { size: "xs" }),
auto_update_done_message: text(layer, "sans", "variant", { size: "xs" }),
auto_update_progress_message: text(layer, "sans", "base", {
size: "xs",
}),
auto_update_done_message: text(layer, "sans", "base", { size: "xs" }),
lsp_status: interactive({
base: {
...diagnostic_status_container,
@@ -64,43 +66,45 @@ export default function status_bar(): any {
diagnostic_summary: interactive({
base: {
height: 20,
icon_width: 16,
icon_width: 14,
icon_spacing: 2,
summary_spacing: 6,
text: text(layer, "sans", { size: "sm" }),
icon_color_ok: foreground(layer, "variant"),
icon_color_ok: foreground(layer, "base"),
icon_color_warning: foreground(layer, "warning"),
icon_color_error: foreground(layer, "negative"),
container_ok: {
corner_radius: 6,
padding: { top: 3, bottom: 3, left: 7, right: 7 },
},
container_warning: {
...diagnostic_status_container,
background: background(layer, "warning"),
border: border(layer, "warning"),
},
container_error: {
...diagnostic_status_container,
background: background(layer, "negative"),
border: border(layer, "negative"),
padding: { top: 2, bottom: 2, left: 6, right: 6 },
},
container_warning: diagnostic_status_container,
container_error: diagnostic_status_container
},
state: {
hovered: {
icon_color_ok: foreground(layer, "on"),
container_ok: {
background: background(layer, "on", "hovered"),
background: background(layer, "hovered")
},
container_warning: {
background: background(layer, "warning", "hovered"),
border: border(layer, "warning", "hovered"),
background: background(layer, "hovered")
},
container_error: {
background: background(layer, "negative", "hovered"),
border: border(layer, "negative", "hovered"),
background: background(layer, "hovered")
},
},
clicked: {
icon_color_ok: foreground(layer, "on"),
container_ok: {
background: background(layer, "pressed")
},
container_warning: {
background: background(layer, "pressed")
},
container_error: {
background: background(layer, "pressed")
}
}
},
}),
panel_buttons: {
@@ -111,8 +115,9 @@ export default function status_bar(): any {
base: interactive({
base: {
...status_container,
icon_size: 16,
icon_color: foreground(layer, "variant"),
icon_size: 14,
icon_color: foreground(layer, "base"),
background: background(layer, "default"),
label: {
margin: { left: 6 },
...text(layer, "sans", { size: "xs" }),
@@ -120,23 +125,25 @@ export default function status_bar(): any {
},
state: {
hovered: {
icon_color: foreground(layer, "hovered"),
background: background(layer, "variant"),
background: background(layer, "hovered"),
},
clicked: {
background: background(layer, "pressed"),
},
},
}),
state: {
active: {
default: {
icon_color: foreground(layer, "active"),
background: background(layer, "active"),
icon_color: foreground(layer, "accent", "default"),
background: background(layer, "default"),
},
hovered: {
icon_color: foreground(layer, "hovered"),
icon_color: foreground(layer, "accent", "hovered"),
background: background(layer, "hovered"),
},
clicked: {
icon_color: foreground(layer, "pressed"),
icon_color: foreground(layer, "accent", "pressed"),
background: background(layer, "pressed"),
},
},
+22
View File
@@ -84,6 +84,27 @@ export default function tab_bar(): any {
bottom: false,
},
}
const nav_button = interactive({
base: {
color: foreground(theme.highest, "on"),
icon_width: 12,
button_width: active_pane_active_tab.height,
border: border(theme.lowest, "on", {
bottom: true,
overlay: true,
}),
},
state: {
hovered: {
color: foreground(theme.highest, "on", "hovered"),
background: background(theme.highest, "on", "hovered"),
},
disabled: {
color: foreground(theme.highest, "on", "disabled"),
},
},
})
const dragged_tab = {
...active_pane_active_tab,
@@ -141,5 +162,6 @@ export default function tab_bar(): any {
right: false,
},
},
nav_button: nav_button,
}
}
+15 -13
View File
@@ -1,8 +1,6 @@
import { icon_button, toggleable_icon_button } from "../component/icon_button"
import { toggleable_text_button } from "../component/text_button"
import { icon_button, toggleable_icon_button, toggleable_text_button } from "../component"
import { interactive, toggleable } from "../element"
import { useTheme } from "../theme"
import { with_opacity } from "../theme/color"
import { useTheme, with_opacity } from "../theme"
import { background, border, foreground, text } from "./components"
const ITEM_SPACING = 8
@@ -34,16 +32,17 @@ function call_controls() {
}
return {
toggle_microphone_button: toggleable_icon_button(theme, {
toggle_microphone_button: toggleable_icon_button({
margin: {
...margin_y,
left: space.group,
right: space.half_item,
},
active_color: "negative",
active_background_color: "negative",
}),
toggle_speakers_button: toggleable_icon_button(theme, {
toggle_speakers_button: toggleable_icon_button({
margin: {
...margin_y,
left: space.half_item,
@@ -51,13 +50,14 @@ function call_controls() {
},
}),
screen_share_button: toggleable_icon_button(theme, {
screen_share_button: toggleable_icon_button({
margin: {
...margin_y,
left: space.half_item,
right: space.group,
},
active_color: "accent",
active_background_color: "accent",
}),
muted: foreground(theme.lowest, "negative"),
@@ -178,15 +178,17 @@ export function titlebar(): any {
left: 80,
right: 0,
},
// Project
project_name_divider: text(theme.lowest, "sans", "variant"),
menu: {
width: 300,
height: 400,
},
project_menu_button: toggleable_text_button(theme, {
color: 'base',
color: "base"
}),
git_menu_button: toggleable_text_button(theme, {
color: 'variant',
color: "variant",
}),
// Collaborators
@@ -259,7 +261,7 @@ export function titlebar(): any {
...call_controls(),
toggle_contacts_button: toggleable_icon_button(theme, {
toggle_contacts_button: toggleable_icon_button({
margin: {
left: ITEM_SPACING,
},
+38
View File
@@ -0,0 +1,38 @@
import { useTheme } from "../common"
import { toggleable_icon_button } from "../component/icon_button"
import { interactive } from "../element"
import { background, border, foreground, text } from "./components"
export const toolbar = () => {
const theme = useTheme()
return {
height: 32,
padding: { left: 4, right: 4, top: 4, bottom: 4 },
background: background(theme.highest),
border: border(theme.highest, { bottom: true }),
item_spacing: 4,
toggleable_tool: toggleable_icon_button({
margin: { left: 4 },
variant: "ghost",
active_color: "accent",
}),
breadcrumb_height: 24,
breadcrumbs: interactive({
base: {
...text(theme.highest, "sans", "variant"),
corner_radius: 6,
padding: {
left: 6,
right: 6,
},
},
state: {
hovered: {
color: foreground(theme.highest, "on", "hovered"),
background: background(theme.highest, "on", "hovered"),
},
},
}),
}
}
+2 -41
View File
@@ -12,6 +12,7 @@ import tabBar from "./tab_bar"
import { interactive } from "../element"
import { titlebar } from "./titlebar"
import { useTheme } from "../theme"
import { toolbar } from "./toolbar"
export default function workspace(): any {
const theme = useTheme()
@@ -127,47 +128,7 @@ export default function workspace(): any {
},
status_bar: statusBar(),
titlebar: titlebar(),
toolbar: {
height: 34,
background: background(theme.highest),
border: border(theme.highest, { bottom: true }),
item_spacing: 8,
nav_button: interactive({
base: {
color: foreground(theme.highest, "on"),
icon_width: 12,
button_width: 24,
corner_radius: 6,
},
state: {
hovered: {
color: foreground(theme.highest, "on", "hovered"),
background: background(theme.highest, "on", "hovered"),
},
disabled: {
color: foreground(theme.highest, "on", "disabled"),
},
},
}),
padding: { left: 8, right: 8, top: 4, bottom: 4 },
},
breadcrumb_height: 24,
breadcrumbs: interactive({
base: {
...text(theme.highest, "sans", "variant"),
corner_radius: 6,
padding: {
left: 6,
right: 6,
},
},
state: {
hovered: {
color: foreground(theme.highest, "on", "hovered"),
background: background(theme.highest, "on", "hovered"),
},
},
}),
toolbar: toolbar(),
disconnected_overlay: {
...text(theme.lowest, "sans"),
background: with_opacity(background(theme.lowest), 0.8),
+11 -8
View File
@@ -1,4 +1,4 @@
import chroma, { Scale, Color } from "chroma-js"
import { Scale, Color } from "chroma-js"
import { Syntax, ThemeSyntax, SyntaxHighlightStyle } from "./syntax"
export { Syntax, ThemeSyntax, SyntaxHighlightStyle }
import {
@@ -13,16 +13,16 @@ export interface Theme {
is_light: boolean
/**
* App background, other elements that should sit directly on top of the background.
*/
* App background, other elements that should sit directly on top of the background.
*/
lowest: Layer
/**
* Panels, tabs, other UI surfaces that sit on top of the background.
*/
* Panels, tabs, other UI surfaces that sit on top of the background.
*/
middle: Layer
/**
* Editors like code buffers, conversation editors, etc.
*/
* Editors like code buffers, conversation editors, etc.
*/
highest: Layer
ramps: RampSet
@@ -206,7 +206,10 @@ function build_color_family(ramps: RampSet): ColorFamily {
for (const ramp in ramps) {
const ramp_value = ramps[ramp as keyof RampSet]
const lightnessValues = [ramp_value(0).get('hsl.l') * 100, ramp_value(1).get('hsl.l') * 100]
const lightnessValues = [
ramp_value(0).get("hsl.l") * 100,
ramp_value(1).get("hsl.l") * 100,
]
const low = Math.min(...lightnessValues)
const high = Math.max(...lightnessValues)
const range = high - low
+1
View File
@@ -23,3 +23,4 @@ export * from "./create_theme"
export * from "./ramps"
export * from "./syntax"
export * from "./theme_config"
export * from "./color"
+1 -5
View File
@@ -4,11 +4,7 @@ import {
SingleOtherToken,
TokenTypes,
} from "@tokens-studio/types"
import {
Shadow,
SyntaxHighlightStyle,
ThemeSyntax,
} from "../create_theme"
import { Shadow, SyntaxHighlightStyle, ThemeSyntax } from "../create_theme"
import { LayerToken, layer_token } from "./layer"
import { PlayersToken, players_token } from "./players"
import { color_token } from "./token"