icon_button.ts

 1import { interactive, toggleable } from "../element"
 2import { background, foreground } from "../style_tree/components"
 3import { useTheme, Theme } from "../theme"
 4import { ButtonVariant, Variant } from "./button"
 5
 6export type Margin = {
 7    top: number
 8    bottom: number
 9    left: number
10    right: number
11}
12
13interface IconButtonOptions {
14    layer?:
15    | Theme["lowest"]
16    | Theme["middle"]
17    | Theme["highest"]
18    color?: keyof Theme["lowest"]
19    margin?: Partial<Margin>
20    variant?: Variant
21}
22
23type ToggleableIconButtonOptions = IconButtonOptions & {
24    active_color?: keyof Theme["lowest"]
25}
26
27export function icon_button({ color, margin, layer, variant = ButtonVariant.Default }: IconButtonOptions) {
28    const theme = useTheme()
29
30    if (!color) color = "base"
31
32    const background_color = variant === ButtonVariant.Ghost ? null : background(layer ?? theme.lowest, color)
33
34    const m = {
35        top: margin?.top ?? 0,
36        bottom: margin?.bottom ?? 0,
37        left: margin?.left ?? 0,
38        right: margin?.right ?? 0,
39    }
40
41    return interactive({
42        base: {
43            corner_radius: 6,
44            padding: {
45                top: 2,
46                bottom: 2,
47                left: 4,
48                right: 4,
49            },
50            margin: m,
51            icon_width: 14,
52            icon_height: 14,
53            button_width: 20,
54            button_height: 16,
55        },
56        state: {
57            default: {
58                background: background_color,
59                color: foreground(layer ?? theme.lowest, color),
60            },
61            hovered: {
62                background: background(layer ?? theme.lowest, color, "hovered"),
63                color: foreground(layer ?? theme.lowest, color, "hovered"),
64            },
65            clicked: {
66                background: background(layer ?? theme.lowest, color, "pressed"),
67                color: foreground(layer ?? theme.lowest, color, "pressed"),
68            },
69        },
70    })
71}
72
73export function toggleable_icon_button(
74    theme: Theme,
75    { color, active_color, margin, variant }: ToggleableIconButtonOptions
76) {
77    if (!color) color = "base"
78
79    return toggleable({
80        state: {
81            inactive: icon_button({ color, margin, variant }),
82            active: icon_button({
83                color: active_color ? active_color : color,
84                margin,
85                layer: theme.middle,
86            }),
87        },
88    })
89}