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(ui): chips #71

Merged
merged 2 commits into from
Oct 23, 2024
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
5 changes: 5 additions & 0 deletions .changeset/clever-sloths-hunt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@groovy-box/ui': patch
---

chip components
19 changes: 19 additions & 0 deletions apps/docs/app/ui/IndividialComp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'use client';
import React from 'react';
import { Chip } from '@groovy-box/ui';

const ChipEle = () => {
return (
<div className='grv-flex grv-flex-wrap grv-gap-4 grv-p-4'>
<Chip clickable onClick={() => alert('Clicked!')}>
Clickable
</Chip>
<Chip onDelete={() => alert('Delete clicked!')}>Deletable</Chip>
<Chip href='https://ui.soumyasagar.in' target='_blank'>
Link
</Chip>
</div>
);
};

export { ChipEle };
207 changes: 207 additions & 0 deletions apps/docs/content/docs/(components)/chips.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
---
title: Chip
description: Various types and configurations of Chip component.
---

## Default

import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
import { Chip, Avatar, AvatarImage, AvatarFallback } from '@/app/ui';
import ComponenentWrapper from '@/app/ui/ComponenentWrapper';
import { Star, Mail } from 'lucide-react';
import { ChipEle } from '@/app/ui/IndividialComp';

<Tabs items={['Preview', 'Code']}>
<Tab value='Preview'>
<ComponenentWrapper>
<div className="grv-flex grv-flex-wrap grv-gap-4 grv-p-4">
<Chip>Default</Chip>
</div>
</ComponenentWrapper>
</Tab>

<Tab value='Code'>
```tsx
import { Chip } from "@groovy-box/ui";

export function ChipDefault() {
return (
<div className="grv-flex grv-flex-wrap grv-gap-4 grv-p-4">
<Chip>Default</Chip>
</div>
);
}
```

</Tab>
</Tabs>

## Variants

<Tabs items={['Preview', 'Code']}>
<Tab value='Preview'>
<ComponenentWrapper>
<div className="grv-flex grv-flex-wrap grv-gap-4 grv-p-4">
<Chip variant="filled">Filled</Chip>
<Chip variant="outlined">Outlined</Chip>
</div>
</ComponenentWrapper>
</Tab>

<Tab value='Code'>
```tsx
import { Chip } from "@groovy-box/ui";

export function ChipVariants() {
return (
<div className="grv-flex grv-flex-wrap grv-gap-4 grv-p-4">
<Chip variant="filled">Filled</Chip>
<Chip variant="outlined">Outlined</Chip>
</div>
);
}
```

</Tab>
</Tabs>

## Sizes

<Tabs items={['Preview', 'Code']}>
<Tab value='Preview'>
<ComponenentWrapper>
<div className="grv-flex grv-flex-wrap grv-gap-4 grv-p-4">
<Chip size="sm">Small</Chip>
<Chip size="md">Medium</Chip>
<Chip size="lg">Large</Chip>
</div>
</ComponenentWrapper>
</Tab>

<Tab value='Code'>
```tsx
import { Chip } from "@groovy-box/ui";

export function ChipSizes() {
return (
<div className="grv-flex grv-flex-wrap grv-gap-4 grv-p-4">
<Chip size="sm">Small</Chip>
<Chip size="md">Medium</Chip>
<Chip size="lg">Large</Chip>
</div>
);
}
```

</Tab>
</Tabs>

## With Icons

<Tabs items={['Preview', 'Code']}>
<Tab value='Preview'>
<ComponenentWrapper>
<div
supressHydrationWarning
className="grv-flex grv-flex-wrap grv-gap-4 grv-p-4">
<Chip
supressHydrationWarning
beforeChildren={
<Avatar>
<AvatarImage
src="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?q=80&w=1887&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
alt="Avatar Image"
/>
<AvatarFallback>AB</AvatarFallback>
</Avatar>
}
>
User Chip
</Chip>
<Chip variant="outlined" afterChildren={<Star className="grv-h-4 grv-w-4" />}>
Starred
</Chip>
<Chip
beforeChildren={<Mail className="grv-h-4 grv-w-4" />}
afterChildren={
<span className="grv-bg-primary-foreground grv-text-primary grv-rounded-full grv-px-2 grv-text-sm">
99+
</span>
}
>
Inbox
</Chip>
</div>
</ComponenentWrapper>
</Tab>

<Tab value='Code'>
```tsx
import { Chip, Avatar, AvatarImage, AvatarFallback } from "@groovy-box/ui";
import { Star, Mail } from 'lucide-react';

export function ChipWithIcons() {
return (
<div
supressHydrationWarning
className="grv-flex grv-flex-wrap grv-gap-4 grv-p-4">
<Chip
beforeChildren={
<Avatar>
<AvatarImage
src="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?q=80&w=1887&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
alt="Avatar Image"
/>
<AvatarFallback>AB</AvatarFallback>
</Avatar>
}
>
User Chip
</Chip>
<Chip variant="outlined" afterChildren={<Star className="grv-h-4 grv-w-4" />}>
Starred
</Chip>
<Chip
beforeChildren={<Mail className="grv-h-4 grv-w-4" />}
afterChildren={
<span className="grv-bg-primary-foreground grv-text-primary grv-rounded-full grv-px-2 grv-text-sm">
99+
</span>
}
>
Inbox
</Chip>
</div>
);
}
```

