<script module lang="ts">
import { tv, type VariantProps } from "tailwind-variants";
export const buttonGroup = tv({
base: "inline-flex items-center",
variants: {
spaced: {
true: "gap-xs",
false: [
// isolate keeps the z-10 segments and z-20 outline ordered inside the
// group instead of against page chrome like the topbar search dropdown
"relative isolate items-stretch gap-none overflow-hidden rounded-md bg-background-subtle [--btn-press:1] dark:bg-background-canvas",
"after:pointer-events-none after:absolute after:inset-0 after:z-20 after:rounded-md after:border after:border-border-default after:content-['']",
"*:relative",
"[&>*:not(:first-child)]:-ml-px [&>*:not(:first-child)]:[--btn-radius-l:0px]",
"[&>*:not(:last-child)]:[--btn-radius-r:0px]",
// a Dropdown keeps its trigger one level down, and the radius vars only
// inherit that far — Button re-declares them on itself, so the wrapper's
// value loses. reach the nested trigger directly.
"[&>*:not(:first-child)>button]:[--btn-radius-l:0px]",
"[&>*:not(:last-child)>button]:[--btn-radius-r:0px]",
"[&>*:not([data-variant=ghost])]:z-10",
"[&>*:focus-visible]:-outline-offset-2"
]
},
direction: {
horizontal: [""],
vertical: ["flex-col"]
}
},
defaultVariants: {
spaced: false,
direction: "horizontal"
}
});
export type ButtonGroupVariants = VariantProps<typeof buttonGroup>;
</script>
<script lang="ts">
import type { Snippet } from "svelte";
import type { HTMLAttributes } from "svelte/elements";
interface Props extends Omit<HTMLAttributes<HTMLDivElement>, "class" | "children"> {
spaced?: ButtonGroupVariants["spaced"];
direction?: ButtonGroupVariants["direction"];
class?: string;
children: Snippet;
}
let {
spaced = false,
direction = "horizontal",
class: className,
children,
...rest
}: Props = $props();
const classes = $derived(buttonGroup({ spaced, direction, class: className }));
</script>
<div class={classes} {...rest}>
{@render children()}
</div>