<script setup>
import { PhPlus } from "@phosphor-icons/vue";
import { Button } from "@dicehub/phi/components/button";
import { DropdownMenu } from "@dicehub/phi/components/dropdown";
</script>
<template>
<DropdownMenu>
<DropdownMenu.Trigger>
<Button :icon="PhPlus">Add</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Item value="worker">Worker</DropdownMenu.Item>
<DropdownMenu.Item value="pages">Pages</DropdownMenu.Item>
<DropdownMenu.Item value="kv">KV Namespace</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu>
</template>Installation
Barrel
import { DropdownMenu } from "@dicehub/phi";Granular
import { DropdownMenu } from "@dicehub/phi/components/dropdown";Usage
<script setup>
import { Button } from "@dicehub/phi/components/button";
import { DropdownMenu } from "@dicehub/phi/components/dropdown";
</script>
<template>
<DropdownMenu>
<DropdownMenu.Trigger>
<Button>Menu</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Item value="edit">Edit</DropdownMenu.Item>
<DropdownMenu.Item value="duplicate">Duplicate</DropdownMenu.Item>
<DropdownMenu.Separator />
<DropdownMenu.Item value="delete" variant="danger">Delete</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu>
</template>Examples
Basic Dropdown
<script setup>
import { PhPlus } from "@phosphor-icons/vue";
import { Button } from "@dicehub/phi/components/button";
import { DropdownMenu } from "@dicehub/phi/components/dropdown";
</script>
<template>
<DropdownMenu>
<DropdownMenu.Trigger>
<Button :icon="PhPlus">Add</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Item value="worker">Worker</DropdownMenu.Item>
<DropdownMenu.Item value="pages">Pages</DropdownMenu.Item>
<DropdownMenu.Item value="kv">KV Namespace</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu>
</template>Inset Items
Use inset on items without an icon to align their text with items that have one.
<script setup>
import { PhCopy, PhPencilSimple, PhTrash } from "@phosphor-icons/vue";
import { Button } from "@dicehub/phi/components/button";
import { DropdownMenu } from "@dicehub/phi/components/dropdown";
</script>
<template>
<DropdownMenu>
<DropdownMenu.Trigger><Button>Edit</Button></DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Item value="rename" :icon="PhPencilSimple">Rename</DropdownMenu.Item>
<DropdownMenu.Item value="duplicate" :icon="PhCopy">Duplicate</DropdownMenu.Item>
<DropdownMenu.Separator />
<DropdownMenu.Item value="move" inset>Move to folder</DropdownMenu.Item>
<DropdownMenu.Item value="favorite" inset>Add to favorites</DropdownMenu.Item>
<DropdownMenu.Separator />
<DropdownMenu.Item value="delete" :icon="PhTrash" variant="danger">Delete</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu>
</template>Handling Item Clicks
Use select handlers on DropdownMenu.Item to handle actions.
<script setup>
import { ref } from "vue";
import { PhCopy, PhPencilSimple, PhTrash } from "@phosphor-icons/vue";
import { Button } from "@dicehub/phi/components/button";
import { DropdownMenu } from "@dicehub/phi/components/dropdown";
const lastAction = ref("");
</script>
<template>
<DropdownMenu>
<DropdownMenu.Trigger><Button>Actions</Button></DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Item value="duplicate" :icon="PhCopy" @select="lastAction = 'Duplicated'">
Duplicate
</DropdownMenu.Item>
<DropdownMenu.Item value="rename" :icon="PhPencilSimple" @select="lastAction = 'Renamed'">
Rename
</DropdownMenu.Item>
<DropdownMenu.Separator />
<DropdownMenu.Item value="delete" :icon="PhTrash" variant="danger" @select="lastAction = 'Deleted'">
Delete
</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu>
</template>Checkbox Items
Use DropdownMenu.CheckboxItem for toggleable options that can be independently checked or unchecked.
<script setup>
import { ref } from "vue";
import { Button } from "@dicehub/phi/components/button";
import { DropdownMenu } from "@dicehub/phi/components/dropdown";
const showSidebar = ref(true);
const showLineNumbers = ref(false);
const wordWrap = ref(true);
</script>
<template>
<DropdownMenu>
<DropdownMenu.Trigger><Button>View Options</Button></DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Group>
<DropdownMenu.Label>Display</DropdownMenu.Label>
<DropdownMenu.CheckboxItem v-model:checked="showSidebar" value="sidebar">
Show sidebar
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem v-model:checked="showLineNumbers" value="line-numbers">
Show line numbers
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem v-model:checked="wordWrap" value="word-wrap">
Word wrap
</DropdownMenu.CheckboxItem>
</DropdownMenu.Group>
</DropdownMenu.Content>
</DropdownMenu>
</template>Nested Menu with Radio Selection
Use DropdownMenu.Sub, SubTrigger, and SubContent to create nested submenus with radio selections.
<script setup>
import { ref } from "vue";
import { PhCreditCard, PhMoon, PhSignOut, PhUser } from "@phosphor-icons/vue";
import { Button } from "@dicehub/phi/components/button";
import { DropdownMenu } from "@dicehub/phi/components/dropdown";
const language = ref("en");
const timezone = ref("America/Los_Angeles");
</script>
<template>
<DropdownMenu>
<DropdownMenu.Trigger><Button :icon="PhUser">Account</Button></DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Item value="profile" :icon="PhUser">Profile</DropdownMenu.Item>
<DropdownMenu.Item value="billing" :icon="PhCreditCard">Billing</DropdownMenu.Item>
<DropdownMenu.Item value="theme" :icon="PhMoon">Dark mode</DropdownMenu.Item>
<DropdownMenu.Sub>
<DropdownMenu.SubTrigger>Language</DropdownMenu.SubTrigger>
<DropdownMenu.SubContent>
<DropdownMenu.RadioGroup v-model="language">
<DropdownMenu.RadioItem value="en">English<DropdownMenu.RadioItemIndicator /></DropdownMenu.RadioItem>
<DropdownMenu.RadioItem value="es">Español<DropdownMenu.RadioItemIndicator /></DropdownMenu.RadioItem>
</DropdownMenu.RadioGroup>
</DropdownMenu.SubContent>
</DropdownMenu.Sub>
<DropdownMenu.Separator />
<DropdownMenu.Item value="logout" :icon="PhSignOut" variant="danger">Log out</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu>
</template>Custom Trigger with Avatar
Use DropdownMenu.Trigger with a custom focusable element when the trigger is not a standard Button.
<script setup>
import { PhGear, PhSignOut, PhUser } from "@phosphor-icons/vue";
import { DropdownMenu } from "@dicehub/phi/components/dropdown";
</script>
<template>
<DropdownMenu>
<DropdownMenu.Trigger>
<button class="avatar-trigger" type="button" aria-label="Open account menu">MR</button>
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Item value="profile" :icon="PhUser">Profile</DropdownMenu.Item>
<DropdownMenu.Item value="settings" :icon="PhGear">Settings</DropdownMenu.Item>
<DropdownMenu.Separator />
<DropdownMenu.Item value="logout" :icon="PhSignOut" variant="danger">Log out</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu>
</template>Navigation Links
Use DropdownMenu.LinkItem for semantic menu items that navigate to a URL.
<script setup>
import { PhArrowSquareOut, PhBookOpen, PhGear } from "@phosphor-icons/vue";
import { Button } from "@dicehub/phi/components/button";
import { DropdownMenu } from "@dicehub/phi/components/dropdown";
</script>
<template>
<DropdownMenu>
<DropdownMenu.Trigger><Button>Resources</Button></DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.LinkItem href="/docs/installation" :icon="PhGear">Settings</DropdownMenu.LinkItem>
<DropdownMenu.LinkItem href="/docs" :icon="PhBookOpen">Documentation</DropdownMenu.LinkItem>
<DropdownMenu.Separator />
<DropdownMenu.LinkItem href="https://developers.cloudflare.com" target="_blank" :icon="PhArrowSquareOut">
Developer Docs
</DropdownMenu.LinkItem>
</DropdownMenu.Content>
</DropdownMenu>
</template>