Table
tableuiPlain HTML table primitives — `<Table>`, `<TableHeader>`, `<TableRow>`, `<TableCell>` — with the registry’s borders, padding, and tokens already applied. Use this when Data Table is too heavy.
Installation
$pnpm dlx shadcn-vue@latest add https://uipkge.dev/r/vue/table.json$npx shadcn-vue@latest add https://uipkge.dev/r/vue/table.json$yarn dlx shadcn-vue@latest add https://uipkge.dev/r/vue/table.json$bunx shadcn-vue@latest add https://uipkge.dev/r/vue/table.jsonNamed registry:
npx shadcn-vue@latest add @uipkge/tableInstalls to:app/components/ui/table/Examples
Loading interactive previews…
Loading interactive previews…
Props
| Name | Type / Values | Default | Required |
|---|---|---|---|
class | HTMLAttributes['class'] | — | optional |
containerClasswrapper around <Table> breaks stickiness, so size the scroller here. | HTMLAttributes['class'] | — | optional |
density | 'compact''cozy''comfortable' | — | optional |
npm dependencies
Used by
ab-test-variant-resultsaccess-request-workflowad-spend-roi-dashboardagent-memory-inspectorai-crm-pipeline-dashboardai-saas-command-centerairbnb-host-earningsapi-documentation-pagebackorder-split-shipment-managerbill-of-lading-viewerbilling-usage-centercap-table-ownership-summarycase-studycase-study-metric-comparisoncash-flow-treasury-dashboardcdc-replication-streamcold-chain-temp-monitorcolumn-profiling-summarycommercial-invoice-generatorcommute-reimbursement-claimscomparison-migration-pathcompensation-band-benchmarkingcompliance-sanctions-screenercompliance-soc2-readinesscontent-calendar-matrixcontractor-timesheet-approvalcron-job-schedulercrypto-wallet-portfoliocustoms-clearance-trackerdata-catalog-lineagedata-contract-governancedata-explorerdata-mesh-domain-catalogdata-quality-metricsdata-retention-policy-managerdata-tabledata-table-pagedatabase-migration-schema-diffdatabase-schema-viewerdbt-model-graphdecision-matrix-tabledelivery-proof-carddeployment-pipelinedns-record-manageremployee-pulse-survey-resultsenvironment-variables-managerfeature-flags-managerfeature-store-registryfield-inspection-managerfine-tuning-job-monitorfloor-plan-explorerfreelance-work-for-hire-contractgift-card-balance-checkerguardrails-safety-scannerimmunization-historyinfluencer-campaign-cardinsurance-eligibility-checkerintegrations-connector-statusinventory-reorder-forecastinvoice-creator-wizardinvoices-listkafka-stream-monitorlab-results-viewerlakehouse-table-optimizerlast-mile-courier-dispatchleaflet-last-mile-courier-dispatchllm-eval-benchmark-matrixloan-calculatorloyalty-rewards-tier-hubmcp-server-registry-managermodel-token-cost-optimizermultimodal-vision-playgroundorder-management-pagepacking-slip-generatorparquet-metadata-inspectorpatient-medical-recordpayouts-management-tablepayroll-run-summaryperformance-review-matrixpersonal-finance-budgetprescription-refill-managerprice-drop-alert-cardpricingpricing-01pricing-matrix-groupedpricing-matrix-sticky-headerprivacy-data-export-portalproduct-comparison-drawerprompt-ab-testing-comparatorpurchase-order-receivingrate-limiting-configrecruitment-candidate-pipelinereferral-program-widgetreverse-etl-sync-managerrole-matrixsafe-note-calculatorschema-drift-alert-boardsecrets-rotation-schedulerskill-assessment-radarspark-job-stage-visualizersql-query-notebookstock-transfer-managerstore-pickup-curbsidestream-processing-flink-topologystudent-gradebook-tablesubpoena-legal-hold-managersubscription-churn-analyticssynthetic-data-generatortax-summary-reporttechnical-specs-sheettenant-rent-ledgertime-tracker-timesheettrademark-patent-portfoliotraining-compliance-trackertransaction-feedtree-tabletriage-queue-dashboardusage-metering-dashboardutm-campaign-buildervendor-supplier-portalvitals-tracker-chartvulnerability-scanner-reportwarehouse-inventory-gridwave-picking-consolewebhook-testerwholesale-b2b-quick-order
Files installed (11)
app/components/ui/table/Table.vue1.4 kB
<script setup lang="ts"> import type { HTMLAttributes } from 'vue' import { computed } from 'vue' import { cn } from '@/lib/utils' // Match DataTable's density enum so consumers can opt into the same // runtime feel without wiring DataTable. `cozy` is the canonical default // for bare tables (cells: py-2, head: h-10); the other two are escape // hatches for high-density admin lists and roomy patient-facing views. const props = defineProps<{ class?: HTMLAttributes['class'] // Extra classes for the scroll container div (e.g. `min-h-0 flex-1` inside a // flex column). A sticky TableHeader pins to THIS div -- an outer overflow // wrapper around <Table> breaks stickiness, so size the scroller here. containerClass?: HTMLAttributes['class'] density?: 'compact' | 'cozy' | 'comfortable' }>() const densityClass = computed(() => { if (props.density === 'compact') return '[&_td]:py-1.5 [&_td]:text-xs [&_th]:h-8 [&_th]:text-xs' if (props.density === 'comfortable') return '[&_td]:py-3 [&_th]:h-12' // cozy is the new TableCell/TableHead baseline (py-2 / h-10) -- no override. return '' }) </script> <template> <div data-uipkge data-slot="table-container" :class="cn('relative w-full overflow-auto', props.containerClass)"> <table data-uipkge data-slot="table" :class="cn('w-full caption-bottom text-sm', densityClass, props.class)"> <slot /> </table> </div> </template>app/components/ui/table/TableBody.vue0.3 kB
<script setup lang="ts"> import type { HTMLAttributes } from 'vue' import { cn } from '@/lib/utils' const props = defineProps<{ class?: HTMLAttributes['class'] }>() </script> <template> <tbody data-uipkge data-slot="table-body" :class="cn('[&_tr:last-child]:border-0', props.class)"> <slot /> </tbody> </template>app/components/ui/table/TableCaption.vue0.3 kB
<script setup lang="ts"> import type { HTMLAttributes } from 'vue' import { cn } from '@/lib/utils' const props = defineProps<{ class?: HTMLAttributes['class'] }>() </script> <template> <caption data-uipkge data-slot="table-caption" :class="cn('text-muted-foreground mt-4 text-sm', props.class)"> <slot /> </caption> </template>app/components/ui/table/TableCell.vue0.4 kB
<script setup lang="ts"> import type { HTMLAttributes } from 'vue' import { cn } from '@/lib/utils' const props = defineProps<{ class?: HTMLAttributes['class'] }>() </script> <template> <td data-uipkge data-slot="table-cell" :class=" cn( 'px-3 py-2 align-middle text-sm whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-0.5', props.class, ) " > <slot /> </td> </template>app/components/ui/table/TableEmpty.vue0.7 kB
<script setup lang="ts"> import type { HTMLAttributes } from 'vue' import { reactiveOmit } from '@vueuse/core' import { cn } from '@/lib/utils' import TableCell from './TableCell.vue' import TableRow from './TableRow.vue' const props = withDefaults( defineProps<{ class?: HTMLAttributes['class'] colspan?: number }>(), { colspan: 1, }, ) const delegatedProps = reactiveOmit(props, 'class') </script> <template> <TableRow> <TableCell :class="cn('text-foreground p-4 align-middle text-sm whitespace-nowrap', props.class)" v-bind="delegatedProps" > <div class="flex items-center justify-center py-10"> <slot /> </div> </TableCell> </TableRow> </template>app/components/ui/table/TableFooter.vue0.4 kB
<script setup lang="ts"> import type { HTMLAttributes } from 'vue' import { cn } from '@/lib/utils' const props = defineProps<{ class?: HTMLAttributes['class'] }>() </script> <template> <tfoot data-uipkge data-slot="table-footer" :class="cn('bg-muted/50 border-t font-medium [&>tr]:last:border-b-0', props.class)" > <slot /> </tfoot> </template>app/components/ui/table/TableHead.vue0.5 kB
<script setup lang="ts"> import type { HTMLAttributes } from 'vue' import { cn } from '@/lib/utils' const props = defineProps<{ class?: HTMLAttributes['class'] }>() </script> <template> <th data-uipkge data-slot="table-head" :class=" cn( 'text-foreground h-10 px-3 text-left align-middle text-sm font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-0.5', props.class, ) " > <slot /> </th> </template>app/components/ui/table/TableHeader.vue0.3 kB
<script setup lang="ts"> import type { HTMLAttributes } from 'vue' import { cn } from '@/lib/utils' const props = defineProps<{ class?: HTMLAttributes['class'] }>() </script> <template> <thead data-uipkge data-slot="table-header" :class="cn('bg-muted/50 [&_tr]:border-b', props.class)"> <slot /> </thead> </template>app/components/ui/table/TableRow.vue0.4 kB
<script setup lang="ts"> import type { HTMLAttributes } from 'vue' import { cn } from '@/lib/utils' const props = defineProps<{ class?: HTMLAttributes['class'] }>() </script> <template> <tr data-uipkge data-slot="table-row" :class="cn('hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors duration-150', props.class)" > <slot /> </tr> </template>app/components/ui/table/index.ts0.5 kB
export { default as Table } from './Table.vue' export { default as TableBody } from './TableBody.vue' export { default as TableCaption } from './TableCaption.vue' export { default as TableCell } from './TableCell.vue' export { default as TableEmpty } from './TableEmpty.vue' export { default as TableFooter } from './TableFooter.vue' export { default as TableHead } from './TableHead.vue' export { default as TableHeader } from './TableHeader.vue' export { default as TableRow } from './TableRow.vue'app/components/ui/table/utils.ts0.3 kB
import type { Updater } from '@tanstack/vue-table' import type { Ref } from 'vue' import { isFunction } from '@tanstack/vue-table' export function valueUpdater<T>(updaterOrValue: Updater<T>, ref: Ref<T>) { ref.value = isFunction(updaterOrValue) ? updaterOrValue(ref.value) : updaterOrValue }
Raw manifest:https://uipkge.dev/r/vue/table.json