|
| 1 | +import { SectionShell } from "@/components/design-system/SectionShell"; |
| 2 | +import { ButtonDropdown } from "@/components/ui/button-dropdown"; |
| 3 | +import { |
| 4 | + DropdownMenuItem, |
| 5 | + DropdownMenuSeparator, |
| 6 | +} from "@/components/ui/dropdown-menu"; |
| 7 | +import { ArrowRight, Copy, Pause, Trash2 } from "lucide-react"; |
| 8 | + |
| 9 | +const code = `import { ButtonDropdown } from "@/components/ui/button-dropdown"; |
| 10 | +import { |
| 11 | + DropdownMenuItem, |
| 12 | + DropdownMenuSeparator, |
| 13 | +} from "@/components/ui/dropdown-menu"; |
| 14 | +import { ArrowRight, Pause, Trash2 } from "lucide-react"; |
| 15 | +
|
| 16 | +<ButtonDropdown |
| 17 | + action={<>Greenlight <ArrowRight className="h-4 w-4" /></>} |
| 18 | + onClick={() => doPrimary()} |
| 19 | +> |
| 20 | + <DropdownMenuItem onSelect={() => doPark()}> |
| 21 | + <Pause /> Park |
| 22 | + </DropdownMenuItem> |
| 23 | + <DropdownMenuSeparator /> |
| 24 | + <DropdownMenuItem destructive onSelect={() => doDiscard()}> |
| 25 | + <Trash2 /> Discard |
| 26 | + </DropdownMenuItem> |
| 27 | +</ButtonDropdown> |
| 28 | +
|
| 29 | +<ButtonDropdown |
| 30 | + variant="secondary" |
| 31 | + action="Duplicate" |
| 32 | + onClick={() => doDuplicate()} |
| 33 | +> |
| 34 | + <DropdownMenuItem onSelect={() => doDuplicateAs()}> |
| 35 | + Duplicate as draft |
| 36 | + </DropdownMenuItem> |
| 37 | + <DropdownMenuItem onSelect={() => doExport()}> |
| 38 | + Export |
| 39 | + </DropdownMenuItem> |
| 40 | +</ButtonDropdown>`; |
| 41 | + |
| 42 | +export function ButtonDropdownSection() { |
| 43 | + return ( |
| 44 | + <SectionShell |
| 45 | + id="button-dropdown" |
| 46 | + title="Button dropdown" |
| 47 | + description={ |
| 48 | + <> |
| 49 | + A split button — a primary action on the left and a chevron end-cap |
| 50 | + on the right that opens a dropdown of related secondary actions. The |
| 51 | + two halves render as one shape with a thin currentColor-tinted |
| 52 | + divider between them, so it works on any variant (and on custom |
| 53 | + backgrounds set via <code>className</code>). The menu uses the same |
| 54 | + dropdown primitive documented below. |
| 55 | + </> |
| 56 | + } |
| 57 | + whenToUse={ |
| 58 | + <ul> |
| 59 | + <li> |
| 60 | + One action is the obvious next step but a small set of related |
| 61 | + secondary actions belong in the same spot. |
| 62 | + </li> |
| 63 | + <li> |
| 64 | + Page-header action boxes where the primary action lives next to |
| 65 | + "park / discard / reset"-style alternates. |
| 66 | + </li> |
| 67 | + </ul> |
| 68 | + } |
| 69 | + whenNotToUse={ |
| 70 | + <ul> |
| 71 | + <li> |
| 72 | + The actions don't share intent — use separate buttons (or a plain{" "} |
| 73 | + <code>DropdownMenu</code> if none of them is the obvious primary). |
| 74 | + </li> |
| 75 | + <li> |
| 76 | + There's only the main action — use a plain <code>Button</code>. |
| 77 | + </li> |
| 78 | + <li> |
| 79 | + The menu is a list of navigation destinations rather than |
| 80 | + secondary actions — use a plain <code>DropdownMenu</code>. |
| 81 | + </li> |
| 82 | + </ul> |
| 83 | + } |
| 84 | + preview={ |
| 85 | + <div className="flex flex-wrap items-center gap-4"> |
| 86 | + <ButtonDropdown |
| 87 | + action={ |
| 88 | + <> |
| 89 | + Greenlight <ArrowRight className="h-4 w-4" /> |
| 90 | + </> |
| 91 | + } |
| 92 | + onClick={() => {}} |
| 93 | + > |
| 94 | + <DropdownMenuItem onSelect={() => {}}> |
| 95 | + <Pause /> Park |
| 96 | + </DropdownMenuItem> |
| 97 | + <DropdownMenuSeparator /> |
| 98 | + <DropdownMenuItem destructive onSelect={() => {}}> |
| 99 | + <Trash2 /> Discard |
| 100 | + </DropdownMenuItem> |
| 101 | + </ButtonDropdown> |
| 102 | + |
| 103 | + <ButtonDropdown |
| 104 | + variant="secondary" |
| 105 | + action={ |
| 106 | + <> |
| 107 | + <Copy className="h-4 w-4" /> Duplicate |
| 108 | + </> |
| 109 | + } |
| 110 | + onClick={() => {}} |
| 111 | + > |
| 112 | + <DropdownMenuItem onSelect={() => {}}> |
| 113 | + Duplicate as draft |
| 114 | + </DropdownMenuItem> |
| 115 | + <DropdownMenuItem onSelect={() => {}}>Export</DropdownMenuItem> |
| 116 | + </ButtonDropdown> |
| 117 | + |
| 118 | + <ButtonDropdown |
| 119 | + variant="danger" |
| 120 | + action="Delete" |
| 121 | + onClick={() => {}} |
| 122 | + > |
| 123 | + <DropdownMenuItem onSelect={() => {}}> |
| 124 | + Move to trash |
| 125 | + </DropdownMenuItem> |
| 126 | + <DropdownMenuItem onSelect={() => {}}>Archive</DropdownMenuItem> |
| 127 | + </ButtonDropdown> |
| 128 | + </div> |
| 129 | + } |
| 130 | + code={code} |
| 131 | + options={ |
| 132 | + <ul className="list-disc pl-5"> |
| 133 | + <li> |
| 134 | + <code>action</code>: content of the left (primary) button. String |
| 135 | + or any ReactNode. |
| 136 | + </li> |
| 137 | + <li> |
| 138 | + <code>onClick</code>: handler for the primary action. The toggle |
| 139 | + (chevron) opens the menu and is independent. |
| 140 | + </li> |
| 141 | + <li> |
| 142 | + <code>variant</code>: any <code>Button</code> variant —{" "} |
| 143 | + <code>primary</code> (default), <code>secondary</code>,{" "} |
| 144 | + <code>ghost</code>, <code>soft</code>, <code>danger</code>,{" "} |
| 145 | + <code>link</code>. |
| 146 | + </li> |
| 147 | + <li> |
| 148 | + <code>size</code>: <code>sm</code> | <code>md</code> (default) |{" "} |
| 149 | + <code>lg</code>. |
| 150 | + </li> |
| 151 | + <li> |
| 152 | + <code>className</code> / <code>toggleClassName</code>: extra |
| 153 | + classes for each half. Useful for custom-colored buttons (e.g. |
| 154 | + stage-color buttons in this app). <code>toggleClassName</code>{" "} |
| 155 | + defaults to mirror <code>className</code>. |
| 156 | + </li> |
| 157 | + <li> |
| 158 | + <code>menuAlign</code>: <code>start | center | end</code> (default{" "} |
| 159 | + <code>end</code>) — forwarded to <code>DropdownMenuContent</code>. |
| 160 | + </li> |
| 161 | + <li> |
| 162 | + <code>toggleAriaLabel</code>: aria-label for the chevron half. |
| 163 | + Default <code>"More actions"</code>. |
| 164 | + </li> |
| 165 | + <li> |
| 166 | + <strong>Children</strong>: pass{" "} |
| 167 | + <code>DropdownMenuItem</code> /{" "} |
| 168 | + <code>DropdownMenuSeparator</code> children — the standard |
| 169 | + dropdown-menu primitives. |
| 170 | + </li> |
| 171 | + </ul> |
| 172 | + } |
| 173 | + /> |
| 174 | + ); |
| 175 | +} |
0 commit comments