a little nicer looking, but i still don't really understand where to set

colors...

I stole a bunch of things from
[this](https://github.com/danielagg/shadcn-data-table-resize-columns)
repository I found online, and that seems to have helped.

I'm still having trouble with colors and tailwind and shadcn...
The buttons also only misalign on firefox, not chrome...
This commit is contained in:
Anish Lakhwara 2024-11-06 22:21:58 -08:00
parent d04497f24d
commit 26ef0c76ac
8 changed files with 267 additions and 154 deletions

View file

@ -6,7 +6,7 @@
"tailwind": { "tailwind": {
"config": "tailwind.config.js", "config": "tailwind.config.js",
"css": "src/index.css", "css": "src/index.css",
"baseColor": "zinc", "baseColor": "slate",
"cssVariables": true, "cssVariables": true,
"prefix": "" "prefix": ""
}, },

View file

@ -1,6 +1,5 @@
import { useState } from 'react' import { useState } from 'react'
import { useCachedState, useQuery } from "@vlcn.io/react"; import { useCachedState, useQuery } from "@vlcn.io/react";
import './App.css'
import { import {
ColumnDef, ColumnDef,
flexRender, flexRender,
@ -9,13 +8,13 @@ import {
} from "@tanstack/react-table" } from "@tanstack/react-table"
import { DataTable } from "@/components/ui/data-table" import { DataTable } from "@/components/ui/data-table"
import * as addParser from '../../parser/add_parser.js'; import * as addParser from '../../parser/add_parser.js';
import { Checkbox } from "@/components/ui/checkbox"
import { Input } from "@/components/ui/input"
function Marshall(parsed) { function Marshall(parsed) {
let project = ""; let project = "";
const tags = []; const tags = [];
console.log(parsed);
for (const attr of parsed.attributes) { for (const attr of parsed.attributes) {
console.log(attr);
switch (attr.type) { switch (attr.type) {
case 'project': case 'project':
project = attr.value; project = attr.value;
@ -37,6 +36,31 @@ type Todo = {
} }
export const columns: ColumnDef<Todo>[] = [ export const columns: ColumnDef<Todo>[] = [
{
id: "select",
header: ({ table }) => (
<Checkbox
checked={
table.getIsAllPageRowsSelected() ||
(table.getIsSomePageRowsSelected() && "indeterminate")
}
onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
aria-label="Select all"
className="translate-y-[2px]"
/>
),
cell: ({ row }) => (
<Checkbox
checked={row.getIsSelected()}
onCheckedChange={(value) => row.toggleSelected(!!value)}
aria-label="Select row"
className="translate-y-[2px]"
/>
),
enableSorting: false,
enableHiding: false,
size: 20,
},
{ {
accessorKey: "description", accessorKey: "description",
header: "Description", header: "Description",
@ -47,11 +71,10 @@ export const columns: ColumnDef<Todo>[] = [
}, },
{ {
accessorKey: "tags", accessorKey: "tags",
header: "tags", header: "Tags",
cell: ({ row }) => { cell: ({ row }) => {
console.log("Tags Parsing: " + row.getValue("tags"))
const formatted = JSON.parse(row.getValue("tags")) const formatted = JSON.parse(row.getValue("tags"))
return <div className="text-right font-medium">{formatted.join(", ")}</div> return <div className="font-medium">{formatted.join(", ")}</div>
} }
}, },
] ]
@ -76,11 +99,13 @@ function App({ ctx }) {
return ( return (
<> <>
<input type="text" <section className="pt-16 container">
<Input type="text"
onKeyUp={addTodo} onKeyUp={addTodo}
onChange={(e) => setNewText(e.target.value)} onChange={(e) => setNewText(e.target.value)}
/> />
<DataTable columns={columns} data={todos} /> <DataTable columns={columns} data={todos} />
</section>
</> </>
) )
} }

View file

@ -0,0 +1,27 @@
import * as React from "react"
import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
import { cn } from "@/lib/utils"
import { CheckIcon } from "@radix-ui/react-icons"
const Checkbox = React.forwardRef<
React.ElementRef<typeof CheckboxPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
>(({ className, ...props }, ref) => (
<CheckboxPrimitive.Root
ref={ref}
className={cn(
"peer h-4 w-4 shrink-0 rounded-sm border border-primary shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
className
)}
{...props}
>
<CheckboxPrimitive.Indicator
className={cn("flex items-center justify-center text-current")}
>
<CheckIcon className="h-4 w-4" />
</CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root>
))
Checkbox.displayName = CheckboxPrimitive.Root.displayName
export { Checkbox }

View file

@ -1,7 +1,10 @@
"use client" "use client"
import { useState } from "react"
import { import {
ColumnDef, ColumnDef,
ColumnSizingState,
flexRender, flexRender,
getCoreRowModel, getCoreRowModel,
useReactTable, useReactTable,
@ -25,21 +28,33 @@ export function DataTable<TData, TValue>({
columns, columns,
data, data,
}: DataTableProps<TData, TValue>) { }: DataTableProps<TData, TValue>) {
const [colSizing, setColSizing] = useState<ColumnSizingState>({});
const table = useReactTable({ const table = useReactTable({
data, data,
columns, columns,
enableColumnResizing: true,
columnResizeMode: "onChange",
getCoreRowModel: getCoreRowModel(), getCoreRowModel: getCoreRowModel(),
onColumnSizingChange: setColSizing,
state: {
columnSizing: colSizing,
},
}) })
return ( return (
<div className="bg-zinc-950 dark:bg-white"> <div >
<Table > <Table >
<TableHeader> <TableHeader>
{table.getHeaderGroups().map((headerGroup) => ( {table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}> <TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => { {headerGroup.headers.map((header) => {
return ( return (
<TableHead key={header.id}> <TableHead key={header.id}
className="relative"
style={{
width: header.getSize(),
}}
>
{header.isPlaceholder {header.isPlaceholder
? null ? null
: flexRender( : flexRender(

View file

@ -0,0 +1,25 @@
import * as React from "react"
import { cn } from "@/lib/utils"
export interface InputProps
extends React.InputHTMLAttributes<HTMLInputElement> {}
const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ className, type, ...props }, ref) => {
return (
<input
type={type}
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 }

View file

@ -1,6 +1,6 @@
import * as React from "react" import * as React from "react";
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils";
const Table = React.forwardRef< const Table = React.forwardRef<
HTMLTableElement, HTMLTableElement,
@ -13,16 +13,16 @@ const Table = React.forwardRef<
{...props} {...props}
/> />
</div> </div>
)) ));
Table.displayName = "Table" Table.displayName = "Table";
const TableHeader = React.forwardRef< const TableHeader = React.forwardRef<
HTMLTableSectionElement, HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement> React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} /> <thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
)) ));
TableHeader.displayName = "TableHeader" TableHeader.displayName = "TableHeader";
const TableBody = React.forwardRef< const TableBody = React.forwardRef<
HTMLTableSectionElement, HTMLTableSectionElement,
@ -33,8 +33,8 @@ const TableBody = React.forwardRef<
className={cn("[&_tr:last-child]:border-0", className)} className={cn("[&_tr:last-child]:border-0", className)}
{...props} {...props}
/> />
)) ));
TableBody.displayName = "TableBody" TableBody.displayName = "TableBody";
const TableFooter = React.forwardRef< const TableFooter = React.forwardRef<
HTMLTableSectionElement, HTMLTableSectionElement,
@ -48,8 +48,8 @@ const TableFooter = React.forwardRef<
)} )}
{...props} {...props}
/> />
)) ));
TableFooter.displayName = "TableFooter" TableFooter.displayName = "TableFooter";
const TableRow = React.forwardRef< const TableRow = React.forwardRef<
HTMLTableRowElement, HTMLTableRowElement,
@ -63,8 +63,8 @@ const TableRow = React.forwardRef<
)} )}
{...props} {...props}
/> />
)) ));
TableRow.displayName = "TableRow" TableRow.displayName = "TableRow";
const TableHead = React.forwardRef< const TableHead = React.forwardRef<
HTMLTableCellElement, HTMLTableCellElement,
@ -73,13 +73,13 @@ const TableHead = React.forwardRef<
<th <th
ref={ref} ref={ref}
className={cn( className={cn(
"h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]", "h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
className className
)} )}
{...props} {...props}
/> />
)) ));
TableHead.displayName = "TableHead" TableHead.displayName = "TableHead";
const TableCell = React.forwardRef< const TableCell = React.forwardRef<
HTMLTableCellElement, HTMLTableCellElement,
@ -87,14 +87,11 @@ const TableCell = React.forwardRef<
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<td <td
ref={ref} ref={ref}
className={cn( className={cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className)}
"p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
className
)}
{...props} {...props}
/> />
)) ));
TableCell.displayName = "TableCell" TableCell.displayName = "TableCell";
const TableCaption = React.forwardRef< const TableCaption = React.forwardRef<
HTMLTableCaptionElement, HTMLTableCaptionElement,
@ -105,8 +102,8 @@ const TableCaption = React.forwardRef<
className={cn("mt-4 text-sm text-muted-foreground", className)} className={cn("mt-4 text-sm text-muted-foreground", className)}
{...props} {...props}
/> />
)) ));
TableCaption.displayName = "TableCaption" TableCaption.displayName = "TableCaption";
export { export {
Table, Table,
@ -117,4 +114,5 @@ export {
TableRow, TableRow,
TableCell, TableCell,
TableCaption, TableCaption,
} };

View file

@ -2,71 +2,76 @@
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
:root { @layer base {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
@media (prefers-color-scheme: light) {
:root { :root {
color: #213547; --background: 0 0% 100%;
background-color: #ffffff; --foreground: 222.2 84% 4.9%;
--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;
--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 222.2 84% 4.9%;
--radius: 0.5rem;
} }
a:hover {
color: #747bff; .dark {
} --background: 222.2 84% 4.9%;
button { --foreground: 210 40% 98%;
background-color: #f9f9f9;
--card: 222.2 84% 4.9%;
--card-foreground: 210 40% 98%;
--popover: 222.2 84% 4.9%;
--popover-foreground: 210 40% 98%;
--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 11.2%;
--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;
--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;
--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;
--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
--ring: 212.7 26.8% 83.9%;
} }
} }
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}

