1import { interactive, toggleable } from "../element"
2import { background, foreground } from "../style_tree/components"
3import { useTheme, Theme, Layer } from "../theme"
4import { Button } from "./button"
5
6export type Margin = {
7 top: number
8 bottom: number
9 left: number
10 right: number
11}
12
13interface IconButtonOptions {
14 layer?: Theme["lowest"] | Theme["middle"] | Theme["highest"]
15 color?: keyof Theme["lowest"]
16 background_color?: keyof Theme["lowest"]
17 margin?: Partial<Margin>
18 variant?: Button.Variant
19 size?: Button.Size
20}
21
22type ToggleableIconButtonOptions = IconButtonOptions & {
23 active_color?: keyof Theme["lowest"]
24 active_background_color?: keyof Theme["lowest"]
25 active_layer?: Layer
26 active_variant?: Button.Variant
27}
28
29export function icon_button(
30 { color, background_color, margin, layer, variant, size }: IconButtonOptions = {
31 variant: Button.variant.Default,
32 size: Button.size.Medium,
33 }
34) {
35 const theme = useTheme()
36
37 if (!color) color = "base"
38
39 const default_background =
40 variant === Button.variant.Ghost
41 ? null
42 : background(layer ?? theme.lowest, background_color ?? color)
43
44 const m = {
45 top: margin?.top ?? 0,
46 bottom: margin?.bottom ?? 0,
47 left: margin?.left ?? 0,
48 right: margin?.right ?? 0,
49 }
50
51 const padding = {
52 top: size === Button.size.Small ? 2 : 2,
53 bottom: size === Button.size.Small ? 2 : 2,
54 left: size === Button.size.Small ? 2 : 4,
55 right: size === Button.size.Small ? 2 : 4,
56 }
57
58 return interactive({
59 base: {
60 corner_radius: 6,
61 padding: padding,
62 margin: m,
63 icon_width: 14,
64 icon_height: 14,
65 button_width: size === Button.size.Small ? 16 : 20,
66 button_height: 14,
67 },
68 state: {
69 default: {
70 background: default_background,
71 color: foreground(layer ?? theme.lowest, color),
72 },
73 hovered: {
74 background: background(layer ?? theme.lowest, background_color ?? color, "hovered"),
75 color: foreground(layer ?? theme.lowest, color, "hovered"),
76 },
77 clicked: {
78 background: background(layer ?? theme.lowest, background_color ?? color, "pressed"),
79 color: foreground(layer ?? theme.lowest, color, "pressed"),
80 },
81 },
82 })
83}
84
85export function toggleable_icon_button({
86 color,
87 background_color,
88 active_color,
89 active_background_color,
90 active_variant,
91 margin,
92 variant,
93 size,
94 active_layer,
95}: ToggleableIconButtonOptions) {
96 if (!color) color = "base"
97
98 return toggleable({
99 state: {
100 inactive: icon_button({ color, background_color, margin, variant, size }),
101 active: icon_button({
102 color: active_color ? active_color : color,
103 background_color: active_background_color ? active_background_color : background_color,
104 margin,
105 layer: active_layer,
106 variant: active_variant || variant,
107 size,
108 }),
109 },
110 })
111}