{"name":"table","type":"registry:component","title":"Table","description":"A responsive table component for displaying tabular data. Uses a simple wrapper component with CSS-based styling for native HTML table elements.","categories":["ui","table","web-component"],"author":"Lloyd Richards <lloyd.d.richards@gmail.com>","dependencies":[],"files":[{"path":"registry/ui/table/table.ts","type":"registry:ui","content":"import { adoptStyles, html, LitElement, unsafeCSS } from \"lit\";\nimport { customElement } from \"lit/decorators.js\";\nimport { tailwind } from \"@/registry/lib/tailwindMixin\";\nimport tableSlottedCss from \"./table.css?inline\";\n\nconst tableStyles = unsafeCSS(tableSlottedCss);\n\n@customElement(\"ui-table\")\nexport class Table extends LitElement {\n  override connectedCallback() {\n    super.connectedCallback();\n    if (this.shadowRoot) {\n      adoptStyles(this.shadowRoot, [tailwind, tableStyles]);\n    }\n  }\n\n  override render() {\n    return html`<slot></slot>`;\n  }\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    \"ui-table\": Table;\n  }\n}\n"},{"path":"registry/ui/table/table.stories.ts","type":"registry:ui","content":"import \"./table\";\nimport \"../badge/badge\";\nimport \"../button/button\";\nimport type { Meta, StoryObj } from \"@storybook/web-components-vite\";\nimport { html } from \"lit\";\n\nconst invoices = [\n  {\n    invoice: \"INV001\",\n    paymentStatus: \"Paid\",\n    totalAmount: \"$250.00\",\n    paymentMethod: \"Credit Card\",\n  },\n  {\n    invoice: \"INV002\",\n    paymentStatus: \"Pending\",\n    totalAmount: \"$150.00\",\n    paymentMethod: \"PayPal\",\n  },\n  {\n    invoice: \"INV003\",\n    paymentStatus: \"Unpaid\",\n    totalAmount: \"$350.00\",\n    paymentMethod: \"Bank Transfer\",\n  },\n  {\n    invoice: \"INV004\",\n    paymentStatus: \"Paid\",\n    totalAmount: \"$450.00\",\n    paymentMethod: \"Credit Card\",\n  },\n  {\n    invoice: \"INV005\",\n    paymentStatus: \"Paid\",\n    totalAmount: \"$550.00\",\n    paymentMethod: \"PayPal\",\n  },\n  {\n    invoice: \"INV006\",\n    paymentStatus: \"Pending\",\n    totalAmount: \"$200.00\",\n    paymentMethod: \"Bank Transfer\",\n  },\n  {\n    invoice: \"INV007\",\n    paymentStatus: \"Unpaid\",\n    totalAmount: \"$300.00\",\n    paymentMethod: \"Credit Card\",\n  },\n];\n\n/**\n * A responsive table component for displaying tabular data.\n */\nconst meta: Meta = {\n  title: \"ui/Table\",\n  component: \"ui-table\",\n  tags: [\"autodocs\"],\n  argTypes: {},\n  parameters: {\n    layout: \"padded\",\n  },\n};\n\nexport default meta;\n\ntype Story = StoryObj;\n\n/**\n * The default form of the table with all basic elements.\n */\nexport const Default: Story = {\n  render: () => html`\n    <ui-table>\n      <table>\n        <caption>\n          A list of your recent invoices.\n        </caption>\n        <thead>\n          <tr>\n            <th class=\"w-[100px]\">Invoice</th>\n            <th>Status</th>\n            <th>Method</th>\n            <th class=\"text-right\">Amount</th>\n          </tr>\n        </thead>\n        <tbody>\n          ${invoices.map(\n            (invoice) => html`\n              <tr>\n                <td class=\"font-medium\">${invoice.invoice}</td>\n                <td>${invoice.paymentStatus}</td>\n                <td>${invoice.paymentMethod}</td>\n                <td class=\"text-right\">${invoice.totalAmount}</td>\n              </tr>\n            `,\n          )}\n        </tbody>\n      </table>\n    </ui-table>\n  `,\n};\n\n/**\n * Table with a footer row for displaying totals or summaries.\n */\nexport const WithFooter: Story = {\n  render: () => html`\n    <ui-table>\n      <table>\n        <caption>\n          A list of your recent invoices.\n        </caption>\n        <thead>\n          <tr>\n            <th class=\"w-[100px]\">Invoice</th>\n            <th>Status</th>\n            <th>Method</th>\n            <th class=\"text-right\">Amount</th>\n          </tr>\n        </thead>\n        <tbody>\n          ${invoices.slice(0, 3).map(\n            (invoice) => html`\n              <tr>\n                <td class=\"font-medium\">${invoice.invoice}</td>\n                <td>${invoice.paymentStatus}</td>\n                <td>${invoice.paymentMethod}</td>\n                <td class=\"text-right\">${invoice.totalAmount}</td>\n              </tr>\n            `,\n          )}\n        </tbody>\n        <tfoot>\n          <tr>\n            <td colspan=\"3\">Total</td>\n            <td class=\"text-right\">$750.00</td>\n          </tr>\n        </tfoot>\n      </table>\n    </ui-table>\n  `,\n};\n\n/**\n * Table with badge components for status indicators.\n */\nexport const WithBadges: Story = {\n  render: () => html`\n    <ui-table>\n      <table>\n        <thead>\n          <tr>\n            <th>Invoice</th>\n            <th>Status</th>\n            <th>Method</th>\n            <th class=\"text-right\">Amount</th>\n          </tr>\n        </thead>\n        <tbody>\n          ${invoices.slice(0, 5).map(\n            (invoice) => html`\n              <tr>\n                <td class=\"font-medium\">${invoice.invoice}</td>\n                <td>\n                  <ui-badge\n                    variant=${\n                      invoice.paymentStatus === \"Paid\"\n                        ? \"default\"\n                        : invoice.paymentStatus === \"Pending\"\n                          ? \"secondary\"\n                          : \"destructive\"\n                    }\n                  >\n                    ${invoice.paymentStatus}\n                  </ui-badge>\n                </td>\n                <td>${invoice.paymentMethod}</td>\n                <td class=\"text-right\">${invoice.totalAmount}</td>\n              </tr>\n            `,\n          )}\n        </tbody>\n      </table>\n    </ui-table>\n  `,\n};\n\n/**\n * Table with action buttons in cells.\n */\nexport const WithActions: Story = {\n  render: () => html`\n    <ui-table>\n      <table>\n        <thead>\n          <tr>\n            <th>Invoice</th>\n            <th>Status</th>\n            <th>Amount</th>\n            <th class=\"text-right\">Actions</th>\n          </tr>\n        </thead>\n        <tbody>\n          ${invoices.slice(0, 4).map(\n            (invoice) => html`\n              <tr>\n                <td class=\"font-medium\">${invoice.invoice}</td>\n                <td>${invoice.paymentStatus}</td>\n                <td>${invoice.totalAmount}</td>\n                <td class=\"text-right\">\n                  <ui-button size=\"sm\" variant=\"ghost\">View</ui-button>\n                  <ui-button size=\"sm\" variant=\"ghost\">Edit</ui-button>\n                </td>\n              </tr>\n            `,\n          )}\n        </tbody>\n      </table>\n    </ui-table>\n  `,\n};\n\n/**\n * Minimal table without caption or footer.\n */\nexport const Minimal: Story = {\n  render: () => html`\n    <ui-table>\n      <table>\n        <thead>\n          <tr>\n            <th>Name</th>\n            <th>Email</th>\n            <th>Role</th>\n          </tr>\n        </thead>\n        <tbody>\n          <tr>\n            <td class=\"font-medium\">John Doe</td>\n            <td>john@example.com</td>\n            <td>Admin</td>\n          </tr>\n          <tr>\n            <td class=\"font-medium\">Jane Smith</td>\n            <td>jane@example.com</td>\n            <td>User</td>\n          </tr>\n          <tr>\n            <td class=\"font-medium\">Bob Johnson</td>\n            <td>bob@example.com</td>\n            <td>User</td>\n          </tr>\n        </tbody>\n      </table>\n    </ui-table>\n  `,\n};\n\n/**\n * Table demonstrating responsive behavior with many columns.\n */\nexport const Responsive: Story = {\n  render: () => html`\n    <ui-table>\n      <table>\n        <caption>\n          Scroll horizontally on small screens.\n        </caption>\n        <thead>\n          <tr>\n            <th>ID</th>\n            <th>Customer</th>\n            <th>Email</th>\n            <th>Status</th>\n            <th>Date</th>\n            <th>Method</th>\n            <th class=\"text-right\">Amount</th>\n          </tr>\n        </thead>\n        <tbody>\n          ${invoices.slice(0, 3).map(\n            (invoice) => html`\n              <tr>\n                <td class=\"font-medium\">${invoice.invoice}</td>\n                <td>John Doe</td>\n                <td>john@example.com</td>\n                <td>${invoice.paymentStatus}</td>\n                <td>2024-01-15</td>\n                <td>${invoice.paymentMethod}</td>\n                <td class=\"text-right\">${invoice.totalAmount}</td>\n              </tr>\n            `,\n          )}\n        </tbody>\n      </table>\n    </ui-table>\n  `,\n};\n\n/**\n * Table with checkbox selection in first column.\n * Demonstrates the checkbox styling pattern from shadcn.\n */\nexport const WithCheckboxes: Story = {\n  render: () => html`\n    <ui-table>\n      <table>\n        <thead>\n          <tr>\n            <th class=\"w-[50px]\">\n              <input type=\"checkbox\" role=\"checkbox\" aria-label=\"Select all\" />\n            </th>\n            <th>Invoice</th>\n            <th>Status</th>\n            <th class=\"text-right\">Amount</th>\n          </tr>\n        </thead>\n        <tbody>\n          ${invoices.slice(0, 4).map(\n            (invoice) => html`\n              <tr>\n                <td>\n                  <input\n                    type=\"checkbox\"\n                    role=\"checkbox\"\n                    aria-label=\"Select row\"\n                  />\n                </td>\n                <td class=\"font-medium\">${invoice.invoice}</td>\n                <td>${invoice.paymentStatus}</td>\n                <td class=\"text-right\">${invoice.totalAmount}</td>\n              </tr>\n            `,\n          )}\n        </tbody>\n      </table>\n    </ui-table>\n  `,\n};\n\n/**\n * Table demonstrating various text alignment options.\n */\nexport const TextAlignment: Story = {\n  render: () => html`\n    <ui-table>\n      <table>\n        <thead>\n          <tr>\n            <th class=\"text-left\">Left Aligned</th>\n            <th class=\"text-center\">Center Aligned</th>\n            <th class=\"text-right\">Right Aligned</th>\n          </tr>\n        </thead>\n        <tbody>\n          <tr>\n            <td class=\"text-left\">Left content</td>\n            <td class=\"text-center\">Center content</td>\n            <td class=\"text-right\">Right content</td>\n          </tr>\n          <tr>\n            <td class=\"text-left\">More left</td>\n            <td class=\"text-center\">More center</td>\n            <td class=\"text-right\">More right</td>\n          </tr>\n        </tbody>\n      </table>\n    </ui-table>\n  `,\n};\n"},{"path":"registry/ui/table/table.css","type":"registry:ui","content":"@reference \"../../styles/tailwind.global.css\";\n\n@layer base {\n  :host {\n    @apply relative w-full overflow-auto block;\n  }\n}\n"}],"css":{"@layer ui-table":{"ui-table table":{"@apply w-full caption-bottom text-sm":{}},"ui-table thead":{"@apply [&_tr]:border-b":{}},"ui-table tbody":{"@apply [&_tr:last-child]:border-0":{}},"ui-table tfoot":{"@apply bg-muted/50 border-t font-medium [&>tr]:last:border-b-0":{}},"ui-table tr":{"@apply hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors":{}},"ui-table th":{"@apply text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]":{}},"ui-table td":{"@apply p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]":{}},"ui-table caption":{"@apply text-muted-foreground mt-4 text-sm":{}}}}}