Tab: fix aria-controls
When porting, I thought I was being clever by just using ids instead of refs in $api.panels But I didn't notice that the refs let you distinguish those panels which are rendered from those which are not. My implementation had aria-controls= set for all tabs, even when their panels were not in the DOM.
This commit is contained in:
@@ -87,11 +87,12 @@
|
|||||||
$api.setSelectedIndex(myIndex);
|
$api.setSelectedIndex(myIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$: myPanelRef = $api.panels[myIndex]?.ref;
|
||||||
$: propsWeControl = {
|
$: propsWeControl = {
|
||||||
id,
|
id,
|
||||||
role: "tab",
|
role: "tab",
|
||||||
type: resolveButtonType({ type: $$props.type, as }, tabRef),
|
type: resolveButtonType({ type: $$props.type, as }, tabRef),
|
||||||
"aria-controls": $api.panels[myIndex],
|
"aria-controls": $myPanelRef ? $api.panels[myIndex]?.id : undefined,
|
||||||
"aria-selected": selected,
|
"aria-selected": selected,
|
||||||
tabIndex: selected ? 0 : -1,
|
tabIndex: selected ? 0 : -1,
|
||||||
disabled: disabled ? true : undefined,
|
disabled: disabled ? true : undefined,
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
<script lang="ts" context="module">
|
<script lang="ts" context="module">
|
||||||
|
interface PanelData {
|
||||||
|
id: string;
|
||||||
|
ref: Readable<HTMLElement | null>;
|
||||||
|
}
|
||||||
export type StateDefinition = {
|
export type StateDefinition = {
|
||||||
// State
|
// State
|
||||||
selectedIndex: number | null;
|
selectedIndex: number | null;
|
||||||
@@ -6,14 +10,14 @@
|
|||||||
activation: "auto" | "manual";
|
activation: "auto" | "manual";
|
||||||
|
|
||||||
tabs: (HTMLElement | null)[];
|
tabs: (HTMLElement | null)[];
|
||||||
panels: string[];
|
panels: PanelData[];
|
||||||
|
|
||||||
// State mutators
|
// State mutators
|
||||||
setSelectedIndex(index: number): void;
|
setSelectedIndex(index: number): void;
|
||||||
registerTab(tab: HTMLElement | null): void;
|
registerTab(tab: HTMLElement | null): void;
|
||||||
unregisterTab(tab: HTMLElement | null): void;
|
unregisterTab(tab: HTMLElement | null): void;
|
||||||
registerPanel(panel: string): void;
|
registerPanel(panel: PanelData): void;
|
||||||
unregisterPanel(panel: string): void;
|
unregisterPanel(panel: PanelData): void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const TABS_CONTEXT_NAME = "headlessui-tabs-context";
|
const TABS_CONTEXT_NAME = "headlessui-tabs-context";
|
||||||
|
|||||||
@@ -7,20 +7,24 @@
|
|||||||
import type { SupportedAs } from "$lib/internal/elements";
|
import type { SupportedAs } from "$lib/internal/elements";
|
||||||
import type { HTMLActionArray } from "$lib/hooks/use-actions";
|
import type { HTMLActionArray } from "$lib/hooks/use-actions";
|
||||||
import Render, { Features } from "$lib/utils/Render.svelte";
|
import Render, { Features } from "$lib/utils/Render.svelte";
|
||||||
|
import { writable, Writable } from "svelte/store";
|
||||||
const forwardEvents = forwardEventsBuilder(get_current_component());
|
const forwardEvents = forwardEventsBuilder(get_current_component());
|
||||||
|
|
||||||
export let as: SupportedAs = "div";
|
export let as: SupportedAs = "div";
|
||||||
export let use: HTMLActionArray = [];
|
export let use: HTMLActionArray = [];
|
||||||
|
|
||||||
|
let elementRef: Writable<HTMLElement | null> = writable(null);
|
||||||
let api = useTabsContext("TabPanel");
|
let api = useTabsContext("TabPanel");
|
||||||
let id = `headlessui-tabs-panel-${useId()}`;
|
let id = `headlessui-tabs-panel-${useId()}`;
|
||||||
|
|
||||||
|
$: panelData = { id, ref: elementRef };
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
$api.registerPanel(id);
|
$api.registerPanel(panelData);
|
||||||
return () => $api.unregisterPanel(id);
|
return () => $api.unregisterPanel(panelData);
|
||||||
});
|
});
|
||||||
|
|
||||||
$: myIndex = $api.panels.indexOf(id);
|
$: myIndex = $api.panels.indexOf(panelData);
|
||||||
$: selected = myIndex === $api.selectedIndex;
|
$: selected = myIndex === $api.selectedIndex;
|
||||||
|
|
||||||
$: propsWeControl = {
|
$: propsWeControl = {
|
||||||
@@ -36,6 +40,7 @@
|
|||||||
{as}
|
{as}
|
||||||
use={[...use, forwardEvents]}
|
use={[...use, forwardEvents]}
|
||||||
name={"TabPanel"}
|
name={"TabPanel"}
|
||||||
|
bind:el={$elementRef}
|
||||||
visible={selected}
|
visible={selected}
|
||||||
features={Features.RenderStrategy | Features.Static}
|
features={Features.RenderStrategy | Features.Static}
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user