Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/192 popover #212

Merged
merged 10 commits into from
Dec 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 64 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,10 @@
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-popover": "^1.0.7",
"@radix-ui/react-radio-group": "^1.1.3",
"@radix-ui/react-scroll-area": "^1.0.5",
"@radix-ui/react-separator": "^1.0.3",
"@radix-ui/react-switch": "^1.0.3",
"@radix-ui/react-tooltip": "^1.0.7",
"class-variance-authority": "^0.7.0",
Expand Down
87 changes: 87 additions & 0 deletions src/components/Popover/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
'use client'

import * as React from 'react'
import * as PopoverPrimitive from '@radix-ui/react-popover'
import * as Separator from '@radix-ui/react-separator'
import { cva, type VariantProps } from 'class-variance-authority'
import * as SeparatorPrimitive from '@radix-ui/react-separator'
import * as ScrollArea from '@radix-ui/react-scroll-area'

import { cn } from '@/lib/utils'

const popoverVariants = cva([
'z-50',
'border border-2 border-border-subtle dark:border-border-dark',
'rounded-lg',
'bg-background dark:bg-background-dark',
'text-foreground text-sm font-normal dark:text-white',
'shadow',
'outline-none',
'overflow-scroll'
])

const Popover = PopoverPrimitive.Root

const PopoverTrigger = PopoverPrimitive.Trigger

export interface PopoverProps
extends React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Root>,
VariantProps<typeof popoverVariants> {}

export interface SeparatorProps
extends React.ComponentPropsWithoutRef<typeof Separator.Root> {}

const PopoverContent = React.forwardRef<
React.ElementRef<typeof PopoverPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
>(
(
{ className, align = 'center', sideOffset = 4, children, ...props },
ref
) => (
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content
ref={ref}
align={align}
sideOffset={sideOffset}
className={cn(popoverVariants(), className)}
{...props}
>
<ScrollArea.Root className="w-full h-full" type="auto">
<ScrollArea.Viewport className="w-full h-full">
{children}
</ScrollArea.Viewport>
<ScrollArea.Scrollbar
orientation="vertical"
className="w-3 pr-1 py-2"
>
<ScrollArea.Thumb className="bg-grey-200 w-2 rounded-lg" />
</ScrollArea.Scrollbar>
</ScrollArea.Root>
</PopoverPrimitive.Content>
</PopoverPrimitive.Portal>
)
)
PopoverContent.displayName = PopoverPrimitive.Content.displayName

const PopoverSeparator = React.forwardRef<
React.ElementRef<typeof SeparatorPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
>(({ className, orientation = 'horizontal', ...props }, ref) => (
<div className="w-full">
<SeparatorPrimitive.Root
ref={ref}
decorative
orientation={orientation}
className={cn(
'shrink-0 bg-border-subtle dark:bg-border-dark',
orientation === 'horizontal' ? 'h-[1px] w-fill' : 'h-fill w-[1px]',
className
)}
{...props}
/>
</div>
))
PopoverSeparator.displayName = SeparatorPrimitive.Root.displayName

export { Popover, PopoverTrigger, PopoverContent, PopoverSeparator }
1 change: 1 addition & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ export * from './Chip'
export * from './Modal'
export * from './WebsiteFooter'
export * from './Select'
export * from './Popover'
export * from './Calendar'
100 changes: 100 additions & 0 deletions stories/Popover/Docs.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { Canvas, Meta } from '@storybook/blocks'

import * as PopoverStories from './Popover.stories'

<Meta of={PopoverStories} />

# Popover

A popover overlay is a temporary, expandable menu that appears on top of the main content when activated. It typically displays a list of options or additional controls when a user clicks or hovers over a specific element, such as a button, icon or select input. This design element helps conserve screen space and provides a clean, unobtrusive way to present additional choices or information to users.

## Default

<Canvas of={PopoverStories.Default} />

## Default with Scrolling

<Canvas of={PopoverStories.ScrollableList} />

## With Radio Group

<Canvas of={PopoverStories.Radio} />

### \<Popover>

The root of the component.

### \<PopoverTrigger>

The button that triggers the popover to open and reveal its contents.

### \<PopoverContent>

The content contained in the popover. Style or className is ignored.

<table>
<tbody>
<tr>
<td>Attribute</td>
<td>Type</td>
<td>Default</td>
</tr>
<tr>
<td>align</td>
<td>`'center' | 'start' | 'end`</td>
<td>`'center'`</td>
</tr>
<tr>
<td>sideOffset</td>
<td>`number`</td>
<td>`4`</td>
</tr>
</tbody>
</table>

### \<PopoverSeparator>

Used to visually separate items in the popover. Can be used to create Headers or Footers.

## Example

```tsx
import {
Popover,
PopoverContent,
PopoverTrigger,
PopoverSeparator,
PopoverProps,
Button
} from '@nearform/quantum'

import { PlusIcon } from '@/assets/build'

const ShoppingList = () => (
<Popover>
<PopoverTrigger>
<Button>Open Shopping List</Button>
</PopoverTrigger>
<PopoverContent className="w-72">
<div className="flex flex-col gap-3 px-4">
<div className="flex font-semibold justify-center pt-2">
Shopping List
</div>
<PopoverSeparator className="-mx-4" />
<li>Bananas</li>
<li>Bread</li>
<li>Butter</li>
<li>Sugar</li>
<li>Icing Sugar</li>
<li>Eggs</li>
<li>Baking Powder</li>
<PopoverSeparator className="-mx-4" />
<div className="flex items-center gap-2 font-semibold pb-2">
<PlusIcon className="stroke-current" />
Add new item
</div>
</div>
</PopoverContent>
</Popover>
)
```
Loading
Loading