Skip to content

Commit

Permalink
feat: tabs component (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
leduyhien152 authored Nov 9, 2023
1 parent 4eb192c commit fc12062
Show file tree
Hide file tree
Showing 15 changed files with 402 additions and 1 deletion.
4 changes: 4 additions & 0 deletions packages/components/tabs/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
root: true,
extends: ['custom/react'],
}
43 changes: 43 additions & 0 deletions packages/components/tabs/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"name": "@consolelabs/tabs",
"version": "0.0.1",
"sideEffects": false,
"main": "src/index.ts",
"files": [
"dist"
],
"publishConfig": {
"access": "public"
},
"license": "MIT",
"scripts": {
"build": "tsup src --dts",
"build:fast": "tsup src",
"dev": "pnpm build:fast -- --watch",
"lint": "eslint src/",
"clean": "rimraf dist .turbo",
"typecheck": "tsc --noEmit",
"prepack": "clean-package",
"postpack": "clean-package restore"
},
"peerDependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@consolelabs/icons": "workspace:*",
"@consolelabs/theme": "workspace:*",
"clean-package": "^2.2.0",
"eslint-config-custom": "workspace:*",
"prettier": "^3.0.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"tsconfig": "workspace:*"
},
"dependencies": {
"@radix-ui/react-tabs": "^1.0.4",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0"
},
"clean-package": "../../../clean-package.config.json"
}
1 change: 1 addition & 0 deletions packages/components/tabs/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './tabs'
28 changes: 28 additions & 0 deletions packages/components/tabs/src/tabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import * as RadixTabs from '@radix-ui/react-tabs'
import React from 'react'
import { tabs, TabTriggerProps } from '@consolelabs/theme'

const Tabs = RadixTabs.Root
const TabList = RadixTabs.List
const TabContent = RadixTabs.Content

const TabTrigger = React.forwardRef<
React.ElementRef<typeof RadixTabs.Trigger>,
React.ComponentPropsWithoutRef<typeof RadixTabs.Trigger> & TabTriggerProps
>(({ className, variant, disabled, ...props }, ref) => {
const { tabTriggerVariants, tabTriggerWrapperClassName } = tabs

return (
<div className={tabTriggerWrapperClassName}>
<RadixTabs.Trigger
className={tabTriggerVariants({ className, variant, disabled })}
disabled={disabled}
ref={ref}
{...props}
/>
</div>
)
})
TabTrigger.displayName = RadixTabs.Trigger.displayName

export { Tabs, TabList, TabContent, TabTrigger }
79 changes: 79 additions & 0 deletions packages/components/tabs/stories/tabs.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { Tabs, TabList, TabTrigger, TabContent } from '../src/tabs'
import { IconCoding, IconSetting, IconUser } from '@consolelabs/icons'

export default {
title: 'ui/Tabs',
}

export function Default() {
return (
<div className="space-y-4">
<div className="w-full max-w-md border rounded shadow">
<Tabs defaultValue="account">
<TabList className="flex justify-between py-1.5">
<TabTrigger value="account">
<IconUser width={16} height={16} />
Account
</TabTrigger>
<TabTrigger value="documents">
<IconCoding width={16} height={16} />
Documents
</TabTrigger>
<TabTrigger disabled value="settings">
<IconSetting width={16} height={16} />
Settings
</TabTrigger>
</TabList>

<div className="border-b" />

<div>
<TabContent value="account">
Make changes to your account.
</TabContent>
<TabContent value="documents">
Access and update your documents.
</TabContent>
<TabContent value="settings">
Edit your profile or update contact information.
</TabContent>
</div>
</Tabs>
</div>

<div className="w-full max-w-md border rounded shadow">
<Tabs defaultValue="account">
<TabList className="flex justify-between py-1.5">
<TabTrigger value="account" variant="solid">
Account
</TabTrigger>
<TabTrigger value="documents" variant="solid">
Documents
</TabTrigger>
<TabTrigger disabled value="settings" variant="solid">
Settings
</TabTrigger>
</TabList>

<div className="border-b" />

<div>
<TabContent value="account">
Make changes to your account.
</TabContent>
<TabContent value="documents">
Access and update your documents.
</TabContent>
<TabContent value="settings">
Edit your profile or update contact information.
</TabContent>
</div>
</Tabs>
</div>
</div>
)
}

Default.story = {
name: 'default',
}
5 changes: 5 additions & 0 deletions packages/components/tabs/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"extends": "tsconfig/react-library.json",
"include": ["src", "index.ts"],
"exclude": ["dist", "node_modules"]
}
7 changes: 7 additions & 0 deletions packages/components/tabs/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { defineConfig } from 'tsup'

export default defineConfig(() => ({
clean: true,
target: 'es2019',
format: ['cjs', 'esm'],
}))
1 change: 1 addition & 0 deletions packages/theme/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export * from './input-field'
export * from './list'
export * from './toggle-button'
export * from './select'
export * from './tabs'
53 changes: 53 additions & 0 deletions packages/theme/src/components/tabs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { VariantProps, cva } from 'class-variance-authority'

