~james/core

core/web/src/lib/components/ui/Segment.svelte -rw-r--r-- 2.0 KiB
452f17b7 — james chore(import): snapshot james.dad.town/core at f70c71c7696a 15 hours ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<script module lang="ts">
	import { tv } from "tailwind-variants";

	export const segment = tv({
		base: "relative z-10 transition-[color] duration-150 hover:bg-transparent",
		variants: {
			selected: {
				true: "text-foreground-default",
				false: "text-foreground-muted hover:text-foreground-default"
			},
			painted: {
				true: "bg-background-default shadow-sm edge-ring-inset hover:bg-background-default",
				false: ""
			},
			collapsed: {
				true: "max-sm:pr-2.25",
				false: ""
			}
		}
	});
</script>

<script lang="ts">
	import type { ComponentProps } from "svelte";
	import Button from "#lib/components/ui/Button.svelte";
	import { getSegmentedControl } from "#lib/components/ui/SegmentedControl.svelte";

	type Props = Omit<ComponentProps<typeof Button>, "variant" | "href" | "role" | "value"> & {
		value: string;
		collapsible?: boolean;
	};

	let {
		value,
		collapsible = false,
		class: className,
		onclick,
		children,
		...rest
	}: Props = $props();

	const control = getSegmentedControl();
	const selected = $derived(control.value === value);
	const href = $derived(control.href?.(value));

	const select = (event: MouseEvent) => {
		onclick?.(event as Parameters<NonNullable<typeof onclick>>[0]);
		if (event.defaultPrevented) return;
		if (
			href &&
			(event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)
		)
			return;
		control.select(value);
	};
</script>

<Button
	data-testid="segment"
	{...rest}
	variant="ghost"
	{href}
	role={href ? undefined : "radio"}
	aria-checked={href ? undefined : selected}
	aria-current={href && selected ? "page" : undefined}
	tabindex={href || selected ? undefined : -1}
	data-segment={value}
	onclick={select}
	class={segment({
		selected,
		painted: selected && !control.ready,
		collapsed: collapsible && !selected,
		class: className
	})}
>
	{#if collapsible && children}
		<span class={selected ? undefined : "max-sm:sr-only"}>{@render children()}</span>
	{:else}
		{@render children?.()}
	{/if}
</Button>