</Tab>
</Tabs>

## Interactions

<Tabs items={['Preview', 'Code']}>
<Tab value='Preview'>
<ComponenentWrapper>
<ChipEle/>
</ComponenentWrapper>
</Tab>

<Tab value='Code'>
```tsx
import { Chip } from "@groovy-box/ui";

export function ChipInteractions() {
return (
<div className="grv-flex grv-flex-wrap grv-gap-4 grv-p-4">
<Chip clickable onClick={() => alert('Clicked!')}>Clickable</Chip>
<Chip onDelete={() => alert('Delete clicked!')}>Deletable</Chip>
<Chip href="https://ui.soumyasagar.in" target="_blank">Link</Chip>
</div>
);
}
```

</Tab>
</Tabs>
141 changes: 141 additions & 0 deletions apps/ui/lib/components/Chip/Chip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
'use client';
import * as React from 'react';
import { cva, type VariantProps } from 'class-variance-authority';
import { X as CloseIcon } from 'lucide-react';

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

const chipVariants = cva(
'grv-inline-flex ui grv-items-center grv-rounded-full grv-text-sm grv-font-medium grv-transition-colors focus:grv-outline-none focus:grv-ring-2 grv-ring-ring grv-ring-offset-2',
{
variants: {
variant: {
filled: 'grv-bg-primary-500 ui',
outlined: 'grv-border-2 grv-border-solid grv-border-accent ui',
},
size: {
sm: 'grv-h-6 grv-px-3 ui',
md: 'grv-h-8 grv-px-4 ui',
lg: 'grv-h-10 grv-px-5 ui',
},
clickable: {
true: 'grv-cursor-pointer',
false: '',
},
},
defaultVariants: {
variant: 'filled',
size: 'md',
clickable: false,
},
}
);

export interface ChipDivProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof chipVariants> {
onDelete?: () => void;
as?: React.ElementType;
href?: never;
beforeChildren?: React.ReactNode;
afterChildren?: React.ReactNode;
}

export interface ChipAnchorProps
extends React.HTMLAttributes<HTMLAnchorElement>,
VariantProps<typeof chipVariants> {
onDelete?: () => void;
href?: string;
target?: string;
as?: React.ElementType;
beforeChildren?: React.ReactNode;
afterChildren?: React.ReactNode;
}

export type ChipProps = ChipAnchorProps | ChipDivProps;

const Chip = React.forwardRef<HTMLDivElement | HTMLAnchorElement, ChipProps>(
(
{
className,
variant,
size,
clickable,
onDelete,
href,
as,
beforeChildren,
afterChildren,
children,
...props
},
ref
) => {
const Component = as || (href ? 'a' : 'div');
const isClickable = Boolean(clickable || href || props.onClick);

console.log(variant);
const textColor =
variant === 'outlined' ? 'grv-text-accent' : 'grv-text-text-primary';

console.log(size);

const textSize =
size === 'sm'
? 'grv-text-[10px]'
: size === 'md'
? 'grv-text-[12px]'
: 'grv-text-[14px]';

return (
<Component
ref={ref}
className={cn(
chipVariants({ variant, size, clickable: isClickable }),
'grv-decoration-primary-100 grv-underline-offset-2 grv-flex grv-overflow-hidden ui',
className
)}
{...(href && { href })}
{...props}
>
{beforeChildren && (
<div
className={cn(
'grv-flex grv-items-center grv-justify-center grv-text-text-primary grv-mr-2 grv-w-[20px] grv-h-[20px] ui grv-overflow-hidden grv-rounded-full grv-object-cover'
)}
>
{beforeChildren}
</div>
)}
<div className={cn(textColor, textSize)}>{children}</div>
{afterChildren && (
<div
className={cn(
`grv-flex grv-items-center grv-justify-center ${textColor} grv-ml-2 ui`
)}
>
{afterChildren}
</div>
)}
{onDelete && (
<div
className={cn(
'grv-ml-2 grv-rounded-full grv-bg-text-primary grv-cursor-pointer grv-py-[4px] grv-px-[4px] grv-transition-colors grv-text-primary grv-opacity-50 hover:grv-opacity-60',
textSize
)}
onClick={(e) => {
e.stopPropagation();
onDelete();
}}
>
<CloseIcon className={cn('grv-h-[10px] grv-w-[10px]')} />
</div>
)}
</Component>
);
}
);

Chip.displayName = 'Chip';

export { Chip };
1 change: 1 addition & 0 deletions apps/ui/lib/components/Chip/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Chip';
1 change: 1 addition & 0 deletions apps/ui/lib/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ export * from './components/Navigation-menu';
export * from './components/Switch';
export * from './components/Toast';
export * from './components/Progress';
export * from './components/Chip';
Loading
Loading