1
0
Fork 0
This repository has been archived on 2025-09-02. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
mareshq-midgard/src/components/ui/table.tsx

124 lines
4.1 KiB
TypeScript

'use client'
import clsx from 'clsx'
import type React from 'react'
import { createContext, useContext, useState } from 'react'
import { Link } from './link'
const TableContext = createContext<{ bleed: boolean; dense: boolean; grid: boolean; striped: boolean }>({
bleed: false,
dense: false,
grid: false,
striped: false,
})
export function Table({
bleed = false,
dense = false,
grid = false,
striped = false,
className,
children,
...props
}: { bleed?: boolean; dense?: boolean; grid?: boolean; striped?: boolean } & React.ComponentPropsWithoutRef<'div'>) {
return (
<TableContext.Provider value={{ bleed, dense, grid, striped } as React.ContextType<typeof TableContext>}>
<div className="flow-root">
<div {...props} className={clsx(className, '-mx-[--gutter] overflow-x-auto whitespace-nowrap')}>
<div className={clsx('inline-block min-w-full align-middle', !bleed && 'sm:px-[--gutter]')}>
<table className="min-w-full text-left text-sm/6 text-zinc-950 dark:text-white">{children}</table>
</div>
</div>
</div>
</TableContext.Provider>
)
}
export function TableHead({ className, ...props }: React.ComponentPropsWithoutRef<'thead'>) {
return <thead {...props} className={clsx(className, 'text-zinc-500 dark:text-zinc-400')} />
}
export function TableBody(props: React.ComponentPropsWithoutRef<'tbody'>) {
return <tbody {...props} />
}
const TableRowContext = createContext<{ href?: string; target?: string; title?: string }>({
href: undefined,
target: undefined,
title: undefined,
})
export function TableRow({
href,
target,
title,
className,
...props
}: { href?: string; target?: string; title?: string } & React.ComponentPropsWithoutRef<'tr'>) {
let { striped } = useContext(TableContext)
return (
<TableRowContext.Provider value={{ href, target, title } as React.ContextType<typeof TableRowContext>}>
<tr
{...props}
className={clsx(
className,
href &&
'has-[[data-row-link][data-focus]]:outline has-[[data-row-link][data-focus]]:outline-2 has-[[data-row-link][data-focus]]:-outline-offset-2 has-[[data-row-link][data-focus]]:outline-blue-500 dark:focus-within:bg-white/[2.5%]',
striped && 'even:bg-zinc-950/[2.5%] dark:even:bg-white/[2.5%]',
href && striped && 'hover:bg-zinc-950/5 dark:hover:bg-white/5',
href && !striped && 'hover:bg-zinc-950/[2.5%] dark:hover:bg-white/[2.5%]'
)}
/>
</TableRowContext.Provider>
)
}
export function TableHeader({ className, ...props }: React.ComponentPropsWithoutRef<'th'>) {
let { bleed, grid } = useContext(TableContext)
return (
<th
{...props}
className={clsx(
className,
'border-b border-b-zinc-950/10 px-4 py-2 font-medium first:pl-[var(--gutter,theme(spacing.2))] last:pr-[var(--gutter,theme(spacing.2))] dark:border-b-white/10',
grid && 'border-l border-l-zinc-950/5 first:border-l-0 dark:border-l-white/5',
!bleed && 'sm:first:pl-1 sm:last:pr-1'
)}
/>
)
}
export function TableCell({ className, children, ...props }: React.ComponentPropsWithoutRef<'td'>) {
let { bleed, dense, grid, striped } = useContext(TableContext)
let { href, target, title } = useContext(TableRowContext)
let [cellRef, setCellRef] = useState<HTMLElement | null>(null)
return (
<td
ref={href ? setCellRef : undefined}
{...props}
className={clsx(
className,
'relative px-4 first:pl-[var(--gutter,theme(spacing.2))] last:pr-[var(--gutter,theme(spacing.2))]',
!striped && 'border-b border-zinc-950/5 dark:border-white/5',
grid && 'border-l border-l-zinc-950/5 first:border-l-0 dark:border-l-white/5',
dense ? 'py-2.5' : 'py-4',
!bleed && 'sm:first:pl-1 sm:last:pr-1'
)}
>
{href && (
<Link
data-row-link
href={href}
target={target}
aria-label={title}
tabIndex={cellRef?.previousElementSibling === null ? 0 : -1}
className="absolute inset-0 focus:outline-none"
/>
)}
{children}
</td>
)
}