This repository has no description
1<script module lang="ts">
2 import { tv, type VariantProps } from "tailwind-variants";
3 import type { ButtonVariants } from "./Button.svelte";
4
5 export const buttonGroup = tv({
6 base: "inline-flex items-center",
7 variants: {
8 spaced: {
9 true: "gap-2",
10 false: [
11 "items-stretch gap-0 overflow-hidden rounded-sm border border-border-default bg-background-subtle dark:bg-background-canvas",
12 "*:relative *:border-y-0",
13 "[&>*:first-child]:-ml-px [&>*:last-child]:-mr-px",
14 "[&>*:not(:first-child)]:-ml-px [&>*:not(:first-child)]:[--btn-radius-l:0px]",
15 "[&>*:not(:last-child)]:[--btn-radius-r:0px]",
16 // children overlap by 1px so adjacent borders collapse into a single seam, which
17 // also means a child's fill paints into its neighbour's border column. ghost
18 // segments have a transparent border and nothing to repaint there, so every
19 // bordered child has to sit above them — otherwise hovering a ghost rubs out the
20 // selected segment's border on whichever edge they share.
21 "[&>*:not([data-variant=ghost])]:z-10",
22 // the group clips overflow, so an outward focus ring gets cut off at its edges and
23 // by bordered neighbours. draw it inside the child instead.
24 "[&>*:focus-visible]:-outline-offset-2"
25 ]
26 }
27 },
28 defaultVariants: {
29 spaced: false
30 }
31 });
32
33 export type ButtonGroupVariants = VariantProps<typeof buttonGroup>;
34
35 export function segmentProps(selected: boolean): {
36 variant: ButtonVariants["variant"];
37 insetShadow: boolean;
38 class?: string;
39 } {
40 return selected
41 ? { variant: "default", insetShadow: true }
42 : { variant: "ghost", insetShadow: false, class: "text-foreground-default" };
43 }
44</script>
45
46<script lang="ts">
47 import type { Snippet } from "svelte";
48
49 interface Props {
50 spaced?: ButtonGroupVariants["spaced"];
51 class?: string;
52 children: Snippet;
53 }
54
55 let { spaced = false, class: className, children, ...rest }: Props = $props();
56
57 const classes = $derived(buttonGroup({ spaced, class: className }));
58</script>
59
60<div class={classes} {...rest}>
61 {@render children()}
62</div>