Skip to content

DataTableColumnHeader: DropdownMenu doesn't render in Shadow DOM #197

Description

@RomiC

Summary

DataTableColumnHeader uses DropdownMenuContent with portal={true} (the default). In a Shadow DOM context the dropdown portal renders to document.body, outside the shadow root, so the sort options popover never appears — users see the header button but clicking it has no visible effect.

Root cause

DataTableColumnHeader renders DropdownMenuContent without specifying a portal container:

// packages/ui-legacy/src/components/ui/data-table/data-table-column-header.tsx
<DropdownMenuContent align="start">   {/* portal={true} by default */}
  ...
</DropdownMenuContent>

With portal={true}, DropdownMenuContent portals its content via DropdownMenuPortal to document.body. Inside a shadow root, document.body is outside the shadow tree — the dropdown HTML is injected there but the shadow root's adoptedStyleSheets don't apply, so the content either appears unstyled or is hidden behind the shadow host overlay.

Proposed fix

Add a portalContainer prop to DataTableColumnHeader and forward it to DropdownMenuPortal:

interface DataTableColumnHeaderProps<TData, TValue> extends React.HTMLAttributes<HTMLDivElement> {
  column: Column<TData, TValue>;
  title: string;
  portalContainer?: Element | null;  // ← new
}

// inside the render:
<DropdownMenuPortal container={portalContainer}>
  <DropdownMenuContent portal={false} align="start">
    ...
  </DropdownMenuContent>
</DropdownMenuPortal>

Consumers running in Shadow DOM pass their shadow-root container:

<DataTableColumnHeader
  column={column}
  title="Name"
  portalContainer={shadowPortalContainer}
/>

Consumers outside Shadow DOM omit it (defaults to document.body as before).

Environment

  • @acronis-platform/shadcn-uikit v0.35.0
  • Shadow DOM MFE context (micro-frontend with adoptedStyleSheets)
  • Same pattern already affects PopoverContent, SelectContent — both have a portal prop and *Portal companion that consumers use as a workaround

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions