Skip to content

Commit dc48f2e

Browse files
authored
feat: Popover component (#1237)
* feat(popover): created Popover component This PR creates the Popover component based on the specs of the core library fix #916 fix #878 * docs(popover): created document page of Popover component with examples * refact(popover): removed unnecessary code * docs(popover): improved documentation * fix(popover): import correct theme props * refact(popover): use relative imports * docs(popover): reverted import paths
1 parent 406ebe5 commit dc48f2e

20 files changed

+1326
-0
lines changed

content/docs/components/popover.mdx

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
---
2+
title: React Popover - Flowbite
3+
description: Use the popover component to show detailed information inside a pop-up box relative to the element that is being clicked or hovered based on multiple styles
4+
---
5+
6+
Use the popover component to show detailed information inside a pop-up box relative to the element that is being clicked or hovered based on multiple styles
7+
8+
Get started with the popover component to show any type of content inside a pop-up box when hovering or clicking over a trigger element. There are multiple examples that you can choose from, such as showing more information about a user profile, company profile, password strength, and more.
9+
10+
Before using the popover component, make sure to import the component in your React project:
11+
12+
```jsx
13+
import { Popover } from 'flowbite-react';
14+
```
15+
16+
## Default popover
17+
18+
Wrap the trigger component with the `<Popover>` component and pass the popover content to the `content` prop of the `<Popover>` component.
19+
20+
This will render the popover whenever you click the trigger component.
21+
22+
<Example name="popover.root" />
23+
24+
## Company profile
25+
26+
This example can be used to show more information about a company profile.
27+
28+
<Example name="popover.profile" />
29+
30+
## Image popover
31+
32+
Use this example to trigger a popover component with detailed information and an image when hovering over a portion of highlighted text inspired by Wikipedia and other large news outlets.
33+
34+
<Example name="popover.image" />
35+
36+
## Password strength
37+
38+
Dynamically show the password strength progress when creating a new password positioned relative to the input element.
39+
40+
<Example name="popover.password" />
41+
42+
## Controlled
43+
44+
Manages visibility via `open` and `openOnChange` props, allowing fine-tuned control over its display. Ideal for scenarios where Popover behavior needs to align with specific application logic or user interactions.
45+
46+
<Example name="popover.controlled" />
47+
48+
## Placement
49+
50+
Update the placement of the popover using the `placement` prop. The default placement is `bottom` and you can also use `right`, `top`, and `left`.
51+
52+
<Example name="popover.placement" />
53+
54+
## Trigger type
55+
56+
Use the `trigger` prop to change the trigger type of the popover if you want to show the popover when clicking on the hover element instead of clicking on it.
57+
58+
The default trigger type is `hover` and you can also use `click`.
59+
60+
<Example name="popover.trigger" />
61+
62+
## Disable arrow
63+
64+
You can disable the arrow of the popover component by passing the `arrow` prop with a value of `false`.
65+
66+
<Example name="popover.disableArrow" />
67+
68+
## Theme
69+
70+
To learn more about how to customize the appearance of components, please see the [Theme docs](/docs/customize/theme).
71+
72+
<Theme name="popover" />
73+
74+
## References
75+
76+
- [Flowbite Popover](https://flowbite.com/docs/components/popover/)

data/docs-sidebar.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export const DOCS_SIDEBAR: DocsSidebarSection[] = [
7171
{ title: 'Modal', href: '/docs/components/modal' },
7272
{ title: 'Navbar', href: '/docs/components/navbar' },
7373
{ title: 'Pagination', href: '/docs/components/pagination' },
74+
{ title: 'Popover', href: '/docs/components/popover' },
7475
{ title: 'Progress bar', href: '/docs/components/progress' },
7576
{ title: 'Rating', href: '/docs/components/rating' },
7677
{ title: 'Sidebar', href: '/docs/components/sidebar' },

examples/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,4 @@ export * as tabs from './tabs';
3030
export * as timeline from './timeline';
3131
export * as toast from './toast';
3232
export * as tooltip from './tooltip';
33+
export * as popover from './popover';

examples/popover/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export { disableArrow } from './popover.disableArrow';
2+
export { placement } from './popover.placement';
3+
export { root } from './popover.root';
4+
export { trigger } from './popover.trigger';
5+
export { profile } from './popover.profile';
6+
export { image } from './popover.image';
7+
export { password } from './popover.password';
8+
export { controlled } from './popover.controlled';
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
'use client';
2+
3+
import { useState } from 'react';
4+
import { BiCaretDown } from 'react-icons/bi';
5+
import { type CodeData } from '~/components/code-demo';
6+
import { Button, Popover, Label, TextInput } from '~/src';
7+
8+
const code = `
9+
'use client';
10+
11+
import { useState } from 'react';
12+
import { BiCaretDown } from 'react-icons/bi';
13+
import { Button, Popover, Label, TextInput } from 'flowbite-react';
14+
15+
function Component() {
16+
const [open, setOpen] = useState(false);
17+
18+
return (
19+
<Popover
20+
aria-labelledby="area-popover"
21+
open={open}
22+
onOpenChange={setOpen}
23+
content={
24+
<div className="flex w-64 flex-col gap-4 p-4 text-sm text-gray-500 dark:text-gray-400">
25+
<div>
26+
<h2 id="area-popover" className="text-base text-gray-500">Area (sqft)</h2>
27+
<div className="mb-2 block">
28+
<Label htmlFor="minsqft" value="Minimum sqft" />
29+
</div>
30+
<TextInput id="minsqft" type="number" />
31+
</div>
32+
<div>
33+
<div className="mb-2 block">
34+
<Label htmlFor="maxsqft" value="Maximum sqft" />
35+
</div>
36+
<TextInput id="maxsqft" type="number" />
37+
</div>
38+
<div className="flex gap-2">
39+
<Button color="gray">Reset</Button>
40+
<Button color="success" onClick={() => setOpen(false)}>
41+
Save
42+
</Button>
43+
</div>
44+
</div>
45+
}
46+
>
47+
<Button>
48+
Area <BiCaretDown className="ml-2" />
49+
</Button>
50+
</Popover>
51+
);
52+
}
53+
`;
54+
55+
function Component() {
56+
const [open, setOpen] = useState(false);
57+
58+
return (
59+
<Popover
60+
open={open}
61+
onOpenChange={setOpen}
62+
content={
63+
<div className="flex w-64 flex-col gap-4 p-4 text-sm text-gray-500 dark:text-gray-400">
64+
<div>
65+
<h2 className="text-base text-gray-500">Area (sqft)</h2>
66+
<div className="mb-2 block">
67+
<Label htmlFor="minsqft" value="Minimum sqft" />
68+
</div>
69+
<TextInput id="minsqft" type="number" />
70+
</div>
71+
<div>
72+
<div className="mb-2 block">
73+
<Label htmlFor="maxsqft" value="Maximum sqft" />
74+
</div>
75+
<TextInput id="maxsqft" type="number" />
76+
</div>
77+
<div className="flex gap-2">
78+
<Button color="gray">Reset</Button>
79+
<Button color="success" onClick={() => setOpen(false)}>
80+
Save
81+
</Button>
82+
</div>
83+
</div>
84+
}
85+
>
86+
<Button>
87+
Area <BiCaretDown className="ml-2" />
88+
</Button>
89+
</Popover>
90+
);
91+
}
92+
93+
export const controlled: CodeData = {
94+
type: 'single',
95+
code: [
96+
{
97+
fileName: 'client',
98+
language: 'tsx',
99+
code,
100+
},
101+
],
102+
githubSlug: 'popover/popover.controlled.tsx',
103+
component: <Component />,
104+
};
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { type CodeData } from '~/components/code-demo';
2+
import { Button, Popover } from '~/src';
3+
4+
const code = `
5+
import { Button, Popover } from 'flowbite-react';
6+
7+
function Component() {
8+
return (
9+
<Popover
10+
aria-labelledby="default-popover"
11+
content={
12+
<div className="w-64 text-sm text-gray-500 dark:text-gray-400">
13+
<div className="border-b border-gray-200 bg-gray-100 px-3 py-2 dark:border-gray-600 dark:bg-gray-700">
14+
<h3 id="default-popover" className="font-semibold text-gray-900 dark:text-white">Popover title</h3>
15+
</div>
16+
<div className="px-3 py-2">
17+
<p>And here's some amazing content. It's very engaging. Right?</p>
18+
</div>
19+
</div>
20+
}
21+
arrow={false}
22+
>
23+
<Button>No Arrow Popover</Button>
24+
</Popover>
25+
);
26+
}
27+
`;
28+
29+
function Component() {
30+
return (
31+
<Popover
32+
aria-labelledby="default-popover"
33+
content={
34+
<div className="w-64 text-sm text-gray-500 dark:text-gray-400">
35+
<div className="border-b border-gray-200 bg-gray-100 px-3 py-2 dark:border-gray-600 dark:bg-gray-700">
36+
<h3 id="default-popover" className="font-semibold text-gray-900 dark:text-white">
37+
Popover title
38+
</h3>
39+
</div>
40+
<div className="px-3 py-2">
41+
<p>And here's some amazing content. It's very engaging. Right?</p>
42+
</div>
43+
</div>
44+
}
45+
arrow={false}
46+
>
47+
<Button>No Arrow Popover</Button>
48+
</Popover>
49+
);
50+
}
51+
52+
export const disableArrow: CodeData = {
53+
type: 'single',
54+
code: [
55+
{
56+
fileName: 'client',
57+
language: 'tsx',
58+
code,
59+
},
60+
],
61+
githubSlug: 'popover/popover.disableArrow.tsx',
62+
component: <Component />,
63+
};

0 commit comments

Comments
 (0)