mirror of
https://github.com/shadcn-ui/ui.git
synced 2026-07-01 16:44:24 +00:00
* feat: add phosphor icons to base ui * feat_ add phosphor to blocks * feat: add phosphor to radix blocks * feat: add phosphor to radix ui * feat: add phosphor to radix example * feat: add missing phosphor icons * fix: rename broken icons * chore: format files * fix: add missing phosphor icons * chore: build registry --------- Co-authored-by: shadcn <m@shadcn.com>
601 lines
24 KiB
TypeScript
601 lines
24 KiB
TypeScript
"use client"
|
|
|
|
import * as React from "react"
|
|
|
|
import {
|
|
Example,
|
|
ExampleWrapper,
|
|
} from "@/registry/bases/base/components/example"
|
|
import { Button } from "@/registry/bases/base/ui/button"
|
|
import { Checkbox } from "@/registry/bases/base/ui/checkbox"
|
|
import {
|
|
Dialog,
|
|
DialogClose,
|
|
DialogContent,
|
|
DialogDescription,
|
|
DialogFooter,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
DialogTrigger,
|
|
} from "@/registry/bases/base/ui/dialog"
|
|
import {
|
|
Field,
|
|
FieldContent,
|
|
FieldDescription,
|
|
FieldGroup,
|
|
FieldLabel,
|
|
FieldSeparator,
|
|
FieldSet,
|
|
FieldTitle,
|
|
} from "@/registry/bases/base/ui/field"
|
|
import { Input } from "@/registry/bases/base/ui/input"
|
|
import {
|
|
InputGroup,
|
|
InputGroupAddon,
|
|
InputGroupButton,
|
|
InputGroupInput,
|
|
} from "@/registry/bases/base/ui/input-group"
|
|
import { Kbd } from "@/registry/bases/base/ui/kbd"
|
|
import {
|
|
NativeSelect,
|
|
NativeSelectOption,
|
|
} from "@/registry/bases/base/ui/native-select"
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectGroup,
|
|
SelectItem,
|
|
SelectSeparator,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from "@/registry/bases/base/ui/select"
|
|
import { Switch } from "@/registry/bases/base/ui/switch"
|
|
import {
|
|
Tabs,
|
|
TabsContent,
|
|
TabsList,
|
|
TabsTrigger,
|
|
} from "@/registry/bases/base/ui/tabs"
|
|
import { Textarea } from "@/registry/bases/base/ui/textarea"
|
|
import {
|
|
Tooltip,
|
|
TooltipContent,
|
|
TooltipTrigger,
|
|
} from "@/registry/bases/base/ui/tooltip"
|
|
import { IconPlaceholder } from "@/app/(create)/components/icon-placeholder"
|
|
|
|
export default function DialogExample() {
|
|
return (
|
|
<ExampleWrapper>
|
|
<DialogWithForm />
|
|
<DialogScrollableContent />
|
|
<DialogWithStickyFooter />
|
|
<DialogNoCloseButton />
|
|
<DialogChatSettings />
|
|
</ExampleWrapper>
|
|
)
|
|
}
|
|
|
|
function DialogWithForm() {
|
|
return (
|
|
<Example title="With Form" className="items-center justify-center">
|
|
<Dialog>
|
|
<form>
|
|
<DialogTrigger render={<Button variant="outline" />}>
|
|
Edit Profile
|
|
</DialogTrigger>
|
|
<DialogContent>
|
|
<DialogHeader>
|
|
<DialogTitle>Edit profile</DialogTitle>
|
|
<DialogDescription>
|
|
Make changes to your profile here. Click save when you're
|
|
done. Your profile will be updated immediately.
|
|
</DialogDescription>
|
|
</DialogHeader>
|
|
<FieldGroup>
|
|
<Field>
|
|
<FieldLabel htmlFor="name-1">Name</FieldLabel>
|
|
<Input id="name-1" name="name" defaultValue="Pedro Duarte" />
|
|
</Field>
|
|
<Field>
|
|
<FieldLabel htmlFor="username-1">Username</FieldLabel>
|
|
<Input
|
|
id="username-1"
|
|
name="username"
|
|
defaultValue="@peduarte"
|
|
/>
|
|
</Field>
|
|
</FieldGroup>
|
|
<DialogFooter>
|
|
<DialogClose render={<Button variant="outline" />}>
|
|
Cancel
|
|
</DialogClose>
|
|
<Button type="submit">Save changes</Button>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</form>
|
|
</Dialog>
|
|
</Example>
|
|
)
|
|
}
|
|
|
|
function DialogScrollableContent() {
|
|
return (
|
|
<Example title="Scrollable Content" className="items-center justify-center">
|
|
<Dialog>
|
|
<DialogTrigger render={<Button variant="outline" />}>
|
|
Scrollable Content
|
|
</DialogTrigger>
|
|
<DialogContent>
|
|
<DialogHeader>
|
|
<DialogTitle>Scrollable Content</DialogTitle>
|
|
<DialogDescription>
|
|
This is a dialog with scrollable content.
|
|
</DialogDescription>
|
|
</DialogHeader>
|
|
<div className="style-nova:-mx-4 style-nova:px-4 no-scrollbar style-vega:px-6 style-mira:px-4 style-maia:px-6 style-vega:-mx-6 style-maia:-mx-6 style-mira:-mx-4 style-lyra:-mx-4 style-lyra:px-4 max-h-[70vh] overflow-y-auto">
|
|
{Array.from({ length: 10 }).map((_, index) => (
|
|
<p
|
|
key={index}
|
|
className="style-lyra:mb-2 style-lyra:leading-relaxed mb-4 leading-normal"
|
|
>
|
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
|
|
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
|
|
enim ad minim veniam, quis nostrud exercitation ullamco laboris
|
|
nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
|
|
in reprehenderit in voluptate velit esse cillum dolore eu fugiat
|
|
nulla pariatur. Excepteur sint occaecat cupidatat non proident,
|
|
sunt in culpa qui officia deserunt mollit anim id est laborum.
|
|
</p>
|
|
))}
|
|
</div>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</Example>
|
|
)
|
|
}
|
|
|
|
function DialogWithStickyFooter() {
|
|
return (
|
|
<Example title="With Sticky Footer" className="items-center justify-center">
|
|
<Dialog>
|
|
<DialogTrigger render={<Button variant="outline" />}>
|
|
Sticky Footer
|
|
</DialogTrigger>
|
|
<DialogContent>
|
|
<DialogHeader>
|
|
<DialogTitle>Scrollable Content</DialogTitle>
|
|
<DialogDescription>
|
|
This is a dialog with scrollable content.
|
|
</DialogDescription>
|
|
</DialogHeader>
|
|
<div className="style-nova:-mx-4 style-nova:px-4 no-scrollbar style-vega:px-6 style-mira:px-4 style-maia:px-6 style-vega:-mx-6 style-maia:-mx-6 style-mira:-mx-4 style-lyra:-mx-4 style-lyra:px-4 max-h-[70vh] overflow-y-auto">
|
|
{Array.from({ length: 10 }).map((_, index) => (
|
|
<p
|
|
key={index}
|
|
className="style-lyra:mb-2 style-lyra:leading-relaxed mb-4 leading-normal"
|
|
>
|
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
|
|
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
|
|
enim ad minim veniam, quis nostrud exercitation ullamco laboris
|
|
nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
|
|
in reprehenderit in voluptate velit esse cillum dolore eu fugiat
|
|
nulla pariatur. Excepteur sint occaecat cupidatat non proident,
|
|
sunt in culpa qui officia deserunt mollit anim id est laborum.
|
|
</p>
|
|
))}
|
|
</div>
|
|
<DialogFooter>
|
|
<DialogClose render={<Button variant="outline" />}>
|
|
Close
|
|
</DialogClose>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</Example>
|
|
)
|
|
}
|
|
|
|
function DialogNoCloseButton() {
|
|
return (
|
|
<Example title="No Close Button" className="items-center justify-center">
|
|
<Dialog>
|
|
<DialogTrigger render={<Button variant="outline" />}>
|
|
No Close Button
|
|
</DialogTrigger>
|
|
<DialogContent showCloseButton={false}>
|
|
<DialogHeader>
|
|
<DialogTitle>No Close Button</DialogTitle>
|
|
<DialogDescription>
|
|
This dialog doesn't have a close button in the top-right
|
|
corner.
|
|
</DialogDescription>
|
|
</DialogHeader>
|
|
<DialogFooter>
|
|
<DialogClose render={<Button variant="outline" />}>
|
|
Close
|
|
</DialogClose>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</Example>
|
|
)
|
|
}
|
|
|
|
const spokenLanguages = [
|
|
{ label: "Auto", value: "auto" },
|
|
{ label: "English", value: "en" },
|
|
{ label: "Spanish", value: "es" },
|
|
{ label: "French", value: "fr" },
|
|
{ label: "German", value: "de" },
|
|
{ label: "Italian", value: "it" },
|
|
{ label: "Portuguese", value: "pt" },
|
|
{ label: "Russian", value: "ru" },
|
|
{ label: "Chinese", value: "zh" },
|
|
{ label: "Japanese", value: "ja" },
|
|
{ label: "Korean", value: "ko" },
|
|
{ label: "Arabic", value: "ar" },
|
|
{ label: "Hindi", value: "hi" },
|
|
{ label: "Bengali", value: "bn" },
|
|
{ label: "Telugu", value: "te" },
|
|
{ label: "Marathi", value: "mr" },
|
|
{ label: "Kannada", value: "kn" },
|
|
{ label: "Malayalam", value: "ml" },
|
|
]
|
|
|
|
const voices = [
|
|
{ label: "Samantha", value: "samantha" },
|
|
{ label: "Alex", value: "alex" },
|
|
{ label: "Fred", value: "fred" },
|
|
{ label: "Victoria", value: "victoria" },
|
|
{ label: "Tom", value: "tom" },
|
|
{ label: "Karen", value: "karen" },
|
|
{ label: "Sam", value: "sam" },
|
|
{ label: "Daniel", value: "daniel" },
|
|
]
|
|
|
|
const themes = [
|
|
{ label: "Light", value: "light" },
|
|
{ label: "Dark", value: "dark" },
|
|
{ label: "System", value: "system" },
|
|
]
|
|
|
|
const accents = [
|
|
{ label: "Default", value: "default" },
|
|
{ label: "Red", value: "red" },
|
|
{ label: "Blue", value: "blue" },
|
|
{ label: "Green", value: "green" },
|
|
{ label: "Purple", value: "purple" },
|
|
{ label: "Pink", value: "pink" },
|
|
]
|
|
|
|
function DialogChatSettings() {
|
|
const [tab, setTab] = React.useState("general")
|
|
const [theme, setTheme] = React.useState("system")
|
|
const [accentColor, setAccentColor] = React.useState("default")
|
|
const [spokenLanguage, setSpokenLanguage] = React.useState("en")
|
|
const [voice, setVoice] = React.useState("samantha")
|
|
|
|
return (
|
|
<Example title="Chat Settings" className="items-center justify-center">
|
|
<Dialog>
|
|
<DialogTrigger render={<Button variant="outline" />}>
|
|
Chat Settings
|
|
</DialogTrigger>
|
|
<DialogContent className="min-w-md">
|
|
<DialogHeader>
|
|
<DialogTitle>Chat Settings</DialogTitle>
|
|
<DialogDescription>
|
|
Customize your chat settings: theme, accent color, spoken
|
|
language, voice, personality, and custom instructions.
|
|
</DialogDescription>
|
|
</DialogHeader>
|
|
<div className="flex flex-col gap-4">
|
|
<NativeSelect
|
|
value={tab}
|
|
onChange={(e) => setTab(e.target.value)}
|
|
className="w-full md:hidden"
|
|
>
|
|
<NativeSelectOption value="general">General</NativeSelectOption>
|
|
<NativeSelectOption value="notifications">
|
|
Notifications
|
|
</NativeSelectOption>
|
|
<NativeSelectOption value="personalization">
|
|
Personalization
|
|
</NativeSelectOption>
|
|
<NativeSelectOption value="security">Security</NativeSelectOption>
|
|
</NativeSelect>
|
|
<Tabs value={tab} onValueChange={setTab}>
|
|
<TabsList className="hidden w-full md:flex">
|
|
<TabsTrigger value="general">General</TabsTrigger>
|
|
<TabsTrigger value="notifications">Notifications</TabsTrigger>
|
|
<TabsTrigger value="personalization">
|
|
Personalization
|
|
</TabsTrigger>
|
|
<TabsTrigger value="security">Security</TabsTrigger>
|
|
</TabsList>
|
|
<div className="style-nova:p-4 style-vega:p-6 style-maia:p-6 style-mira:p-4 style-lyra:p-4 style-vega:min-h-[550px] style-maia:min-h-[550px] style-mira:min-h-[450px] style-lyra:min-h-[450px] style-nova:min-h-[460px] style-nova:rounded-lg style-vega:rounded-lg style-maia:rounded-xl style-mira:rounded-md style-lyra:rounded-none border [&_[data-slot=select-trigger]]:min-w-[125px]">
|
|
<TabsContent value="general">
|
|
<FieldSet>
|
|
<FieldGroup>
|
|
<Field orientation="horizontal">
|
|
<FieldLabel htmlFor="theme">Theme</FieldLabel>
|
|
<Select
|
|
items={themes}
|
|
value={theme}
|
|
onValueChange={(value) => setTheme(value as string)}
|
|
>
|
|
<SelectTrigger id="theme">
|
|
<SelectValue />
|
|
</SelectTrigger>
|
|
<SelectContent align="end">
|
|
<SelectGroup>
|
|
{themes.map((theme) => (
|
|
<SelectItem
|
|
key={theme.value}
|
|
value={theme.value}
|
|
>
|
|
{theme.label}
|
|
</SelectItem>
|
|
))}
|
|
</SelectGroup>
|
|
</SelectContent>
|
|
</Select>
|
|
</Field>
|
|
<FieldSeparator />
|
|
<Field orientation="horizontal">
|
|
<FieldLabel htmlFor="accent-color">
|
|
Accent Color
|
|
</FieldLabel>
|
|
<Select
|
|
items={accents}
|
|
value={accentColor}
|
|
onValueChange={(value) =>
|
|
setAccentColor(value as string)
|
|
}
|
|
>
|
|
<SelectTrigger id="accent-color">
|
|
<SelectValue />
|
|
</SelectTrigger>
|
|
<SelectContent align="end">
|
|
<SelectGroup>
|
|
{accents.map((accent) => (
|
|
<SelectItem
|
|
key={accent.value}
|
|
value={accent.value}
|
|
>
|
|
{accent.label}
|
|
</SelectItem>
|
|
))}
|
|
</SelectGroup>
|
|
</SelectContent>
|
|
</Select>
|
|
</Field>
|
|
<FieldSeparator />
|
|
<Field orientation="responsive">
|
|
<FieldContent>
|
|
<FieldLabel htmlFor="spoken-language">
|
|
Spoken Language
|
|
</FieldLabel>
|
|
<FieldDescription>
|
|
For best results, select the language you mainly
|
|
speak. If it's not listed, it may still be
|
|
supported via auto-detection.
|
|
</FieldDescription>
|
|
</FieldContent>
|
|
<Select
|
|
items={spokenLanguages}
|
|
value={spokenLanguage}
|
|
onValueChange={(value) =>
|
|
setSpokenLanguage(value as string)
|
|
}
|
|
>
|
|
<SelectTrigger id="spoken-language">
|
|
<SelectValue />
|
|
</SelectTrigger>
|
|
<SelectContent align="end">
|
|
<SelectGroup>
|
|
{spokenLanguages.map((language) => (
|
|
<SelectItem
|
|
key={language.value}
|
|
value={language.value}
|
|
>
|
|
{language.label}
|
|
</SelectItem>
|
|
))}
|
|
</SelectGroup>
|
|
</SelectContent>
|
|
</Select>
|
|
</Field>
|
|
<FieldSeparator />
|
|
<Field orientation="horizontal">
|
|
<FieldLabel htmlFor="voice">Voice</FieldLabel>
|
|
<Select
|
|
items={voices}
|
|
value={voice}
|
|
onValueChange={(value) => setVoice(value as string)}
|
|
>
|
|
<SelectTrigger id="voice">
|
|
<SelectValue />
|
|
</SelectTrigger>
|
|
<SelectContent align="end">
|
|
<SelectGroup>
|
|
{voices.map((voice) => (
|
|
<SelectItem
|
|
key={voice.value}
|
|
value={voice.value}
|
|
>
|
|
{voice.label}
|
|
</SelectItem>
|
|
))}
|
|
</SelectGroup>
|
|
</SelectContent>
|
|
</Select>
|
|
</Field>
|
|
</FieldGroup>
|
|
</FieldSet>
|
|
</TabsContent>
|
|
<TabsContent value="notifications">
|
|
<FieldGroup>
|
|
<FieldSet>
|
|
<FieldLabel>Responses</FieldLabel>
|
|
<FieldDescription>
|
|
Get notified when ChatGPT responds to requests that take
|
|
time, like research or image generation.
|
|
</FieldDescription>
|
|
<FieldGroup data-slot="checkbox-group">
|
|
<Field orientation="horizontal">
|
|
<Checkbox id="push" defaultChecked disabled />
|
|
<FieldLabel htmlFor="push" className="font-normal">
|
|
Push notifications
|
|
</FieldLabel>
|
|
</Field>
|
|
</FieldGroup>
|
|
</FieldSet>
|
|
<FieldSeparator />
|
|
<FieldSet>
|
|
<FieldLabel>Tasks</FieldLabel>
|
|
<FieldDescription>
|
|
Get notified when tasks you've created have
|
|
updates. <a href="#">Manage tasks</a>
|
|
</FieldDescription>
|
|
<FieldGroup data-slot="checkbox-group">
|
|
<Field orientation="horizontal">
|
|
<Checkbox id="push-tasks" />
|
|
<FieldLabel
|
|
htmlFor="push-tasks"
|
|
className="font-normal"
|
|
>
|
|
Push notifications
|
|
</FieldLabel>
|
|
</Field>
|
|
<Field orientation="horizontal">
|
|
<Checkbox id="email-tasks" />
|
|
<FieldLabel
|
|
htmlFor="email-tasks"
|
|
className="font-normal"
|
|
>
|
|
Email notifications
|
|
</FieldLabel>
|
|
</Field>
|
|
</FieldGroup>
|
|
</FieldSet>
|
|
</FieldGroup>
|
|
</TabsContent>
|
|
<TabsContent value="personalization">
|
|
<FieldGroup>
|
|
<Field orientation="responsive">
|
|
<FieldLabel htmlFor="nickname">Nickname</FieldLabel>
|
|
<InputGroup>
|
|
<InputGroupInput
|
|
id="nickname"
|
|
placeholder="Broski"
|
|
className="@md/field-group:max-w-[200px]"
|
|
/>
|
|
<InputGroupAddon align="inline-end">
|
|
<Tooltip>
|
|
<TooltipTrigger
|
|
render={<InputGroupButton size="icon-xs" />}
|
|
>
|
|
<IconPlaceholder
|
|
lucide="InfoIcon"
|
|
tabler="IconInfoCircle"
|
|
hugeicons="AlertCircleIcon"
|
|
phosphor="InfoIcon"
|
|
/>
|
|
</TooltipTrigger>
|
|
<TooltipContent className="flex items-center gap-2">
|
|
Used to identify you in the chat. <Kbd>N</Kbd>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
</InputGroupAddon>
|
|
</InputGroup>
|
|
</Field>
|
|
<FieldSeparator />
|
|
<Field
|
|
orientation="responsive"
|
|
className="@md/field-group:flex-col @2xl/field-group:flex-row"
|
|
>
|
|
<FieldContent>
|
|
<FieldLabel htmlFor="about">More about you</FieldLabel>
|
|
<FieldDescription>
|
|
Tell us more about yourself. This will be used to help
|
|
us personalize your experience.
|
|
</FieldDescription>
|
|
</FieldContent>
|
|
<Textarea
|
|
id="about"
|
|
placeholder="I'm a software engineer..."
|
|
className="min-h-[120px] @md/field-group:min-w-full @2xl/field-group:min-w-[300px]"
|
|
/>
|
|
</Field>
|
|
<FieldSeparator />
|
|
<FieldLabel>
|
|
<Field orientation="horizontal">
|
|
<FieldContent>
|
|
<FieldLabel htmlFor="customization">
|
|
Enable customizations
|
|
</FieldLabel>
|
|
<FieldDescription>
|
|
Enable customizations to make ChatGPT more
|
|
personalized.
|
|
</FieldDescription>
|
|
</FieldContent>
|
|
<Switch id="customization" defaultChecked />
|
|
</Field>
|
|
</FieldLabel>
|
|
</FieldGroup>
|
|
</TabsContent>
|
|
<TabsContent value="security">
|
|
<FieldGroup>
|
|
<Field orientation="horizontal">
|
|
<FieldContent>
|
|
<FieldLabel htmlFor="2fa">
|
|
Multi-factor authentication
|
|
</FieldLabel>
|
|
<FieldDescription>
|
|
Enable multi-factor authentication to secure your
|
|
account. If you do not have a two-factor
|
|
authentication device, you can use a one-time code
|
|
sent to your email.
|
|
</FieldDescription>
|
|
</FieldContent>
|
|
<Switch id="2fa" />
|
|
</Field>
|
|
<FieldSeparator />
|
|
<Field orientation="horizontal">
|
|
<FieldContent>
|
|
<FieldTitle>Log out</FieldTitle>
|
|
<FieldDescription>
|
|
Log out of your account on this device.
|
|
</FieldDescription>
|
|
</FieldContent>
|
|
<Button variant="outline" size="sm">
|
|
Log Out
|
|
</Button>
|
|
</Field>
|
|
<FieldSeparator />
|
|
<Field orientation="horizontal">
|
|
<FieldContent>
|
|
<FieldTitle>Log out of all devices</FieldTitle>
|
|
<FieldDescription>
|
|
This will log you out of all devices, including the
|
|
current session. It may take up to 30 minutes for the
|
|
changes to take effect.
|
|
</FieldDescription>
|
|
</FieldContent>
|
|
<Button variant="outline" size="sm">
|
|
Log Out All
|
|
</Button>
|
|
</Field>
|
|
</FieldGroup>
|
|
</TabsContent>
|
|
</div>
|
|
</Tabs>
|
|
</div>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</Example>
|
|
)
|
|
}
|