EXEPERTAI LAB

Research alpha

Time Machine
EXEPERTAI LAB
GALLERY / COLLECTION
← Browse Astryx gallery
VisuallyHidden·component·@astryxdesign/core

VisuallyHidden

Renders content in the accessibility tree while hiding it visually. Use for accessible names on icon-only controls, aria-live announcement regions, and supplementary screen-reader context. Deliberately has no styling props; the whole point is to stay invisible.

Open in Playground @astryxdesign/core/VisuallyHidden

Showcases and examples

4 documented examples

VisuallyHidden

VisuallyHidden API entry

Preview loads on approachPreview loads on approach
Exact source · visually-hidden-showcase
// Copyright (c) Meta Platforms, Inc. and affiliates.

'use client';

import {VisuallyHidden} from '@astryxdesign/core/VisuallyHidden';
import {IconButton} from '@astryxdesign/core/IconButton';
import {Card} from '@astryxdesign/core/Card';
import {HStack, VStack} from '@astryxdesign/core/Layout';
import {Text} from '@astryxdesign/core/Text';
import {Icon} from '@astryxdesign/core/Icon';
import {
  ArrowDownTrayIcon,
  ShareIcon,
  TrashIcon,
} from '@heroicons/react/24/outline';
import {SpeakerWaveIcon} from '@heroicons/react/24/solid';

const actions = [
  {label: 'Download', icon: ArrowDownTrayIcon},
  {label: 'Share', icon: ShareIcon},
  {label: 'Delete', icon: TrashIcon},
] as const;

/**
 * VisuallyHidden is invisible by design, so this hero teaches the concept by
 * contrast: the icon-only buttons are all a sighted user sees, while the
 * caption spells out the accessible name each one exposes. A live
 * <VisuallyHidden> region below announces the same names to assistive tech,
 * so the demo genuinely exercises the component it documents.
 */
export default function VisuallyHiddenShowcase() {
  return (
    <VStack gap={5} hAlign="center">
      <HStack gap={6} vAlign="stretch" wrap="wrap" hAlign="center">
        <Card variant="muted">
          <VStack gap={4} hAlign="center">
            <Text type="supporting" color="secondary">
              What you see
            </Text>
            <HStack gap={2}>
              {actions.map(({label, icon}) => (
                <IconButton
                  key={label}
                  label={label}
                  icon={<Icon icon={icon} />}
                  variant="ghost"
                />
              ))}
            </HStack>
          </VStack>
        </Card>

        <Card variant="muted">
          <VStack gap={4} hAlign="start">
            <HStack gap={2} vAlign="center">
              <Icon icon={SpeakerWaveIcon} size="sm" />
              <Text type="supporting" color="secondary">
                What a screen reader hears
              </Text>
            </HStack>
            <VStack gap={2}>
              {actions.map(({label}) => (
                <Text key={label} type="body">
                  {label}, button
                </Text>
              ))}
            </VStack>
          </VStack>
        </Card>
      </HStack>

      {/* A real live region: silent to sighted users, announced by AT. */}
      <VisuallyHidden as="div" aria-live="polite">
        Actions available: Download, Share, Delete.
      </VisuallyHidden>
    </VStack>
  );
}

Usage

Renders content in the accessibility tree while hiding it visually. Use for accessible names on icon-only controls, aria-live announcement regions, and supplementary screen-reader context. Deliberately has no styling props; the whole point is to stay invisible.

  • Use to give icon-only buttons and controls an accessible name that screen readers announce.
  • Render as a block element (as="div") with aria-live to announce dynamic updates like drag-and-drop or result counts.
  • Use it to hide content from everyone; it stays in the accessibility tree; use conditional rendering or hidden to remove content entirely.
  • Put interactive controls inside it; the content is not visible and cannot receive pointer input.

Typed props

PropType and behavior
childrenReactNode
Content exposed to assistive technology while hidden from sight.
asElementType · default 'span'
HTML tag to render as. Use a block element for live regions.