Skip to content

Commit

Permalink
feat: Popover component (#1237)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
nigellima authored Jan 23, 2024
1 parent 406ebe5 commit dc48f2e
Show file tree
Hide file tree
Showing 20 changed files with 1,326 additions and 0 deletions.
76 changes: 76 additions & 0 deletions content/docs/components/popover.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
title: React Popover - Flowbite
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
---

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

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.

Before using the popover component, make sure to import the component in your React project:

```jsx
import { Popover } from 'flowbite-react';
```

## Default popover

Wrap the trigger component with the `<Popover>` component and pass the popover content to the `content` prop of the `<Popover>` component.

This will render the popover whenever you click the trigger component.

<Example name="popover.root" />

## Company profile

This example can be used to show more information about a company profile.

<Example name="popover.profile" />

## Image popover

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.

<Example name="popover.image" />

## Password strength

Dynamically show the password strength progress when creating a new password positioned relative to the input element.

<Example name="popover.password" />

## Controlled

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.

<Example name="popover.controlled" />

## Placement

Update the placement of the popover using the `placement` prop. The default placement is `bottom` and you can also use `right`, `top`, and `left`.

<Example name="popover.placement" />

## Trigger type

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.

The default trigger type is `hover` and you can also use `click`.

<Example name="popover.trigger" />

## Disable arrow

You can disable the arrow of the popover component by passing the `arrow` prop with a value of `false`.

<Example name="popover.disableArrow" />

## Theme

To learn more about how to customize the appearance of components, please see the [Theme docs](/docs/customize/theme).

<Theme name="popover" />

## References

- [Flowbite Popover](https://flowbite.com/docs/components/popover/)
1 change: 1 addition & 0 deletions data/docs-sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export const DOCS_SIDEBAR: DocsSidebarSection[] = [
{ title: 'Modal', href: '/docs/components/modal' },
{ title: 'Navbar', href: '/docs/components/navbar' },
{ title: 'Pagination', href: '/docs/components/pagination' },
{ title: 'Popover', href: '/docs/components/popover' },
{ title: 'Progress bar', href: '/docs/components/progress' },
{ title: 'Rating', href: '/docs/components/rating' },
{ title: 'Sidebar', href: '/docs/components/sidebar' },
Expand Down
1 change: 1 addition & 0 deletions examples/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ export * as tabs from './tabs';
export * as timeline from './timeline';
export * as toast from './toast';
export * as tooltip from './tooltip';
export * as popover from './popover';
8 changes: 8 additions & 0 deletions examples/popover/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export { disableArrow } from './popover.disableArrow';
export { placement } from './popover.placement';
export { root } from './popover.root';
export { trigger } from './popover.trigger';
export { profile } from './popover.profile';
export { image } from './popover.image';
export { password } from './popover.password';
export { controlled } from './popover.controlled';
104 changes: 104 additions & 0 deletions examples/popover/popover.controlled.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
'use client';

import { useState } from 'react';
import { BiCaretDown } from 'react-icons/bi';
import { type CodeData } from '~/components/code-demo';
import { Button, Popover, Label, TextInput } from '~/src';

const code = `
'use client';
import { useState } from 'react';
import { BiCaretDown } from 'react-icons/bi';
import { Button, Popover, Label, TextInput } from 'flowbite-react';
function Component() {
const [open, setOpen] = useState(false);
return (
<Popover
aria-labelledby="area-popover"
open={open}
onOpenChange={setOpen}
content={
<div className="flex w-64 flex-col gap-4 p-4 text-sm text-gray-500 dark:text-gray-400">
<div>
<h2 id="area-popover" className="text-base text-gray-500">Area (sqft)</h2>
<div className="mb-2 block">
<Label htmlFor="minsqft" value="Minimum sqft" />
</div>
<TextInput id="minsqft" type="number" />
</div>
<div>
<div className="mb-2 block">
<Label htmlFor="maxsqft" value="Maximum sqft" />
</div>
<TextInput id="maxsqft" type="number" />
</div>
<div className="flex gap-2">
<Button color="gray">Reset</Button>
<Button color="success" onClick={() => setOpen(false)}>
Save
</Button>
</div>
</div>
}
>
<Button>
Area <BiCaretDown className="ml-2" />
</Button>
</Popover>
);
}
`;

function Component() {
const [open, setOpen] = useState(false);

return (
<Popover
open={open}
onOpenChange={setOpen}
content={
<div className="flex w-64 flex-col gap-4 p-4 text-sm text-gray-500 dark:text-gray-400">
<div>
<h2 className="text-base text-gray-500">Area (sqft)</h2>
<div className="mb-2 block">
<Label htmlFor="minsqft" value="Minimum sqft" />
</div>
<TextInput id="minsqft" type="number" />
</div>
<div>
<div className="mb-2 block">
<Label htmlFor="maxsqft" value="Maximum sqft" />
</div>
<TextInput id="maxsqft" type="number" />
</div>
<div className="flex gap-2">
<Button color="gray">Reset</Button>
<Button color="success" onClick={() => setOpen(false)}>
Save
</Button>
</div>
</div>
}
>
<Button>
Area <BiCaretDown className="ml-2" />
</Button>
</Popover>
);
}

export const controlled: CodeData = {
type: 'single',
code: [
{
fileName: 'client',
language: 'tsx',
code,
},
],
githubSlug: 'popover/popover.controlled.tsx',
component: <Component />,
};
63 changes: 63 additions & 0 deletions examples/popover/popover.disableArrow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { type CodeData } from '~/components/code-demo';
import { Button, Popover } from '~/src';

const code = `
import { Button, Popover } from 'flowbite-react';
function Component() {
return (
<Popover
aria-labelledby="default-popover"
content={
<div className="w-64 text-sm text-gray-500 dark:text-gray-400">
<div className="border-b border-gray-200 bg-gray-100 px-3 py-2 dark:border-gray-600 dark:bg-gray-700">
<h3 id="default-popover" className="font-semibold text-gray-900 dark:text-white">Popover title</h3>
</div>
<div className="px-3 py-2">
<p>And here's some amazing content. It's very engaging. Right?</p>
</div>
</div>
}
arrow={false}
>
<Button>No Arrow Popover</Button>
</Popover>
);
}
`;

function Component() {
return (
<Popover
aria-labelledby="default-popover"
content={
<div className="w-64 text-sm text-gray-500 dark:text-gray-400">
<div className="border-b border-gray-200 bg-gray-100 px-3 py-2 dark:border-gray-600 dark:bg-gray-700">
<h3 id="default-popover" className="font-semibold text-gray-900 dark:text-white">
Popover title
</h3>
</div>
<div className="px-3 py-2">
<p>And here's some amazing content. It's very engaging. Right?</p>
</div>
</div>
}
arrow={false}
>
<Button>No Arrow Popover</Button>
</Popover>
);
}

export const disableArrow: CodeData = {
type: 'single',
code: [
{
fileName: 'client',
language: 'tsx',
code,
},
],
githubSlug: 'popover/popover.disableArrow.tsx',
component: <Component />,
};
Loading

1 comment on commit dc48f2e

@vercel
Copy link

@vercel vercel bot commented on dc48f2e Jan 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.