Backstage UI: Add VisuallyHidden component.

Adds a new VisuallyHidden component for hiding content visually while keeping it accessible to screen readers.

Signed-off-by: Johan Persson <johanopersson@gmail.com>
This commit is contained in:
Johan Persson
2025-10-21 10:24:13 +02:00
parent 8a2725b100
commit 1ef3ca48d6
13 changed files with 322 additions and 0 deletions
@@ -0,0 +1,51 @@
import { PropsTable } from '@/components/PropsTable';
import { Snippet } from '@/components/Snippet';
import { CodeBlock } from '@/components/CodeBlock';
import { VisuallyHiddenSnippet } from '@/snippets/stories-snippets';
import {
visuallyHiddenPropDefs,
visuallyHiddenUsageSnippet,
visuallyHiddenDefaultSnippet,
visuallyHiddenExampleUsageSnippet,
} from './visually-hidden.props';
import { PageTitle } from '@/components/PageTitle';
import { Theming } from '@/components/Theming';
import { ChangelogComponent } from '@/components/ChangelogComponent';
<PageTitle
title="VisuallyHidden"
description="Visually hides content while keeping it accessible to screen readers."
/>
<Snippet
align="start"
py={4}
preview={<VisuallyHiddenSnippet story="Default" />}
code={visuallyHiddenDefaultSnippet}
/>
## Usage
<CodeBlock code={visuallyHiddenUsageSnippet} />
## API reference
<PropsTable data={visuallyHiddenPropDefs} />
## Examples
### Example Usage
Here's an example of providing screen reader context for a list of links in a footer.
<Snippet
align="start"
py={4}
preview={<VisuallyHiddenSnippet story="ExampleUsage" />}
code={visuallyHiddenExampleUsageSnippet}
open
/>
<Theming component="VisuallyHidden" />
<ChangelogComponent component="visually-hidden" />
@@ -0,0 +1,47 @@
import {
classNamePropDefs,
stylePropDefs,
type PropDef,
} from '@/utils/propDefs';
export const visuallyHiddenPropDefs: Record<string, PropDef> = {
children: {
type: 'enum',
values: ['ReactNode'],
responsive: false,
},
...classNamePropDefs,
...stylePropDefs,
};
export const visuallyHiddenUsageSnippet = `import { VisuallyHidden } from '@backstage/ui';
<VisuallyHidden>
This content is visually hidden but accessible to screen readers
</VisuallyHidden>`;
export const visuallyHiddenDefaultSnippet = `<Flex direction="column" gap="4">
<Text as="p">
This text is followed by a paragraph that is visually hidden but
accessible to screen readers. Try using a screen reader to hear it, or
inspect the DOM to see it's there.
</Text>
<VisuallyHidden>
This content is visually hidden but accessible to screen readers
</VisuallyHidden>
</Flex>`;
export const visuallyHiddenExampleUsageSnippet = `<Flex direction="column" gap="4">
<VisuallyHidden>
<Text as="h2">Footer links</Text>
</VisuallyHidden>
<Text as="p">
<a href="#">About us</a>
</Text>
<Text as="p">
<a href="#">Jobs</a>
</Text>
<Text as="p">
<a href="#">Terms and Conditions</a>
</Text>
</Flex>`;
@@ -29,6 +29,7 @@ import * as HeaderPageStories from '../../../packages/ui/src/components/HeaderPa
import * as TableStories from '../../../packages/ui/src/components/Table/Table.stories';
import * as TagGroupStories from '../../../packages/ui/src/components/TagGroup/TagGroup.stories';
import * as PasswordFieldStories from '../../../packages/ui/src/components/PasswordField/PasswordField.stories';
import * as VisuallyHiddenStories from '../../../packages/ui/src/components/visuallyHidden/VisuallyHidden.stories';
// Helper function to create snippet components
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -74,3 +75,6 @@ export const HeaderSnippet = createSnippetComponent(HeaderStories);
export const HeaderPageSnippet = createSnippetComponent(HeaderPageStories);
export const TableSnippet = createSnippetComponent(TableStories);
export const TagGroupSnippet = createSnippetComponent(TagGroupStories);
export const VisuallyHiddenSnippet = createSnippetComponent(
VisuallyHiddenStories,
);
+5
View File
@@ -182,6 +182,11 @@ export const components: Page[] = [
slug: 'tooltip',
status: 'alpha',
},
{
title: 'VisuallyHidden',
slug: 'visually-hidden',
status: 'alpha',
},
];
export type ScreenSize = {