From a1e789171e7d8e63db35f805b5f1bb396074f87c Mon Sep 17 00:00:00 2001 From: Jonas Carlsen Date: Mon, 8 Sep 2025 12:59:01 +0200 Subject: [PATCH] feat: skip non-accessible content --- .../src/Embed/UuDisclaimerEmbed.stories.tsx | 30 +++++++++++++++- .../ndla-ui/src/Embed/UuDisclaimerEmbed.tsx | 36 ++++++++++++++++--- packages/ndla-ui/src/locale/messages-en.ts | 6 +++- packages/ndla-ui/src/locale/messages-nb.ts | 6 +++- packages/ndla-ui/src/locale/messages-nn.ts | 6 +++- packages/ndla-ui/src/locale/messages-se.ts | 6 +++- packages/types-embed/src/uuDisclaimerTypes.ts | 1 + 7 files changed, 82 insertions(+), 9 deletions(-) diff --git a/packages/ndla-ui/src/Embed/UuDisclaimerEmbed.stories.tsx b/packages/ndla-ui/src/Embed/UuDisclaimerEmbed.stories.tsx index c841b8cc9d..d244a00c5d 100644 --- a/packages/ndla-ui/src/Embed/UuDisclaimerEmbed.stories.tsx +++ b/packages/ndla-ui/src/Embed/UuDisclaimerEmbed.stories.tsx @@ -7,7 +7,7 @@ */ import type { Meta, StoryObj } from "@storybook/react"; -import { ExpandableBox, ExpandableBoxSummary, FramedContent, PageContent } from "@ndla/primitives"; +import { Button, ExpandableBox, ExpandableBoxSummary, FramedContent, PageContent } from "@ndla/primitives"; import type { UUDisclaimerData, UuDisclaimerEmbedData } from "@ndla/types-embed"; import H5pEmbed from "./H5pEmbed"; import IframeEmbed from "./IframeEmbed"; @@ -199,3 +199,31 @@ export const Error: StoryObj = { ), }, }; + +export const SkipContent: StoryObj = { + args: { + embed: { + resource: "uu-disclaimer", + status: "success", + embedData: { ...embedData, skipContent: "true" }, + data, + }, + children: ( +
+

Dette er noe ugyldig innhold

+ +

+ Innholdet kan enkelt hoppes over ved å bruke knappen skip-knappen som dukker opp når du bruker + tastaturnavigering inne i popoveren. +

+
+ ), + }, + render: (args) => ( + <> + +

Dette er noe gyldig innhold

+ + + ), +}; diff --git a/packages/ndla-ui/src/Embed/UuDisclaimerEmbed.tsx b/packages/ndla-ui/src/Embed/UuDisclaimerEmbed.tsx index e863707af5..504bc576b1 100644 --- a/packages/ndla-ui/src/Embed/UuDisclaimerEmbed.tsx +++ b/packages/ndla-ui/src/Embed/UuDisclaimerEmbed.tsx @@ -6,12 +6,13 @@ * */ -import { type ReactNode } from "react"; +import { useRef, type ReactNode } from "react"; import { useTranslation } from "react-i18next"; import { Portal } from "@ark-ui/react"; import { AccessibilityFill, ErrorWarningFill } from "@ndla/icons"; -import { IconButton, PopoverContent, PopoverRoot, PopoverTrigger } from "@ndla/primitives"; +import { Button, IconButton, PopoverContent, PopoverRoot, PopoverTrigger } from "@ndla/primitives"; import { styled } from "@ndla/styled-system/jsx"; +import { visuallyHidden } from "@ndla/styled-system/patterns"; import type { UuDisclaimerMetaData } from "@ndla/types-embed"; interface Props { @@ -44,14 +45,35 @@ const StyledErrorWarningFill = styled(ErrorWarningFill, { const StyledPopoverContent = styled(PopoverContent, { base: { + display: "flex", + flexDirection: "column", + gap: "xsmall", width: "surface.xlarge", maxHeight: "50vh", overflowY: "auto", }, }); +const HiddenButton = styled(Button, { + base: { + "&:not(:focus)": { + position: "absolute", + width: "1px", + height: "1px", + padding: "0", + margin: "-1px", + overflow: "hidden", + clip: "rect(0,0,0,0)", + whiteSpace: "nowrap", + borderWidth: "0", + }, + }, +}); + const UuDisclaimerEmbed = ({ embed, transformedDisclaimer, children }: Props) => { const { t } = useTranslation(); + const skipRef = useRef(null); + const contentRef = useRef(null); if (embed.status === "error") { return ( @@ -66,7 +88,7 @@ const UuDisclaimerEmbed = ({ embed, transformedDisclaimer, children }: Props) => return ( - + contentRef.current}> - +
{transformedDisclaimer}
+ {embed.embedData.skipContent === "true" && ( + skipRef.current?.focus()}>{t("uuDisclaimer.skipContent")} + )}
{children}
+
+ {t("uuDisclaimer.contentCompleted")} +
); }; diff --git a/packages/ndla-ui/src/locale/messages-en.ts b/packages/ndla-ui/src/locale/messages-en.ts index 15ec149ab6..6763f6485d 100644 --- a/packages/ndla-ui/src/locale/messages-en.ts +++ b/packages/ndla-ui/src/locale/messages-en.ts @@ -307,7 +307,11 @@ const messages = { disclaimer: "Accessibility warning", }, }, - uuDisclaimer: { title: "Accessibility" }, + uuDisclaimer: { + title: "Accessibility", + skipContent: "Skip non-accessible content", + contentCompleted: "End of non-accessible content.", + }, gloss: { examples: "Examples", showExamples: "Show examples", diff --git a/packages/ndla-ui/src/locale/messages-nb.ts b/packages/ndla-ui/src/locale/messages-nb.ts index 850e1fb22f..06b75ef552 100644 --- a/packages/ndla-ui/src/locale/messages-nb.ts +++ b/packages/ndla-ui/src/locale/messages-nb.ts @@ -308,7 +308,11 @@ const messages = { disclaimer: "UU-advarsel", }, }, - uuDisclaimer: { title: "Tilgjengelighet" }, + uuDisclaimer: { + title: "Tilgjengelighet", + skipContent: "Hopp over ikke-tilgjengelig innhold", + contentCompleted: "Slutt på ikke-tilgjengelig innhold.", + }, gloss: { examples: "Eksempler", showExamples: "Vis eksempler", diff --git a/packages/ndla-ui/src/locale/messages-nn.ts b/packages/ndla-ui/src/locale/messages-nn.ts index a4528754bd..0673df407a 100644 --- a/packages/ndla-ui/src/locale/messages-nn.ts +++ b/packages/ndla-ui/src/locale/messages-nn.ts @@ -308,7 +308,11 @@ const messages = { disclaimer: "UU-advarsel", }, }, - uuDisclaimer: { title: "Tilgjengelighet" }, + uuDisclaimer: { + title: "Tilgjengelighet", + skipContent: "Hopp over ikkje-tilgjengeleg innhald", + contentCompleted: "Slutt på ikkje-tilgjengeleg innhald.", + }, gloss: { examples: "Eksempler", showExamples: "Vis eksempler", diff --git a/packages/ndla-ui/src/locale/messages-se.ts b/packages/ndla-ui/src/locale/messages-se.ts index 9cd35054fe..f8cf7e65f1 100644 --- a/packages/ndla-ui/src/locale/messages-se.ts +++ b/packages/ndla-ui/src/locale/messages-se.ts @@ -309,7 +309,11 @@ const messages = { disclaimer: "UU-advarsel", }, }, - uuDisclaimer: { title: "Tilgjengelighet" }, + uuDisclaimer: { + title: "Tilgjengelighet", + skipContent: "Hopp over ikke-tilgjengelig innhold", + contentCompleted: "Slutt på ikke-tilgjengelig innhold.", + }, gloss: { examples: "Ovdamearkkat", showExamples: "Vis eksempler", diff --git a/packages/types-embed/src/uuDisclaimerTypes.ts b/packages/types-embed/src/uuDisclaimerTypes.ts index f960fca74c..5b074b41fd 100644 --- a/packages/types-embed/src/uuDisclaimerTypes.ts +++ b/packages/types-embed/src/uuDisclaimerTypes.ts @@ -10,6 +10,7 @@ import type { MetaData } from "./baseTypes"; export interface UuDisclaimerEmbedData { resource: "uu-disclaimer"; + skipContent?: string; disclaimer: string; }