text_button.ts

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