- Accordion
- Alert
- Alert Dialog
- Autocomplete
- Auth Surface
- Avatar
- Badge
- Browse Catalog Dialog
- Button
- Card
- Checkbox
- Checkbox Group
- Collapsible
- Combobox
- Command
- Connector Setup Dialog
- Cookie Banner
- Dialog
- Directory Card
- Directory Detail
- Directory Skeleton
- DrawerНовое
- Token Parts Input
- Empty
- Field
- Fieldset
- File Preview Modal
- File Preview Skeleton
- Form
- Frame
- Group
- Icon
- Input
- Input Group
- Kbd
- Label
- Legal Shell
- Menu
- Mermaid Diagram
- Mind Map Diagram
- Not Found Screen
- Onboarding Frame
- Popover
- PDF Thumbnail
- Personalization Landing
- Preview Card
- Pricing Page
- Progress
- Radio Group
- Ring Spinner
- Scroll Area
- Select
- Separator
- Settings Page
- Settings Skills
- Settings Connectors
- Settings Capabilities
- Settings Usage
- Settings Account
- Settings Billing
- Sheet
- Sidebar
- Skeleton
- Skill Create Dialog
- Slider
- Spinner
- Stat
- Switch
- Table
- Tabs
- Textarea
- Toast
- Toggle
- Tooltip
- Компоненты AI
- Chat Conversation
- Chat Message
- Chat Response
- Chat Suggestion
- Chat Prompt Input
- Slash Highlighted Textarea
- Chat Search Dialog
- Chat Skill Doc
- Chat Connector Detail
- Chat Attachments
- Chat File Card
- Chat Token Chip
- Chat Code Block
- Chat Image
- Chat Inline Citation
- Chat Sources
- Chat Web Search
- Chat Research
- Chat Source
- Chat Actions
- Chat Context
- Chat Loader
- Chat Compaction
- Chat Timeline
- Chat Snippet
- Chat Terminal
- Chat Stack Trace
- Chat Test Results
- Chat File Tree
- Chat Environment Variables
- Chat Audio Player
- Chat Transcription
- Chat Speech Input
- Chat Mic Selector
- Chat Voice Selector
- Chat Agent
- Chat Persona
- Chat Connection
- Chat Connector Suggestion
- Chat Queue
- Chat Checkpoint
- Chat Confirmation
- Chat Artifact
- Chat JSX Preview
- Chat Schema Display
- Chat Package Info
- Chat Commit
- Chat Plan
- Chat Open In Chat
- Chat Sandbox
- Chat Model Selector
- Chat Canvas
- Chat Node
- Chat Edge
Popover
Доступное всплывающее окно, привязанное к кнопке.
"use client";
import { Button } from "@/components/ui/button";
import { Field } from "@/components/ui/field";
import { Form } from "@/components/ui/form";
import {
Popover,
PopoverDescription,
PopoverPopup,
PopoverTitle,
PopoverTrigger,
} from "@/components/ui/popover";
import { Textarea } from "@/components/ui/textarea";
export default function Particle() {
return (
<Popover>
<PopoverTrigger render={<Button variant="outline" />}>
Открыть поповер
</PopoverTrigger>
<PopoverPopup className="w-80">
<div className="mb-4">
<PopoverTitle className="text-base">Оставьте отзыв</PopoverTitle>
<PopoverDescription>
Расскажите, что мы можем улучшить.
</PopoverDescription>
</div>
<Form className="flex w-full flex-col gap-4">
<Field>
<Textarea
aria-label="Оставить отзыв"
id="feedback"
placeholder="Что нам стоит улучшить?"
/>
</Field>
<Button type="submit">Отправить отзыв</Button>
</Form>
</PopoverPopup>
</Popover>
);
}
Установка
pnpm dlx shadcn@latest add @oracul/popover
Использование
import {
Popover,
PopoverClose,
PopoverDescription,
PopoverPopup,
PopoverTitle,
PopoverTrigger,
} from "@/components/ui/popover"<Popover>
<PopoverTrigger>Open Popover</PopoverTrigger>
<PopoverPopup>
<PopoverTitle>Popover Title</PopoverTitle>
<PopoverDescription>Popover Description</PopoverDescription>
<PopoverClose>Close</PopoverClose>
</PopoverPopup>
</Popover>API
Popover
Корневой компонент. Псевдоним для Popover.Root из Base UI.
PopoverTrigger
Кнопка-триггер, открывающая popover. Псевдоним для Popover.Trigger из Base UI.
PopoverPopup
Контейнер всплывающего окна, отображающий содержимое popover. Также экспортируется как PopoverContent.
| Свойство | Тип | По умолчанию | Описание |
|---|---|---|---|
tooltipStyle | boolean | false | Если true, применяет стилизацию в виде подсказки (меньший отступ, стрелка) |
side | "top" | "bottom" | "left" | "right" | "bottom" | Сторона триггера для позиционирования окна |
align | "start" | "center" | "end" | "center" | Выравнивание относительно триггера |
sideOffset | number | 4 | Расстояние от триггера в пикселях |
alignOffset | number | 0 | Смещение вдоль оси выравнивания |
portalProps | Popover.Portal.Props | - | Свойства, передаваемые во внутренний портал (keepMounted, container и т. д.); см. API портала Popover в Base UI |
PopoverTitle
Текст заголовка popover. Стилизованная обёртка для Popover.Title из Base UI.
PopoverDescription
Текст описания popover. Стилизованная обёртка для Popover.Description из Base UI.
PopoverClose
Кнопка закрытия popover. Псевдоним для Popover.Close из Base UI.
PopoverCreateHandle
Создаёт дескриптор для отсоединённых триггеров popover. Возвращает объект-дескриптор для привязки к нескольким триггерам.
Примеры
С кнопкой закрытия
"use client";
import { IconX } from "@tabler/icons-react";
import { Button } from "@/components/ui/button";
import {
Popover,
PopoverClose,
PopoverDescription,
PopoverPopup,
PopoverTitle,
PopoverTrigger,
} from "@/components/ui/popover";
export default function Particle() {
return (
<Popover>
<PopoverTrigger render={<Button variant="outline" />}>
Открыть поповер
</PopoverTrigger>
<PopoverPopup className="w-80">
<PopoverClose
aria-label="Закрыть"
className="absolute end-2 top-2"
render={<Button size="icon" variant="ghost" />}
>
<IconX stroke={1.5} />
</PopoverClose>
<div className="mb-2">
<PopoverTitle className="text-base">Уведомления</PopoverTitle>
<PopoverDescription>
Новых уведомлений нет. Отличная работа!
</PopoverDescription>
</div>
<PopoverClose render={<Button variant="outline" />}>
Закрыть
</PopoverClose>
</PopoverPopup>
</Popover>
);
}
Стиль подсказки
Используйте свойство tooltipStyle, чтобы popover выглядел как подсказка. Это рекомендуется, когда у вас есть кнопка с информационным значком, единственная цель которой — показать дополнительную информацию. Лучшие практики смотрите в рекомендациях по доступности подсказок.
"use client";
import { IconInfoCircle } from "@tabler/icons-react";
import { Button } from "@/components/ui/button";
import {
InputGroup,
InputGroupAddon,
InputGroupInput,
} from "@/components/ui/input-group";
import {
Popover,
PopoverPopup,
PopoverTrigger,
} from "@/components/ui/popover";
export default function Particle() {
return (
<InputGroup>
<InputGroupInput
aria-label="Пароль"
placeholder="Пароль"
type="password"
/>
<InputGroupAddon align="inline-end">
<Popover>
<PopoverTrigger
openOnHover
render={
<Button
aria-label="Требования к паролю"
size="icon-xs"
variant="ghost"
/>
}
>
<IconInfoCircle stroke={1.5} />
</PopoverTrigger>
<PopoverPopup side="top" tooltipStyle>
<p>Минимум 8 символов</p>
</PopoverPopup>
</Popover>
</InputGroupAddon>
</InputGroup>
);
}
Анимированные popover
Вы можете создавать анимированные popover, которые плавно переходят между разными триггерами, используя отсоединённые триггеры. Этот шаблон позволяет нескольким триггерам использовать одно всплывающее окно popover с автоматическими анимациями положения, размера и изменений содержимого.
Чтобы создать отсоединённые триггеры:
- Создайте дескриптор с помощью
PopoverCreateHandle - Привяжите один и тот же дескриптор к нескольким компонентам
PopoverTrigger - Каждый триггер передаёт свойство
payload, содержащее компонент с содержимым - Используйте один компонент
Popoverс дескриптором для отрисовки всплывающего окна
"use client";
import { IconBell, IconUser } from "@tabler/icons-react";
import type { ComponentType } from "react";
import {
Avatar,
AvatarFallback,
AvatarImage,
} from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import {
Popover,
PopoverCreateHandle,
PopoverDescription,
PopoverPopup,
PopoverTitle,
PopoverTrigger,
} from "@/components/ui/popover";
const popoverHandle = PopoverCreateHandle<ComponentType>();
const NotificationsContent = () => {
return (
<>
<PopoverTitle className="text-base">Уведомления</PopoverTitle>
<PopoverDescription>
Сейчас у вас нет новых уведомлений.
</PopoverDescription>
</>
);
};
const ProfileContent = () => {
return (
<div className="w-48">
<div className="flex items-center gap-3">
<Avatar>
<AvatarImage
alt="Mark Andersson"
src="https://images.unsplash.com/photo-1543610892-0b1f7e6d8ac1?w=128&h=128&dpr=2&q=80"
/>
<AvatarFallback>MA</AvatarFallback>
</Avatar>
<div className="min-w-0 flex-1">
<h4 className="line-clamp-1 font-medium text-sm">Mark Andersson</h4>
<div className="flex items-center gap-3 text-muted-foreground text-xs">
Продуктовый дизайнер
</div>
</div>
</div>
<Button className="mt-3 w-full" size="sm" variant="outline">
Выйти
</Button>
</div>
);
};
export default function Particle() {
return (
<div className="flex gap-2">
<PopoverTrigger
handle={popoverHandle}
payload={NotificationsContent}
render={
<Button aria-label="Notifications" size="icon" variant="outline" />
}
>
<IconBell aria-hidden="true" stroke={1.5} />
</PopoverTrigger>
<PopoverTrigger
handle={popoverHandle}
payload={ProfileContent}
render={<Button aria-label="Profile" size="icon" variant="outline" />}
>
<IconUser aria-hidden="true" stroke={1.5} />
</PopoverTrigger>
<Popover handle={popoverHandle}>
{({ payload: Payload }) => (
<PopoverPopup className="min-w-none">
{Payload !== undefined && <Payload />}
</PopoverPopup>
)}
</Popover>
</div>
);
}