diff --git a/.changeset/loose-grapes-bake.md b/.changeset/loose-grapes-bake.md
new file mode 100644
index 00000000..1b302227
--- /dev/null
+++ b/.changeset/loose-grapes-bake.md
@@ -0,0 +1,5 @@
+---
+'@example/ui-playground': patch
+---
+
+feat: add separator variant & examples.
diff --git a/.changeset/wicked-frogs-live.md b/.changeset/wicked-frogs-live.md
new file mode 100644
index 00000000..b763eb75
--- /dev/null
+++ b/.changeset/wicked-frogs-live.md
@@ -0,0 +1,5 @@
+---
+'@example/ui-playground': patch
+---
+
+feat: add new tanstack table component examples.
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 29d9fb3a..6c06dac8 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -56,5 +56,6 @@
],
"[sql]": {
"editor.defaultFormatter": "adpyke.vscode-sql-formatter"
- }
+ },
+ "typescript.experimental.useTsgo": false
}
diff --git a/examples/ui-playground/package.json b/examples/ui-playground/package.json
index bf8c343c..5a889ef5 100644
--- a/examples/ui-playground/package.json
+++ b/examples/ui-playground/package.json
@@ -3,7 +3,7 @@
"version": "0.1.0-alpha.78",
"private": true,
"scripts": {
- "dev": "NODE_OPTIONS='--inspect' next dev --port 3003 --turbopack",
+ "dev": "NODE_OPTIONS='--inspect' next dev --port 3004 --turbopack",
"build": "next build",
"start": "next start",
"lint": "eslint .",
@@ -20,6 +20,7 @@
"@phosphor-icons/react": "^2.1.8",
"@tailwindcss/postcss": "^4.1.7",
"@tanstack/react-query": "^5.71.5",
+ "@tanstack/react-table": "^8.21.3",
"@tiptap/extension-color": "^2.26.3",
"@tiptap/extension-link": "2.26.3",
"@tiptap/extension-text-align": "^2.26.3",
diff --git a/examples/ui-playground/src/app/playground/shadcn/page-sidebar.tsx b/examples/ui-playground/src/app/playground/shadcn/page-sidebar.tsx
index 59264dde..26c5c825 100644
--- a/examples/ui-playground/src/app/playground/shadcn/page-sidebar.tsx
+++ b/examples/ui-playground/src/app/playground/shadcn/page-sidebar.tsx
@@ -27,9 +27,11 @@ const navigationItems = [
{ href: '#link', label: 'Link' },
{ href: '#pagination', label: 'Pagination' },
{ href: '#progress', label: 'Progress' },
+ { href: '#separator', label: 'Separator' },
{ href: '#select', label: 'Select' },
{ href: '#slider', label: 'Slider' },
{ href: '#switch', label: 'Switch' },
+ { href: '#table', label: 'Table' },
{ href: '#tabs', label: 'Tabs' },
{ href: '#tooltip', label: 'Tooltip' },
{ href: '#dropdown-menu', label: 'Dropdown Menu' },
diff --git a/examples/ui-playground/src/app/playground/shadcn/page.tsx b/examples/ui-playground/src/app/playground/shadcn/page.tsx
index 86a0c896..b2e6bf54 100644
--- a/examples/ui-playground/src/app/playground/shadcn/page.tsx
+++ b/examples/ui-playground/src/app/playground/shadcn/page.tsx
@@ -20,8 +20,10 @@ import { PaginationSection } from './pagination-section'
import { ProgressSection } from './progress-section'
import { RichTextSection } from './rich-text-section'
import { SelectSection } from './select-section'
+import { SeparatorSection } from './separator-section'
import { SliderSection } from './slider-section'
import { SwitchSection } from './switch-section'
+import { TableSection } from './table-section'
import { TabsSection } from './tabs-section'
import { TextareaSection } from './textarea-section'
import { ToastSection } from './toast-section'
@@ -72,7 +74,7 @@ export default function ComboboxPage() {
Input OTP
- A
+
Link
@@ -93,10 +95,18 @@ export default function ComboboxPage() {
Slider
+
+ Separator
+
+
Switch
+
+ Table
+
+
Tabs
diff --git a/examples/ui-playground/src/app/playground/shadcn/separator-section.tsx b/examples/ui-playground/src/app/playground/shadcn/separator-section.tsx
new file mode 100644
index 00000000..c3515f37
--- /dev/null
+++ b/examples/ui-playground/src/app/playground/shadcn/separator-section.tsx
@@ -0,0 +1,47 @@
+import React from 'react'
+
+import { Separator, Typography } from '@genseki/react/v2'
+
+import { PlaygroundCard } from '~/src/components/card'
+
+function BasicSeparatorExamples() {
+ return (
+
+
+ Left content
+
+ Right content
+
+
+ Top
+
+ Bottom
+
+
+ Left content
+
+ Right content
+
+
+ Top
+
+ Bottom
+
+
+ )
+}
+
+export function SeparatorSection() {
+ return (
+
+
+
+ Visual dividers for grouping content horizontally or vertically.
+
+
+
+
+
+
+ )
+}
diff --git a/examples/ui-playground/src/app/playground/shadcn/table-section.tsx b/examples/ui-playground/src/app/playground/shadcn/table-section.tsx
new file mode 100644
index 00000000..7daa3ec3
--- /dev/null
+++ b/examples/ui-playground/src/app/playground/shadcn/table-section.tsx
@@ -0,0 +1,241 @@
+import React from 'react'
+
+import { createColumnHelper, getCoreRowModel, useReactTable } from '@tanstack/react-table'
+
+import { TanstackTable } from '@genseki/react'
+import { Typography } from '@genseki/react/v2'
+
+import { PlaygroundCard } from '../../../components/card'
+
+type User = {
+ id: number
+ fname: string
+ lname: string
+ food: string
+}
+
+const columnHelper = createColumnHelper()
+
+const columns = [
+ columnHelper.accessor('id', {
+ header: 'ID',
+ cell: (props) => {props.getValue()}
,
+ }),
+ columnHelper.accessor('fname', {
+ header: 'First Name',
+ cell: (props) => {props.getValue()}
,
+ }),
+ columnHelper.accessor('lname', {
+ header: 'Last Name',
+ cell: (props) => {props.getValue()}
,
+ }),
+ columnHelper.accessor('food', {
+ header: 'Favorite Food',
+ cell: (props) => {props.getValue()}
,
+ }),
+]
+
+function BasicTable() {
+ const users: User[] = [
+ {
+ id: 1,
+ fname: 'Supakorn',
+ lname: 'Netsuwan',
+ food: 'Hamburger',
+ },
+ {
+ id: 2,
+ fname: 'Jane',
+ lname: 'Doe',
+ food: 'Pizza',
+ },
+ {
+ id: 3,
+ fname: 'John',
+ lname: 'Smith',
+ food: 'Sushi',
+ },
+ {
+ id: 4,
+ fname: 'Emily',
+ lname: 'Johnson',
+ food: 'Tacos',
+ },
+ {
+ id: 5,
+ fname: 'Michael',
+ lname: 'Brown',
+ food: 'Pasta',
+ },
+ ]
+
+ const table = useReactTable({
+ getCoreRowModel: getCoreRowModel(),
+ data: users,
+ columns,
+ })
+
+ return (
+
+
+
+ )
+}
+
+function SortableTable() {
+ const users: User[] = [
+ {
+ id: 1,
+ fname: 'Supakorn',
+ lname: 'Netsuwan',
+ food: 'Hamburger',
+ },
+ {
+ id: 2,
+ fname: 'Jane',
+ lname: 'Doe',
+ food: 'Pizza',
+ },
+ {
+ id: 3,
+ fname: 'John',
+ lname: 'Smith',
+ food: 'Sushi',
+ },
+ {
+ id: 4,
+ fname: 'Emily',
+ lname: 'Johnson',
+ food: 'Tacos',
+ },
+ {
+ id: 5,
+ fname: 'Michael',
+ lname: 'Brown',
+ food: 'Pasta',
+ },
+ ]
+
+ const table = useReactTable({
+ getCoreRowModel: getCoreRowModel(),
+ data: users,
+ columns,
+ })
+
+ return (
+
+
+
+ )
+}
+
+function LoadingTable() {
+ const users: User[] = []
+
+ const table = useReactTable({
+ getCoreRowModel: getCoreRowModel(),
+ data: users,
+ columns,
+ })
+
+ return (
+
+
+
+ )
+}
+
+function EmptyTable() {
+ const users: User[] = []
+
+ const table = useReactTable({
+ getCoreRowModel: getCoreRowModel(),
+ data: users,
+ columns,
+ })
+
+ return (
+
+
+
+ )
+}
+
+function ErrorTable() {
+ const users: User[] = []
+
+ const table = useReactTable({
+ getCoreRowModel: getCoreRowModel(),
+ data: users,
+ columns,
+ })
+
+ return (
+
+
+
+ )
+}
+
+export const TableSection = React.memo(function () {
+ return (
+
+
+
+ A simple table with basic data display functionality.
+
+
+
+
+
+
+
+
+
+ Table with sortable columns. Click on column headers to sort.
+
+
+
+
+
+
+
+
+ Table displaying a loading state while data is being fetched.
+
+
+
+
+
+
+
+
+ Table displaying an empty state when no data is available.
+
+
+
+
+
+
+
+
+ Table displaying an error state when data fetching fails.
+
+
+
+
+
+
+ )
+})
+
+TableSection.displayName = 'TableSection'
diff --git a/packages/react/src/react/components/primitives/tanstack-table.tsx b/packages/react/src/react/components/primitives/tanstack-table.tsx
index a7ca1e7f..b2f8c2ff 100644
--- a/packages/react/src/react/components/primitives/tanstack-table.tsx
+++ b/packages/react/src/react/components/primitives/tanstack-table.tsx
@@ -14,6 +14,7 @@ import {
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from './table'
+import { Typography } from '../../../../v2'
import { cn } from '../../utils/cn'
type RowClickHandler = (row: Row, e: React.MouseEvent) => void
@@ -133,15 +134,22 @@ export function TanstackTable({
role={canSort ? 'button' : undefined}
tabIndex={canSort ? 0 : -1}
>
- 1 && 'justify-center'
)}
>
- {children}
+
+ {children}
+
{canSort && children && getSortIcon(header.column.getIsSorted())}
-
+
)
})}
@@ -230,14 +238,12 @@ export const TableEmpty = (props: {
{props.emptyFallback ?? (
-
+
-
- {props.emptyMessage ?? 'No data'}
-
+
{props.emptyMessage ?? 'No data'}
)}
diff --git a/packages/react/v2/components/primitives/separator.tsx b/packages/react/v2/components/primitives/separator.tsx
index 1d9ec5a7..4a6237cf 100644
--- a/packages/react/v2/components/primitives/separator.tsx
+++ b/packages/react/v2/components/primitives/separator.tsx
@@ -2,28 +2,44 @@
import React from 'react'
import * as SeparatorPrimitive from '@radix-ui/react-separator'
-
-import { cn } from '../../../src/react/utils/cn'
+import { cva, type VariantProps } from 'class-variance-authority'
/**
* Shadcn component
*/
+const separator = cva('shrink-0', {
+ variants: {
+ variant: {
+ solid:
+ 'bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px',
+ dashed: `bg-size-[12px_12px] bg-repeat
+ data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=horizontal]:bg-[linear-gradient(to_right,var(--color-border-primary)_50%,transparent_50%)]
+ data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px data-[orientation=vertical]:bg-[linear-gradient(to_bottom,var(--color-border-primary)_50%,transparent_50%)]
+ `,
+ },
+ },
+ defaultVariants: {
+ variant: 'solid',
+ },
+})
+
+type SeparatorProps = React.ComponentProps
&
+ VariantProps
+
function Separator({
className,
orientation = 'horizontal',
+ variant,
decorative = true,
...props
-}: React.ComponentProps) {
+}: SeparatorProps) {
return (
)
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4a1434d2..48f99003 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -171,6 +171,9 @@ importers:
'@tanstack/react-query':
specifier: ^5.71.5
version: 5.76.1(react@19.1.0)
+ '@tanstack/react-table':
+ specifier: ^8.21.3
+ version: 8.21.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@tiptap/extension-color':
specifier: ^2.26.3
version: 2.26.3(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))(@tiptap/extension-text-style@2.26.3(@tiptap/core@2.26.3(@tiptap/pm@2.26.3)))