const tabTriggerVariants = cva(
[
'flex flex-1 items-center justify-center gap-x-1 text-sm font-medium px-1 py-1',
],
{
variants: {
variant: {
solid: '',
link: '',
},
disabled: {
true: '',
false: '',
},
},
compoundVariants: [
{
disabled: true,
className: 'text-neutral-400 cursor-not-allowed',
},
{
disabled: false,
variant: 'solid',
className:
'rounded text-neutral-600 hover:text-neutral-500 hover:bg-neutral-150 data-[state=active]:text-neutral-800 data-[state=active]:hover:text-neutral-500',
},
{
disabled: false,
variant: 'link',
className:
'text-neutral-600 hover:text-neutral-700 data-[state=active]:text-neutral-800 data-[state=active]:hover:text-neutral-700',
},
],
defaultVariants: {
variant: 'link',
disabled: false,
},
},
)

const tabTriggerWrapperClassName =
'inline-flex flex-1 px-2 border-r border-r-neutral-200 last:border-none sm:border-none'

const tabs = {
tabTriggerVariants,
tabTriggerWrapperClassName,
}

export type TabTriggerProps = VariantProps<typeof tabTriggerVariants>

export { tabs }
3 changes: 2 additions & 1 deletion packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,13 @@
"@radix-ui/react-scroll-area": "^1.0.5",
"@radix-ui/react-select": "^2.0.0",
"@radix-ui/react-switch": "^1.0.3",
"@radix-ui/react-tabs": "^1.0.4",
"@radix-ui/react-toggle-group": "^1.0.4",
"@radix-ui/react-tooltip": "^1.0.7",
"@tanstack/react-table": "^8.10.7",
"@uidotdev/usehooks": "^2.4.0",
"browser-string-hexer": "^1.0.0",
"bs58": "^5.0.0",
"@tanstack/react-table": "^8.10.7",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"vaul": "^0.7.2",
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/src/tabs/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './tabs'
export * from './trigger'
39 changes: 39 additions & 0 deletions packages/ui/src/tabs/tabs.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Tabs, TabList, TabTrigger, TabContent } from '.'

export default {
title: 'ui/Tabs',
}

export function Default() {
return (
<div className="w-full max-w-md p-2 border rounded shadow">
<Tabs defaultValue="account">
<TabList className="flex justify-between py-2">
<TabTrigger value="account">Account</TabTrigger>
<TabTrigger value="documents" variant="solid">
Documents
</TabTrigger>
<TabTrigger disabled value="settings">
Settings
</TabTrigger>
</TabList>

<div className="my-2 border-b border-b-neutral-200" />

<div>
<TabContent value="account">Make changes to your account.</TabContent>
<TabContent value="documents">
Access and update your documents.
</TabContent>
<TabContent value="settings">
Edit your profile or update contact information.
</TabContent>
</div>
</Tabs>
</div>
)
}

Default.story = {
name: 'default',
}
7 changes: 7 additions & 0 deletions packages/ui/src/tabs/tabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import * as RadixTabs from '@radix-ui/react-tabs'

const Tabs = RadixTabs.Root
const TabList = RadixTabs.List
const TabContent = RadixTabs.Content

export { Tabs, TabList, TabContent }
64 changes: 64 additions & 0 deletions packages/ui/src/tabs/trigger.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import * as RadixTabs from '@radix-ui/react-tabs'
import type { VariantProps } from 'class-variance-authority'
import { cva } from 'class-variance-authority'
import * as React from 'react'

const tabTrigger = cva(
[
'flex flex-1 items-center justify-center gap-x-1 text-sm font-medium px-1 py-0.5',
],
{
variants: {
variant: {
solid: '',
link: '',
},
disabled: {
true: '',
false: '',
},
},
compoundVariants: [
{
disabled: true,
className: 'text-neutral-400 cursor-not-allowed',
},
{
disabled: false,
variant: 'solid',
className:
'rounded text-neutral-600 hover:text-neutral-500 hover:bg-neutral-150 data-[state=active]:text-neutral-800',
},
{
disabled: false,
variant: 'link',
className:
'text-neutral-600 hover:text-neutral-700 data-[state=active]:text-neutral-800',
},
],
defaultVariants: {
variant: 'link',
disabled: false,
},
},
)

type Props = React.ComponentPropsWithoutRef<typeof RadixTabs.Trigger> &
VariantProps<typeof tabTrigger>

const TabTrigger = React.forwardRef<
React.ElementRef<typeof RadixTabs.Trigger>,
Props
>(({ className, variant, disabled, ...props }, ref) => (
<div className="inline-flex flex-1 px-2 border-r border-r-neutral-200 last:border-none">
<RadixTabs.Trigger
className={tabTrigger({ className, variant, disabled })}
disabled={disabled}
ref={ref}
{...props}
/>
</div>
))
TabTrigger.displayName = RadixTabs.Trigger.displayName

export { TabTrigger }
Loading

1 comment on commit fc12062

@vercel
Copy link

@vercel vercel bot commented on fc12062 Nov 9, 2023

Choose a reason for hiding this comment

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

Successfully deployed to the following URLs:

websites-mochi – ./apps/mochi-web

websites-mochi-consolelabs.vercel.app
websites-mochi-git-main-consolelabs.vercel.app
beta.mochi.gg
websites-mochi.vercel.app

Please sign in to comment.