fix(ui): open external Table row hrefs in a new tab
Automatically apply `target="_blank"` and `rel="noopener noreferrer"` on `Row` when `href` is an external link, so external links in default BUI Table rows open in a new tab instead of navigating the current page. `rel` tokens are merged rather than replaced, so consumer-provided tokens (e.g. `rel="nofollow"`) are preserved while `noopener noreferrer` is always enforced whenever `target="_blank"` is in effect. Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/ui': patch
|
||||
---
|
||||
|
||||
Fixed `Table` rows with external `href` values to open in a new tab by automatically applying `target="_blank"` and `rel="noopener noreferrer"`.
|
||||
|
||||
**Affected components**: Table
|
||||
@@ -36,9 +36,26 @@ export function Row<T extends object>(props: RowProps<T>) {
|
||||
props,
|
||||
);
|
||||
const { classes, columns, children, href } = ownProps;
|
||||
const hasInternalHref = !!href && !isExternalLink(href);
|
||||
const isExternal = isExternalLink(href);
|
||||
const hasInternalHref = !!href && !isExternal;
|
||||
const hasExternalHref = !!href && isExternal;
|
||||
const hasInteraction = !!restProps.onAction || !!href;
|
||||
|
||||
// Derive the effective target, defaulting to _blank for external links.
|
||||
const effectiveTarget = hasExternalHref ? '_blank' : restProps.target;
|
||||
// Always include noopener noreferrer when target=_blank, merging any
|
||||
// consumer-provided rel tokens to avoid reverse-tabnabbing risk.
|
||||
const effectiveRel =
|
||||
effectiveTarget === '_blank'
|
||||
? [
|
||||
...new Set([
|
||||
'noopener',
|
||||
'noreferrer',
|
||||
...(restProps.rel?.split(/\s+/).filter(Boolean) ?? []),
|
||||
]),
|
||||
].join(' ')
|
||||
: restProps.rel;
|
||||
|
||||
const handlePress = hasInteraction
|
||||
? () => {
|
||||
restProps.onAction?.();
|
||||
@@ -71,9 +88,11 @@ export function Row<T extends object>(props: RowProps<T>) {
|
||||
<InternalLinkProvider href={href}>
|
||||
<ReactAriaRow
|
||||
href={href}
|
||||
{...restProps}
|
||||
target={effectiveTarget}
|
||||
rel={effectiveRel}
|
||||
className={classes.root}
|
||||
data-react-aria-pressable={hasInternalHref ? 'true' : undefined}
|
||||
{...restProps}
|
||||
onAction={handlePress}
|
||||
>
|
||||
{content}
|
||||
|
||||
Reference in New Issue
Block a user