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