59 lines
1.6 KiB
Svelte
59 lines
1.6 KiB
Svelte
<script lang="ts">
|
|
/**
|
|
* SortButtonGroup component - Button group for sorting options
|
|
*
|
|
* @req: UR-007 - Navigate media in library
|
|
* @req: DR-007 - Library browsing screens
|
|
*/
|
|
|
|
export interface SortOption {
|
|
key: string;
|
|
label: string;
|
|
}
|
|
|
|
interface Props {
|
|
options: SortOption[];
|
|
selected: string;
|
|
onSelect: (key: string) => void;
|
|
className?: string;
|
|
}
|
|
|
|
let { options, selected, onSelect, className = "" }: Props = $props();
|
|
|
|
function handleClick(key: string) {
|
|
onSelect(key);
|
|
}
|
|
|
|
function handleKeydown(e: KeyboardEvent, index: number) {
|
|
if (e.key === "ArrowRight" && index < options.length - 1) {
|
|
e.preventDefault();
|
|
onSelect(options[index + 1].key);
|
|
} else if (e.key === "ArrowLeft" && index > 0) {
|
|
e.preventDefault();
|
|
onSelect(options[index - 1].key);
|
|
} else if (e.key === "Enter" || e.key === " ") {
|
|
e.preventDefault();
|
|
onSelect(options[index].key);
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<div class={`flex flex-wrap gap-2 ${className}`}>
|
|
{#each options as option, index (option.key)}
|
|
<button
|
|
onclick={() => handleClick(option.key)}
|
|
onkeydown={(e) => handleKeydown(e, index)}
|
|
role="radio"
|
|
aria-checked={selected === option.key}
|
|
tabindex={selected === option.key ? 0 : -1}
|
|
class={`px-4 py-3 rounded-lg font-medium transition-colors ${
|
|
selected === option.key
|
|
? "bg-[var(--color-jellyfin)] text-white"
|
|
: "bg-[var(--color-surface)] text-gray-300 hover:bg-[var(--color-surface-hover)]"
|
|
}`}
|
|
>
|
|
{option.label}
|
|
</button>
|
|
{/each}
|
|
</div>
|