Skip to content
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
2 changes: 2 additions & 0 deletions src/frontend/packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
},
"dependencies": {
"@radix-ui/react-avatar": "^1.1.2",
"@radix-ui/react-label": "^2.1.1",
"@radix-ui/react-popover": "^1.1.5",
"@radix-ui/react-separator": "^1.1.1",
"@radix-ui/react-slot": "^1.1.1",
"@radix-ui/react-toast": "^1.2.4",
Expand Down
1 change: 1 addition & 0 deletions src/frontend/packages/ui/src/components/Input/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Input } from './input';
87 changes: 87 additions & 0 deletions src/frontend/packages/ui/src/components/Input/input.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { Meta, StoryObj } from '@storybook/react';
import { Input } from './input';
import { Label } from '../Label';
import { Button } from '../Button';

const meta: Meta<typeof Input> = {
title: 'Widget/Input',
component: Input,
parameters: {
layout: 'centered',
},
decorators: [
(Story) => (
<div style={{ width: '600px', padding: '10px' }}>
<Story />
</div>
),
],
tags: ['autodocs'],
argTypes: {
placeholder: { control: 'text' },
disabled: { control: 'boolean' },
},
};
export default meta;

type Story = StoryObj<typeof Input>;

export const Default: Story = {
args: {
placeholder: 'Default input',
},
};

export const Disabled: Story = {
args: {
placeholder: 'Disabled input',
disabled: true,
},
};

export const WithLabel: Story = {
args: {
placeholder: 'Enter your name',
disabled: false,
id: 'name',
},
render: (args) => (
<div className="flex w-full items-center space-x-2">
<Label htmlFor={args.id}>Name</Label>
<Input
id={args.id}
placeholder={args.placeholder}
disabled={args.disabled}
/>
</div>
),
};

export const Form: Story = {
args: {
placeholder: 'Enter your name',
disabled: false,
id: 'name',
},
render: (args) => (
<div className="flex w-full items-center">
<Label
htmlFor={args.id}
className="mr-3"
>
Name
</Label>
<Input
id={args.id}
placeholder={args.placeholder}
disabled={args.disabled}
/>
<Button
variant="ghost"
type="submit"
>
확인
</Button>
</div>
),
};
20 changes: 20 additions & 0 deletions src/frontend/packages/ui/src/components/Input/input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as React from 'react';

import { cn } from '@workspace/ui/lib/utils';

const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<'input'>>(({ className, ...props }, ref) => {
return (
<input
type="text"
className={cn(
'flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
className,
)}
ref={ref}
{...props}
/>
);
});
Input.displayName = 'Input';

export { Input };
1 change: 1 addition & 0 deletions src/frontend/packages/ui/src/components/Label/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Label } from './label';
23 changes: 23 additions & 0 deletions src/frontend/packages/ui/src/components/Label/label.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { Meta, StoryObj } from '@storybook/react';
import { Label } from './label';
const meta: Meta<typeof Label> = {
title: 'Widget/Label',
component: Label,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {
children: { control: 'text', description: 'Label text' },
htmlFor: { control: 'text' },
},
};
export default meta;
type Story = StoryObj<typeof Label>;

export const Default: Story = {
args: {
htmlFor: 'name',
children: '공작새',
},
};
22 changes: 22 additions & 0 deletions src/frontend/packages/ui/src/components/Label/label.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use client';

import * as React from 'react';
import * as LabelPrimitive from '@radix-ui/react-label';
import { cva, type VariantProps } from 'class-variance-authority';

import { cn } from '@workspace/ui/lib/utils';

const labelVariants = cva('text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70');

const Label = React.forwardRef<React.ElementRef<typeof LabelPrimitive.Root>, React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & VariantProps<typeof labelVariants>>(
({ className, ...props }, ref) => (
<LabelPrimitive.Root
ref={ref}
className={cn(labelVariants(), className)}
{...props}
/>
),
);
Label.displayName = LabelPrimitive.Root.displayName;

export { Label };
1 change: 1 addition & 0 deletions src/frontend/packages/ui/src/components/Popover/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor } from './popover';
110 changes: 110 additions & 0 deletions src/frontend/packages/ui/src/components/Popover/popover.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { Meta, StoryFn, StoryObj } from '@storybook/react';
import { Input } from '../Input';
import { Label } from '../Label';
import { Button } from '../Button';
import { Avatar, AvatarFallback, AvatarImage } from '../Avatar';
import { Popover, PopoverContent, PopoverTrigger } from './popover';

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

type Story = StoryObj<typeof Popover>;

const Template: StoryFn = (args) => (
<Popover>
<PopoverTrigger asChild>
<Avatar
variant="default"
className="cursor-pointer"
>
<AvatarImage src="https://github.com/shadcn.png" />
<AvatarFallback>Avatar</AvatarFallback>
</Avatar>
</PopoverTrigger>
<PopoverContent
align="end"
className="w-72 "
>
{args.children}
</PopoverContent>
</Popover>
);

export const Default: Story = Template.bind({});
Default.args = {
children: (
<div className="flex flex-col items-start space-y-4">
<Button
variant="ghost"
size="sm"
className="text-xs"
>
LOGOUT
</Button>
<Avatar
variant="default"
className="w-full h-full"
>
<AvatarImage src="https://github.com/shadcn.png" />
<AvatarFallback>Avatar</AvatarFallback>
</Avatar>
<div className="w-full flex flex-col space-y-2 items-end">
<div className="flex w-full items-center space-x-2">
<Label htmlFor="name">Name</Label>
<Input
id="name"
disabled={true}
placeholder="Enter your name"
value={'공작새'}
/>
</div>
<Button
variant="outline"
size="sm"
className="text-xs"
>
Edit Profile
</Button>
</div>
</div>
),
};

export const EditMode: Story = Template.bind({});
EditMode.args = {
children: (
<div className="flex flex-col space-y-4 items-end">
<div className="flex w-full items-center space-x-2">
<Label htmlFor="profile">Profile</Label>
<Input
id="profile"
disabled={false}
placeholder="Enter your profile url"
type="file"
/>
</div>
<div className="flex w-full items-center space-x-2">
<Label htmlFor="name">Name</Label>
<Input
id="name"
disabled={false}
placeholder="Enter your name"
/>
</div>
<Button
variant="outline"
size="sm"
className="text-xs"
>
SAVE
</Button>
</div>
),
};
33 changes: 33 additions & 0 deletions src/frontend/packages/ui/src/components/Popover/popover.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"use client"

import * as React from "react"
import * as PopoverPrimitive from "@radix-ui/react-popover"

import { cn } from "@workspace/ui/lib/utils"

const Popover = PopoverPrimitive.Root

const PopoverTrigger = PopoverPrimitive.Trigger

const PopoverAnchor = PopoverPrimitive.Anchor

const PopoverContent = React.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, PopoverAnchor }
3 changes: 3 additions & 0 deletions src/frontend/packages/ui/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ export * from './Toast';
export * from './Resizable';
export * from './Avatar';
export * from './Separate';
export * from './Popover';
export * from './Label';
export * from './Input';
Loading
Loading