Skip to content

Commit

Permalink
feat: add popover ui
Browse files Browse the repository at this point in the history
  • Loading branch information
siloneco committed Nov 8, 2023
1 parent 103a304 commit 5b74591
Show file tree
Hide file tree
Showing 5 changed files with 275 additions and 0 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"@markuplint/jsx-parser": "^3.11.0",
"@markuplint/react-spec": "^3.12.0",
"@radix-ui/react-avatar": "^1.0.4",
"@radix-ui/react-popover": "^1.0.7",
"@radix-ui/react-slot": "^1.0.2",
"@stoplight/prism-cli": "^5.4.0",
"@storybook/addon-essentials": "^7.5.1",
Expand Down
159 changes: 159 additions & 0 deletions pnpm-lock.yaml

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

41 changes: 41 additions & 0 deletions src/components/ui/Popover/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Button } from '../Button';

import { Popover, PopoverTrigger, PopoverContent } from '.';

import type { Meta, StoryObj } from '@storybook/react';

import { cn } from '@/libs/utils';

const meta: Meta<typeof Popover> = {
component: Popover,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
};

export default meta;

type Story = StoryObj<typeof Popover>;

export const Default: Story = {
render: () => (
<Popover>
<PopoverTrigger>Popover</PopoverTrigger>
<PopoverContent>Content</PopoverContent>
</Popover>
),
};

export const WithButton: Story = {
render: () => (
<Popover>
<PopoverTrigger asChild>
<Button>Popover</Button>
</PopoverTrigger>
<PopoverContent className={cn('text-white', 'bg-black')}>
Content
</PopoverContent>
</Popover>
),
};
42 changes: 42 additions & 0 deletions src/components/ui/Popover/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { render } from '@testing-library/react';

import '@testing-library/jest-dom';
import { Popover, PopoverTrigger, PopoverContent } from '.';

describe('ui/Popoverのテスト', () => {
it('renders trigger text correctly', () => {
const triggerText = 'Trigger';
const screen = render(
<Popover>
<PopoverTrigger>{triggerText}</PopoverTrigger>
<PopoverContent>Content</PopoverContent>
</Popover>
);

expect(screen.getByText(triggerText)).toBeInTheDocument();
});

it('renders content correctly', () => {
const content = 'Content';
const screen = render(
<Popover open>
<PopoverTrigger>Trigger</PopoverTrigger>
<PopoverContent>{content}</PopoverContent>
</Popover>
);

expect(screen.getByText(content)).toBeInTheDocument();
});

it('not renders content by default', () => {
const content = 'Content';
const screen = render(
<Popover>
<PopoverTrigger>Trigger</PopoverTrigger>
<PopoverContent>{content}</PopoverContent>
</Popover>
);

expect(() => screen.getByText(content)).toThrow();
});
});
32 changes: 32 additions & 0 deletions src/components/ui/Popover/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use client';

import { forwardRef } from 'react';

import * as PopoverPrimitive from '@radix-ui/react-popover';

import { cn } from '@/libs/utils';

const Popover = PopoverPrimitive.Root;

const PopoverTrigger = PopoverPrimitive.Trigger;

const PopoverContent = forwardRef<
React.ElementRef<typeof PopoverPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content
ref={ref}
align={align}
sideOffset={sideOffset}
className={cn(
'z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
className
)}
{...props}
/>
</PopoverPrimitive.Portal>
));
PopoverContent.displayName = PopoverPrimitive.Content.displayName;

export { Popover, PopoverTrigger, PopoverContent };

0 comments on commit 5b74591

Please sign in to comment.