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