Skip to content

@radix-ui/react-dialog: Accessibility error inside shadow dom #3484

@nayounsang

Description

@nayounsang

Bug report

Current Behavior

  • Even if I write a Title inside Content, the following error occurs
`DialogContent` requires a `DialogTitle` for the component to be accessible for screen reader users.

If you want to hide the `DialogTitle`, you can wrap it with our VisuallyHidden component.

For more information, see 

...
<Dialog.Content>
  <Dialog.Title>Hello World</Dialog.Title>
</Dialog.Content>

Expected behavior

  • If the title exists, an error should not occur

Reproducible example

CodeSandbox Template

import React, { useRef, useState } from "react";
import root from "react-shadow";
import {
  Dialog,
  DialogTrigger,
  DialogContent,
  DialogTitle,
  DialogDescription,
  DialogPortal,
  DialogOverlay,
} from "@radix-ui/react-dialog";
import { VisuallyHidden } from "@radix-ui/react-visually-hidden";

export default function App() {
  const [open, setOpen] = useState(false);
  const [container, setContainer] = useState<HTMLDivElement | null>(null);

  return (
    <Dialog open={open} onOpenChange={setOpen}>
      <DialogTrigger asChild>
        <button>Open Dialog</button>
      </DialogTrigger>

      <root.div>
        <div
          ref={setContainer}
          style={{ position: "relative", zIndex: 9999, inset: 0 }}
        >
          {container && (
            <DialogPortal container={container}>
              <DialogOverlay
                style={{
                  position: "fixed",
                  inset: 0,
                  backgroundColor: "rgba(0,0,0,0.4)",
                }}
              />
              <DialogContent
                style={{
                  background: "white",
                  padding: "2rem",
                  borderRadius: "1rem",
                  position: "fixed",
                  top: "50%",
                  left: "50%",
                  transform: "translate(-50%, -50%)",
                }}
              >
                <DialogTitle>Test Dialog</DialogTitle>
                <DialogDescription>
                  This is a test dialog inside Shadow DOM.
                </DialogDescription>
                <button onClick={() => setOpen(false)}>Close</button>
              </DialogContent>
            </DialogPortal>
          )}
        </div>
      </root.div>
    </Dialog>
  );
}

Suggested solution

We need to figure out how error validation logic works.
See

const TitleWarning: React.FC<TitleWarningProps> = ({ titleId }) => {
  const titleWarningContext = useWarningContext(TITLE_WARNING_NAME);

  const MESSAGE = `\`${titleWarningContext.contentName}\` requires a \`${titleWarningContext.titleName}\` for the component to be accessible for screen reader users.

If you want to hide the \`${titleWarningContext.titleName}\`, you can wrap it with our VisuallyHidden component.

For more information, see https://radix-ui.com/primitives/docs/components/${titleWarningContext.docsSlug}`;

  React.useEffect(() => {
    if (titleId) {
      const hasTitle = document.getElementById(titleId);
      if (!hasTitle) console.error(MESSAGE);
    }
  }, [MESSAGE, titleId]);

  return null;
};

Additional context

useId and VisuallyHidden do not work.
This also applies to description related warnings.

Your environment

Software Name(s) Version
Radix Package(s) "@radix-ui/react-dialog 1.1.6
React n/a 18
Browser chrome 134.0.6998.118
Assistive tech
Node n/a 20
npm/yarn/pnpm yarn 4
Operating System mac 14

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions