WIP UI Tweaks (#2911)

- Tighten up toolbar
- Reduce intensity of active tools
- Remove divider between project + branch
- Add a styletree for toolbar + move breadcrumb into it
- Some ts theme tidying

[[PR Description]]

Release Notes:

- Improved density and contrast of a number of UI elements.
This commit is contained in:
Nate Butler
2023-08-30 11:19:05 -04:00
committed by GitHub
38 changed files with 493 additions and 372 deletions
+35 -34
View File
@@ -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 {
@@ -172,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: {
@@ -180,7 +181,7 @@ export default function assistant(): any {
},
clicked: {
background: background(theme.middle, "pressed"),
}
},
},
}),
saved_at: {
+13 -10
View File
@@ -39,7 +39,12 @@ export default function channel_modal(): any {
row_height: ITEM_HEIGHT,
header: {
background: background(theme.lowest),
border: border(theme.middle, { "bottom": true, "top": false, left: false, right: false }),
border: border(theme.middle, {
bottom: true,
top: false,
left: false,
right: false,
}),
padding: {
top: SPACING,
left: SPACING - BUTTON_OFFSET,
@@ -48,7 +53,7 @@ export default function channel_modal(): any {
corner_radii: {
top_right: 12,
top_left: 12,
}
},
},
body: {
background: background(theme.middle),
@@ -57,12 +62,11 @@ export default function channel_modal(): any {
left: SPACING,
right: SPACING,
bottom: SPACING,
},
corner_radii: {
bottom_right: 12,
bottom_left: 12,
}
},
},
modal: {
background: background(theme.middle),
@@ -74,7 +78,6 @@ export default function channel_modal(): any {
right: 0,
top: 0,
},
},
// FIXME: due to a bug in the picker's size calculation, this must be 600
max_height: 600,
@@ -83,7 +86,7 @@ export default function channel_modal(): any {
...text(theme.middle, "sans", "on", { size: "lg" }),
padding: {
left: BUTTON_OFFSET,
}
},
},
picker: {
empty_container: {},
@@ -108,8 +111,8 @@ export default function channel_modal(): any {
background: background(theme.middle),
padding: {
left: 7,
right: 7
}
right: 7,
},
},
cancel_invite_button: {
...text(theme.middle, "sans", { size: "xs" }),
@@ -125,7 +128,7 @@ export default function channel_modal(): any {
padding: {
left: 4,
right: 4,
}
},
},
contact_avatar: {
corner_radius: 10,
@@ -147,6 +150,6 @@ export default function channel_modal(): any {
background: background(theme.middle, "disabled"),
color: foreground(theme.middle, "disabled"),
},
}
},
}
}
+7 -7
View File
@@ -27,7 +27,7 @@ export default function contacts_panel(): any {
color: foreground(layer, "on"),
icon_width: 14,
button_width: 16,
corner_radius: 8
corner_radius: 8,
}
const project_row = {
@@ -61,7 +61,7 @@ export default function contacts_panel(): any {
width: 14,
}
const header_icon_button = toggleable_icon_button(theme, {
const header_icon_button = toggleable_icon_button({
variant: "ghost",
size: "sm",
active_layer: theme.lowest,
@@ -275,7 +275,7 @@ export default function contacts_panel(): any {
list_empty_label_container: {
margin: {
left: NAME_MARGIN,
}
},
},
list_empty_icon: {
color: foreground(layer, "variant"),
@@ -289,7 +289,7 @@ export default function contacts_panel(): any {
top: SPACING / 2,
bottom: SPACING / 2,
left: SPACING,
right: SPACING
right: SPACING,
},
},
state: {
@@ -330,7 +330,7 @@ export default function contacts_panel(): any {
right: 4,
},
background: background(layer, "hovered"),
...text(layer, "sans", "hovered", { size: "xs" })
...text(layer, "sans", "hovered", { size: "xs" }),
},
contact_status_free: indicator({ layer, color: "positive" }),
contact_status_busy: indicator({ layer, color: "negative" }),
@@ -404,7 +404,7 @@ export default function contacts_panel(): any {
channel_editor: {
padding: {
left: NAME_MARGIN,
}
}
},
},
}
}
+4 -5
View File
@@ -1,4 +1,3 @@
import { useTheme } from "../common"
import { text_button } from "../component/text_button"
import { icon_button } from "../component/icon_button"
@@ -14,14 +13,14 @@ export default function contacts_panel(): any {
base: text_button({}),
state: {
active: {
...text_button({ color: "accent" })
}
}
...text_button({ color: "accent" }),
},
},
}),
disclosure: {
...text(theme.lowest, "sans", "base"),
button: icon_button({ variant: "ghost" }),
spacing: 4,
}
},
}
}
@@ -3,5 +3,4 @@ import { background, border } from "./components"
export default function contacts_popover(): any {
const theme = useTheme()
}
+1 -1
View File
@@ -307,7 +307,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"),
+94 -37
View File
@@ -31,7 +31,7 @@ export default function search(): any {
text: text(theme.highest, "mono", "default"),
border: border(theme.highest),
margin: {
right: 9,
right: SEARCH_ROW_SPACING,
},
padding: {
top: 4,
@@ -48,7 +48,7 @@ export default function search(): any {
}
return {
padding: { top: 4, bottom: 4 },
padding: { top: 0, bottom: 0 },
option_button: toggleable({
base: interactive({
@@ -60,7 +60,8 @@ export default function search(): any {
corner_radius: 2,
margin: { right: 2 },
border: {
width: 1., color: background(theme.highest, "on")
width: 1,
color: background(theme.highest, "on"),
},
padding: {
left: 4,
@@ -74,14 +75,16 @@ export default function search(): any {
...text(theme.highest, "mono", "variant", "hovered"),
background: background(theme.highest, "on", "hovered"),
border: {
width: 1., color: background(theme.highest, "on", "hovered")
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")
width: 1,
color: background(theme.highest, "on", "pressed"),
},
},
},
@@ -96,11 +99,19 @@ export default function search(): any {
border: border(theme.highest, "accent"),
},
hovered: {
background: background(theme.highest, "accent", "hovered"),
background: background(
theme.highest,
"accent",
"hovered"
),
border: border(theme.highest, "accent", "hovered"),
},
clicked: {
background: background(theme.highest, "accent", "pressed"),
background: background(
theme.highest,
"accent",
"pressed"
),
border: border(theme.highest, "accent", "pressed"),
},
},
@@ -117,7 +128,8 @@ export default function search(): any {
corner_radius: 2,
margin: { right: 2 },
border: {
width: 1., color: background(theme.highest, "on")
width: 1,
color: background(theme.highest, "on"),
},
padding: {
left: 4,
@@ -131,14 +143,16 @@ export default function search(): any {
...text(theme.highest, "mono", "variant", "hovered"),
background: background(theme.highest, "on", "hovered"),
border: {
width: 1., color: background(theme.highest, "on", "hovered")
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")
width: 1,
color: background(theme.highest, "on", "pressed"),
},
},
},
@@ -153,11 +167,19 @@ export default function search(): any {
border: border(theme.highest, "accent"),
},
hovered: {
background: background(theme.highest, "accent", "hovered"),
background: background(
theme.highest,
"accent",
"hovered"
),
border: border(theme.highest, "accent", "hovered"),
},
clicked: {
background: background(theme.highest, "accent", "pressed"),
background: background(
theme.highest,
"accent",
"pressed"
),
border: border(theme.highest, "accent", "pressed"),
},
},
@@ -168,9 +190,20 @@ export default function search(): any {
// 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: {
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" } })
}
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,
invalid_editor: {
@@ -216,12 +249,12 @@ export default function search(): any {
dimensions: {
width: 14,
height: 14,
}
},
},
container: {
margin: { right: 4 },
padding: { left: 1, right: 1 },
}
},
},
// Toggle group buttons - Text | Regex | Semantic
mode_button: toggleable({
@@ -233,27 +266,39 @@ export default function search(): any {
border: {
...border(theme.highest, "on"),
left: false,
right: false
right: false,
},
margin: {
top: 1,
bottom: 1,
},
padding: {
left: 12,
right: 12,
left: 10,
right: 10,
},
corner_radius: 6,
},
state: {
hovered: {
...text(theme.highest, "mono", "variant", "hovered", { size: "sm" }),
background: background(theme.highest, "variant", "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"),
...text(theme.highest, "mono", "variant", "pressed", {
size: "sm",
}),
background: background(
theme.highest,
"variant",
"pressed"
),
border: border(theme.highest, "on", "pressed"),
},
},
@@ -262,15 +307,19 @@ export default function search(): any {
active: {
default: {
...text(theme.highest, "mono", "on", { size: "sm" }),
background: background(theme.highest, "on")
background: background(theme.highest, "on"),
},
hovered: {
...text(theme.highest, "mono", "on", "hovered", { 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")
...text(theme.highest, "mono", "on", "pressed", {
size: "sm",
}),
background: background(theme.highest, "on", "pressed"),
},
},
},
@@ -300,8 +349,8 @@ export default function search(): any {
},
},
state: {
hovered: {}
}
hovered: {},
},
}),
active: interactive({
base: {
@@ -325,22 +374,30 @@ export default function search(): any {
state: {
hovered: {
...text(theme.highest, "mono", "on", "hovered"),
background: background(theme.highest, "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"),
background: background(
theme.highest,
"on",
"pressed"
),
border: border(theme.highest, "on", "pressed"),
},
},
})
}
}),
},
}),
search_bar_row_height: 34,
search_bar_row_height: 32,
search_row_spacing: 8,
option_button_height: 22,
modes_container: {},
...search_results()
...search_results(),
}
}
+23 -19
View File
@@ -34,9 +34,11 @@ export default function status_bar(): any {
...text(layer, "mono", "base", { size: "xs" }),
},
active_language: text_button({
color: "base"
color: "base",
}),
auto_update_progress_message: text(layer, "sans", "base", {
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: {
@@ -73,34 +75,36 @@ export default function status_bar(): any {
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: {
@@ -125,7 +129,7 @@ export default function status_bar(): any {
},
clicked: {
background: background(layer, "pressed"),
}
},
},
}),
state: {
+3 -3
View File
@@ -93,7 +93,7 @@ export default function tab_bar(): any {
border: border(theme.lowest, "on", {
bottom: true,
overlay: true,
})
}),
},
state: {
hovered: {
@@ -101,7 +101,7 @@ export default function tab_bar(): any {
background: background(theme.highest, "on", "hovered"),
},
disabled: {
color: foreground(theme.highest, "on", "disabled")
color: foreground(theme.highest, "on", "disabled"),
},
},
})
@@ -162,6 +162,6 @@ export default function tab_bar(): any {
right: false,
},
},
nav_button: nav_button
nav_button: nav_button,
}
}
+11 -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"),
@@ -183,14 +183,12 @@ export function titlebar(): any {
height: 400,
},
// Project
project_name_divider: text(theme.lowest, "sans", "variant"),
project_menu_button: toggleable_text_button(theme, {
color: 'base',
color: "base"
}),
git_menu_button: toggleable_text_button(theme, {
color: 'variant',
color: "variant",
}),
// Collaborators
@@ -263,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 -30
View File
@@ -12,7 +12,7 @@ import tabBar from "./tab_bar"
import { interactive } from "../element"
import { titlebar } from "./titlebar"
import { useTheme } from "../theme"
import { toggleable_icon_button } from "../component/icon_button"
import { toolbar } from "./toolbar"
export default function workspace(): any {
const theme = useTheme()
@@ -128,35 +128,7 @@ export default function workspace(): any {
},
status_bar: statusBar(),
titlebar: titlebar(),
toolbar: {
height: 42,
background: background(theme.highest),
border: border(theme.highest, { bottom: true }),
item_spacing: 8,
toggleable_tool: toggleable_icon_button(theme, {
margin: { left: 8 },
variant: "ghost",
active_color: "accent",
}),
padding: { left: 8, right: 8 },
},
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),