···1515 import { Accordion } from "melt/builders";
1616 import type { Snippet } from "svelte";
1717 import { page } from "$app/state";
1818+ import { roving } from "$lib";
1819 import Fa from "svelte-fa";
19202021 let { tabs }: { tabs: { label: string; icon: IconDefinition; content: Snippet<[]> }[] } = $props();
···4445 class:flexc={isMobile()}
4546 class="flexr gap-10"
4647 style:width={isMobile() ? "100%" : "fit-content"}
4848+ {@attach roving("button")}
4749 >
4850 {#each tabs as tab (tab.label)}
4951 {@const item = accordion.getItem({ id: tab.label })}
+10
packages/panel/src/lib/index.ts
···11import { faTriangleExclamation } from "@fortawesome/free-solid-svg-icons";
22import { faCircleXmark } from "@fortawesome/free-regular-svg-icons";
33+import type { Attachment } from "svelte/attachments";
34import { addToast } from "../routes/Toaster.svelte";
55+import { rovingIndex } from "roving-ux";
4657export { openDialog, closeDialog } from "../routes/Dialog.svelte";
6879export * as api from "./api";
810911export { isMobile } from "../routes/+layout.svelte";
1212+1313+/// An attachment that applies roving behavior to the attached element. Allowing its children to be navigated with arrow keys.
1414+export const roving: (target?: string) => Attachment<HTMLElement> = (target) => (element) => {
1515+ rovingIndex({
1616+ target: target ?? "& > a, button",
1717+ element,
1818+ });
1919+};
10201121/**
1222 * Trims {@paramstr} to {@param maxLength}, adding ellipses if it was too long.