Style cleanup for channels panel

This commit is contained in:
Nate Butler
2023-08-16 12:38:44 -04:00
parent 0524abf114
commit 6c15636ccc
7 changed files with 241 additions and 45 deletions
+117 -5
View File
@@ -1,6 +1,118 @@
export const ButtonVariant = {
Default: 'default',
Ghost: 'ghost'
} as const
import { font_sizes, useTheme } from "../common"
import { Layer, Theme } from "../theme"
import { TextStyle, background } from "../style_tree/components"
export type Variant = typeof ButtonVariant[keyof typeof ButtonVariant]
// 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
}
}
+22 -14
View File
@@ -1,7 +1,7 @@
import { interactive, toggleable } from "../element"
import { background, foreground } from "../style_tree/components"
import { useTheme, Theme } from "../theme"
import { ButtonVariant, Variant } from "./button"
import { useTheme, Theme, Layer } from "../theme"
import { Button } from "./button"
export type Margin = {
top: number
@@ -17,19 +17,24 @@ interface IconButtonOptions {
| Theme["highest"]
color?: keyof Theme["lowest"]
margin?: Partial<Margin>
variant?: Variant
variant?: Button.Variant
size?: Button.Size
}
type ToggleableIconButtonOptions = IconButtonOptions & {
active_color?: keyof Theme["lowest"]
active_layer?: Layer
}
export function icon_button({ color, margin, layer, variant = ButtonVariant.Default }: IconButtonOptions) {
export function icon_button({ color, margin, layer, variant, size }: IconButtonOptions = {
variant: Button.variant.Default,
size: Button.size.Medium,
}) {
const theme = useTheme()
if (!color) color = "base"
const background_color = variant === ButtonVariant.Ghost ? null : background(layer ?? theme.lowest, color)
const background_color = variant === Button.variant.Ghost ? null : background(layer ?? theme.lowest, color)
const m = {
top: margin?.top ?? 0,
@@ -38,15 +43,17 @@ export function icon_button({ color, margin, layer, variant = ButtonVariant.Defa
right: margin?.right ?? 0,
}
const padding = {
top: size === Button.size.Small ? 0 : 2,
bottom: size === Button.size.Small ? 0 : 2,
left: size === Button.size.Small ? 0 : 4,
right: size === Button.size.Small ? 0 : 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,
@@ -72,17 +79,18 @@ export function icon_button({ color, margin, layer, variant = ButtonVariant.Defa
export function toggleable_icon_button(
theme: Theme,
{ color, active_color, margin, variant }: ToggleableIconButtonOptions
{ color, active_color, margin, variant, size, active_layer }: ToggleableIconButtonOptions
) {
if (!color) color = "base"
return toggleable({
state: {
inactive: icon_button({ color, margin, variant }),
inactive: icon_button({ color, margin, variant, size }),
active: icon_button({
color: active_color ? active_color : color,
margin,
layer: theme.middle,
layer: active_layer,
size
}),
},
})
+78
View File
@@ -0,0 +1,78 @@
import { Interactive, interactive, toggleable, Toggleable } from "../element"
import { TextStyle, background, text } from "../style_tree/components"
import { useTheme } from "../theme"
import { Button } from "./button"
type LabelButtonStyle = {
corder_radius: number
background: string | null
padding: {
top: number
bottom: number
left: number
right: number
},
margin: Button.Options['margin']
button_height: number
} & TextStyle
/** Styles an Interactive&lt;ContainedText> */
export function label_button_style(
options: Partial<Button.Options> = {
variant: Button.variant.Default,
shape: Button.shape.Rectangle,
states: {
hovered: true,
pressed: true
}
}
): Interactive<LabelButtonStyle> {
const theme = useTheme()
const base = Button.button_base(options)
const layer = options.layer ?? theme.middle
const color = options.color ?? "base"
const default_state = {
...base,
...text(layer ?? theme.lowest, "sans", color),
font_size: Button.FONT_SIZE,
}
return interactive({
base: default_state,
state: {
hovered: {
background: background(layer, options.background ?? color, "hovered")
},
clicked: {
background: background(layer, options.background ?? color, "pressed")
}
}
})
}
/** Styles an Toggleable&lt;Interactive&lt;ContainedText>> */
export function toggle_label_button_style(
options: Partial<Button.ToggleableOptions> = {
variant: Button.variant.Default,
shape: Button.shape.Rectangle,
states: {
hovered: true,
pressed: true
}
}
): Toggleable<Interactive<LabelButtonStyle>> {
const activeOptions = {
...options,
color: options.active_color || options.color,
background: options.active_background || options.background
}
return toggleable({
state: {
inactive: label_button_style(options),
active: label_button_style(activeOptions),
},
})
}
+4 -4
View File
@@ -6,7 +6,7 @@ import {
text,
} from "../style_tree/components"
import { useTheme, Theme } from "../theme"
import { ButtonVariant, Variant } from "./button"
import { Button } from "./button"
import { Margin } from "./icon_button"
interface TextButtonOptions {
@@ -14,7 +14,7 @@ interface TextButtonOptions {
| Theme["lowest"]
| Theme["middle"]
| Theme["highest"]
variant?: Variant
variant?: Button.Variant
color?: keyof Theme["lowest"]
margin?: Partial<Margin>
text_properties?: TextProperties
@@ -25,7 +25,7 @@ type ToggleableTextButtonOptions = TextButtonOptions & {
}
export function text_button({
variant = ButtonVariant.Default,
variant = Button.variant.Default,
color,
layer,
margin,
@@ -34,7 +34,7 @@ export function text_button({
const theme = useTheme()
if (!color) color = "base"
const background_color = variant === ButtonVariant.Ghost ? null : background(layer ?? theme.lowest, color)
const background_color = variant === Button.variant.Ghost ? null : background(layer ?? theme.lowest, color)
const text_options: TextProperties = {
size: "xs",