text_button.ts

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