fix(ui): only show pointer cursor on interactive Table rows

Row always passed onAction to React Aria even when no handler or
href was set, causing all rows to appear interactive. Now onAction
is only passed when there is an actual interaction. CSS explicitly
sets cursor: default on rows and scopes cursor: pointer to rows
with href, selection mode, or pressable state.

Signed-off-by: Johan Persson <johanopersson@gmail.com>
This commit is contained in:
Johan Persson
2026-03-10 10:01:45 +01:00
parent 645749d827
commit fbd5c5a93d
3 changed files with 22 additions and 11 deletions
@@ -0,0 +1,7 @@
---
'@backstage/ui': patch
---
Fixed Table rows showing a pointer cursor when not interactive. Rows now only show `cursor: pointer` when they have an `href`, are selectable, or are pressable.
**Affected components:** Table
@@ -83,6 +83,7 @@
.bui-TableRow {
border-bottom: 1px solid var(--bui-border-2);
transition: color 0.2s ease-in-out;
cursor: default;
&:hover {
background-color: var(--bui-bg-tint-hover);
@@ -100,6 +101,8 @@
background-color: var(--bui-bg-tint-disabled);
}
&[data-href],
&[data-selection-mode],
&[data-react-aria-pressable='true'] {
cursor: pointer;
}
@@ -37,14 +37,18 @@ export function Row<T extends object>(props: RowProps<T>) {
);
const { classes, columns, children, href } = ownProps;
const hasInternalHref = !!href && !isExternalLink(href);
const hasInteraction = !!restProps.onAction || !!href;
const handlePress = () => {
if (href) {
analytics.captureEvent('click', href, {
attributes: { to: String(href) },
});
}
};
const handlePress = hasInteraction
? () => {
restProps.onAction?.();
if (href) {
analytics.captureEvent('click', href, {
attributes: { to: String(href) },
});
}
}
: undefined;
let { selectionBehavior, selectionMode } = useTableOptions();
@@ -70,10 +74,7 @@ export function Row<T extends object>(props: RowProps<T>) {
className={classes.root}
data-react-aria-pressable={hasInternalHref ? 'true' : undefined}
{...restProps}
onAction={() => {
restProps.onAction?.();
handlePress();
}}
onAction={handlePress}
>
{content}
</ReactAriaRow>