View file

@ -1,60 +1,78 @@
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */
export default { module.exports = {
darkMode: ["class"], darkMode: ["class"],
content: [ content: [
"./index.html", './pages/**/*.{ts,tsx}',
"./src/**/.{js,ts,jsx,tsx}", './components/**/*.{ts,tsx}',
'./app/**/*.{ts,tsx}',
'./src/**/*.{ts,tsx}',
], ],
prefix: "",
theme: { theme: {
container: {
center: true,
padding: "2rem",
screens: {
"2xl": "1400px",
},
},
extend: { extend: {
borderRadius: {
lg: 'var(--radius)',
md: 'calc(var(--radius) - 2px)',
sm: 'calc(var(--radius) - 4px)'
},
colors: { colors: {
background: 'hsl(var(--background))', border: "hsl(var(--border))",
foreground: 'hsl(var(--foreground))', input: "hsl(var(--input))",
card: { ring: "hsl(var(--ring))",
DEFAULT: 'hsl(var(--card))', background: "hsl(var(--background))",
foreground: 'hsl(var(--card-foreground))' foreground: "hsl(var(--foreground))",
},
popover: {
DEFAULT: 'hsl(var(--popover))',
foreground: 'hsl(var(--popover-foreground))'
},
primary: { primary: {
DEFAULT: 'hsl(var(--primary))', DEFAULT: "hsl(var(--primary))",
foreground: 'hsl(var(--primary-foreground))' foreground: "hsl(var(--primary-foreground))",
}, },
secondary: { secondary: {
DEFAULT: 'hsl(var(--secondary))', DEFAULT: "hsl(var(--secondary))",
foreground: 'hsl(var(--secondary-foreground))' foreground: "hsl(var(--secondary-foreground))",
},
muted: {
DEFAULT: 'hsl(var(--muted))',
foreground: 'hsl(var(--muted-foreground))'
},
accent: {
DEFAULT: 'hsl(var(--accent))',
foreground: 'hsl(var(--accent-foreground))'
}, },
destructive: { destructive: {
DEFAULT: 'hsl(var(--destructive))', DEFAULT: "hsl(var(--destructive))",
foreground: 'hsl(var(--destructive-foreground))' foreground: "hsl(var(--destructive-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
popover: {
DEFAULT: "hsl(var(--popover))",
foreground: "hsl(var(--popover-foreground))",
},
card: {
DEFAULT: "hsl(var(--card))",
foreground: "hsl(var(--card-foreground))",
},
},
borderRadius: {
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)",
},
keyframes: {
"accordion-down": {
from: { height: "0" },
to: { height: "var(--radix-accordion-content-height)" },
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: "0" },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
},
}, },
border: 'hsl(var(--border))',
input: 'hsl(var(--input))',
ring: 'hsl(var(--ring))',
chart: {
'1': 'hsl(var(--chart-1))',
'2': 'hsl(var(--chart-2))',
'3': 'hsl(var(--chart-3))',
'4': 'hsl(var(--chart-4))',
'5': 'hsl(var(--chart-5))'
}
}
}
}, },
plugins: [require("tailwindcss-animate")], plugins: [require("tailwindcss-animate")],
} }