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