diff --git a/packages/demo/src/components/demo/table.tsx b/packages/demo/src/components/demo/table.tsx
index c1651dc..a0d0bdd 100644
--- a/packages/demo/src/components/demo/table.tsx
+++ b/packages/demo/src/components/demo/table.tsx
@@ -483,11 +483,7 @@ export const TableDemo = ({
- toggleRow(2) : undefined}
- >
+
Charlie Brown
charlie@example.com
Viewer
diff --git a/packages/demo/src/content/components/table.mdx b/packages/demo/src/content/components/table.mdx
index e8e50d5..0b0c67a 100644
--- a/packages/demo/src/content/components/table.mdx
+++ b/packages/demo/src/content/components/table.mdx
@@ -69,7 +69,12 @@ Basic usage:
### Clickable Rows
-Rows accept an `onClick` handler, which enables hover interactions. Use `data-state="selected"` to mark a row as selected.
+Rows can be made interactive in two ways:
+
+- **`onClick`** — Pass a click handler for custom behavior (e.g., toggling selection state).
+- **`href`** — Pass a URL to make the row navigable on click. This also adds keyboard accessibility (`Enter`/`Space` to activate) and proper ARIA semantics. Add an `hrefLabel` prop to tell screen reader users where the link will go.
+
+Both props enable hover interactions automatically. Use `data-state="selected"` to mark a row as selected.
Try clicking a row below to toggle its selected state!
@@ -310,6 +315,8 @@ Use [container queries](https://tailwindcss.com/docs/responsive-design#what-are-
### TableRow
-| Name | Description | Type | Default | Required |
-| ----------- | ------------------------------------------- | --------- | ------- | -------- |
-| `clickable` | Applies hover and cursor interaction styles | `boolean` | `false` | ❌ |
+| Name | Description | Type | Default | Required |
+| ----------- | ----------------------------------------------------------- | --------- | ---------------- | -------- |
+| `clickable` | Applies hover and cursor interaction styles | `boolean` | `false` | ❌ |
+| `href` | URL to navigate to on click | `string` | — | ❌ |
+| `hrefLabel` | Accessible label for the link (announced by screen readers) | `string` | `"View details"` | ❌ |
diff --git a/packages/ui/package.json b/packages/ui/package.json
index 436a533..1cd9a49 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -2,7 +2,7 @@
"name": "@eqtylab/equality",
"description": "EQTYLab's component and token-based design system",
"homepage": "https://equality.eqtylab.io/",
- "version": "1.9.0",
+ "version": "1.9.1",
"license": "Apache-2.0",
"keywords": [
"component library",
diff --git a/packages/ui/src/components/table/table-components.module.css b/packages/ui/src/components/table/table-components.module.css
index f3b9ee6..7762c83 100644
--- a/packages/ui/src/components/table/table-components.module.css
+++ b/packages/ui/src/components/table/table-components.module.css
@@ -64,7 +64,31 @@
--hover-darken: 50%;
--hover-lighten: 50%;
@apply cursor-pointer;
- @apply hover:bg-mixed-light! dark:hover:bg-mixed-dark!;
+}
+
+/* Prevent row from highlighting when the user hovers clickable tags in the table */
+.table-row--clickable:not([data-state='selected']):hover:not(
+ :has(button:hover, a:not(.table-row-link):hover)
+ ) {
+ @apply bg-mixed-light! dark:bg-mixed-dark!;
+}
+
+/* Linked Row (stretched link pattern) */
+
+.table-row--linked {
+ @apply relative;
+}
+
+.table-row-link {
+ @apply absolute inset-0 z-10;
+}
+
+.table-row--linked :is(button, a:not(.table-row-link)) {
+ @apply relative z-20;
+}
+
+.table-row--linked:has(.table-row-link:focus-visible) {
+ @apply outline-brand-primary outline outline-2 outline-offset-[-2px];
}
.table-body .table-row--clickable[data-state='selected'] {
diff --git a/packages/ui/src/components/table/table-components.tsx b/packages/ui/src/components/table/table-components.tsx
index 41837b3..5fc4789 100644
--- a/packages/ui/src/components/table/table-components.tsx
+++ b/packages/ui/src/components/table/table-components.tsx
@@ -59,14 +59,49 @@ TableFooter.displayName = 'TableFooter';
const TableRow = React.forwardRef<
HTMLTableRowElement,
- React.HTMLAttributes & { clickable?: boolean }
->(({ className, clickable, ...props }, ref) => (
-
-));
+ React.HTMLAttributes & {
+ clickable?: boolean;
+ href?: string;
+ hrefLabel?: string;
+ }
+>(
+ (
+ { className, clickable, href, hrefLabel = 'View details', children, onClick, ...props },
+ ref
+ ) => {
+ const isClickable = clickable || !!href;
+
+ const handleClick = (e: React.MouseEvent) => {
+ // Don't trigger row click if an interactive element was clicked
+ const target = e.target as HTMLElement;
+ if (target.closest('button, a:not([data-table-row-link])')) {
+ return;
+ }
+ onClick?.(e);
+ };
+
+ return (
+
+ {href && (
+
+ {hrefLabel}
+
+ )}
+ {children}
+
+ );
+ }
+);
TableRow.displayName = 'TableRow';
const TableHead = React.forwardRef<