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?:
 14    | Theme["lowest"]
 15    | Theme["middle"]
 16    | Theme["highest"]
 17    variant?: Button.Variant
 18    color?: keyof Theme["lowest"]
 19    margin?: Partial<Margin>
 20    disabled?: boolean
 21    text_properties?: TextProperties
 22}
 23
 24type ToggleableTextButtonOptions = TextButtonOptions & {
 25    active_color?: keyof Theme["lowest"]
 26}
 27
 28export function text_button({
 29    variant = Button.variant.Default,
 30    color,
 31    layer,
 32    margin,
 33    disabled,
 34    text_properties,
 35}: TextButtonOptions = {}) {
 36    const theme = useTheme()
 37    if (!color) color = "base"
 38
 39    const background_color = variant === Button.variant.Ghost ? null : 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:
 71                    disabled
 72                        ? foreground(layer ?? theme.lowest, "disabled")
 73                        : foreground(layer ?? theme.lowest, color),
 74            },
 75            hovered:
 76                disabled ? {} : {
 77                    background: background(layer ?? theme.lowest, color, "hovered"),
 78                    color: foreground(layer ?? theme.lowest, color, "hovered"),
 79                },
 80            clicked: disabled ? {} : {
 81                background: background(layer ?? theme.lowest, color, "pressed"),
 82                color: foreground(layer ?? theme.lowest, color, "pressed"),
 83            },
 84        },
 85    })
 86}
 87
 88export function toggleable_text_button(
 89    theme: Theme,
 90    { variant, color, active_color, margin }: ToggleableTextButtonOptions = {}
 91) {
 92    if (!color) color = "base"
 93
 94    return toggleable({
 95        state: {
 96            inactive: text_button({ variant, color, margin }),
 97            active: text_button({
 98                variant,
 99                color: active_color ? active_color : color,
100                margin,
101                layer: theme.middle,
102            }),
103        },
104    })
105}