shadcn.io is an independent project built on shadcn/ui
An outline icon button shows the current alignment, starting on the left. The menu checks one of Align Left, Align Center, Align Right, or Justify, and the icon follows.
Use it in an editor when the current alignment should stay visible on the button. If the choices should sit on the page, a Toggle Group fits. In React, Base UI stores the value and does not restyle the text.
Installation
Anatomy

Usage
<DropdownMenu>
<DropdownMenuTrigger
render={
<Button
aria-label="Text alignment"
size="icon-md"
variant="outline"
/>
}
>
{alignment === "left" ? <AlignLeftIcon aria-hidden="true" /> : null}
{alignment === "center" ? <AlignCenterIcon aria-hidden="true" /> : null}
{alignment === "right" ? <AlignRightIcon aria-hidden="true" /> : null}
{alignment === "justify" ? (
<AlignJustifyIcon aria-hidden="true" />
) : null}
</DropdownMenuTrigger>
<DropdownMenuContent className="w-48">
<DropdownMenuRadioGroup onValueChange={setAlignment} value={alignment}>
<DropdownMenuRadioItem value="left">
<AlignLeftIcon aria-hidden="true" />
Align Left
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="center">
<AlignCenterIcon aria-hidden="true" />
Align Center
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="right">
<AlignRightIcon aria-hidden="true" />
Align Right
</DropdownMenuRadioItem>
{/* The rest of the file is under Installation. */}FAQ
How does the alignment choice work?
Left starts selected. The values are left, center, right and justify, in one radio group, so picking one unchecks the others.
DropdownMenuRadioGroup takes value, and onValueChange receives the new value. Each DropdownMenuRadioItem has its value.
Why does the trigger icon change?
The button renders the left, center, right or justify icon depending on the current value, so it always shows the active alignment. Each row repeats the same icon before its label.
Why is Justify under a line?
A DropdownMenuSeparator sits inside the radio group, between Align Right and Justify, to set the full-width option apart. It doesn't split the group: Justify still unchecks the others.
How wide is the menu?
The menu is w-48. The trigger is an outline Button with size="icon-md" and aria-label set to Text alignment, since it has no visible text.
API Reference
Dropdown Menu
Sets onValueChange={setAlignment}, value={alignment}, value="left", value="center", value="right" and value="justify". The rest is on the Dropdown Menu page.
Button
Sets aria-label="Text alignment", size="icon-md" and variant="outline". The rest is on the Button page.





