Improve Link structure in BUI
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/ui': patch
|
||||
---
|
||||
|
||||
Improved the Link component structure in Backstage UI.
|
||||
@@ -553,6 +553,14 @@ export const componentDefinitions: {
|
||||
readonly dataAttributes: {
|
||||
readonly variant: readonly ['subtitle', 'body', 'caption', 'label'];
|
||||
readonly weight: readonly ['regular', 'bold'];
|
||||
readonly color: readonly [
|
||||
'primary',
|
||||
'secondary',
|
||||
'danger',
|
||||
'warning',
|
||||
'success',
|
||||
];
|
||||
readonly truncate: readonly [true, false];
|
||||
};
|
||||
};
|
||||
readonly List: {
|
||||
|
||||
@@ -33,4 +33,78 @@
|
||||
text-decoration-color: color-mix(in srgb, currentColor 30%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.bui-Link[data-variant='title-large'] {
|
||||
font-size: var(--bui-font-size-8);
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
.bui-Link[data-variant='title-medium'] {
|
||||
font-size: var(--bui-font-size-7);
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
.bui-Link[data-variant='title-small'] {
|
||||
font-size: var(--bui-font-size-6);
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
.bui-Link[data-variant='title-x-small'] {
|
||||
font-size: var(--bui-font-size-5);
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
.bui-Link[data-variant='body-large'] {
|
||||
font-size: var(--bui-font-size-4);
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
.bui-Link[data-variant='body-medium'] {
|
||||
font-size: var(--bui-font-size-3);
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
.bui-Link[data-variant='body-small'] {
|
||||
font-size: var(--bui-font-size-2);
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
.bui-Link[data-variant='body-x-small'] {
|
||||
font-size: var(--bui-font-size-1);
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
.bui-Link[data-weight='regular'] {
|
||||
font-weight: var(--bui-font-weight-regular);
|
||||
}
|
||||
|
||||
.bui-Link[data-weight='bold'] {
|
||||
font-weight: var(--bui-font-weight-bold);
|
||||
}
|
||||
|
||||
.bui-Link[data-color='primary'] {
|
||||
color: var(--bui-fg-primary);
|
||||
}
|
||||
|
||||
.bui-Link[data-color='secondary'] {
|
||||
color: var(--bui-fg-secondary);
|
||||
}
|
||||
|
||||
.bui-Link[data-color='danger'] {
|
||||
color: var(--bui-fg-danger);
|
||||
}
|
||||
|
||||
.bui-Link[data-color='warning'] {
|
||||
color: var(--bui-fg-warning);
|
||||
}
|
||||
|
||||
.bui-Link[data-color='success'] {
|
||||
color: var(--bui-fg-success);
|
||||
}
|
||||
|
||||
.bui-Link[data-truncate] {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,65 +21,41 @@ import { useStyles } from '../../hooks/useStyles';
|
||||
import type { LinkProps } from './types';
|
||||
import { useNavigate, useHref } from 'react-router-dom';
|
||||
import { isExternalLink } from '../../utils/isExternalLink';
|
||||
import stylesLink from './Link.module.css';
|
||||
import stylesText from '../Text/Text.module.css';
|
||||
import styles from './Link.module.css';
|
||||
|
||||
/** @public */
|
||||
export const Link = forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => {
|
||||
const navigate = useNavigate();
|
||||
const { classNames: classNamesLink } = useStyles('Link', props);
|
||||
const {
|
||||
classNames: classNamesText,
|
||||
dataAttributes: textDataAttributes,
|
||||
cleanedProps,
|
||||
} = useStyles('Text', {
|
||||
const { classNames, dataAttributes, cleanedProps } = useStyles('Link', {
|
||||
variant: 'body',
|
||||
weight: 'regular',
|
||||
color: 'primary',
|
||||
...props,
|
||||
});
|
||||
const { className, variant, weight, color, truncate, href, ...restProps } =
|
||||
cleanedProps;
|
||||
|
||||
const { className, href, ...restProps } = cleanedProps;
|
||||
|
||||
const isExternal = isExternalLink(href);
|
||||
|
||||
const component = (
|
||||
<AriaLink
|
||||
ref={ref}
|
||||
className={clsx(classNames.root, styles[classNames.root], className)}
|
||||
href={href}
|
||||
{...dataAttributes}
|
||||
{...restProps}
|
||||
/>
|
||||
);
|
||||
|
||||
// If it's an external link, render AriaLink without RouterProvider
|
||||
if (isExternal) {
|
||||
return (
|
||||
<AriaLink
|
||||
ref={ref}
|
||||
className={clsx(
|
||||
classNamesText.root,
|
||||
classNamesLink.root,
|
||||
stylesText[classNamesText.root],
|
||||
stylesLink[classNamesLink.root],
|
||||
className,
|
||||
)}
|
||||
data-truncate={truncate}
|
||||
href={href}
|
||||
{...textDataAttributes}
|
||||
{...restProps}
|
||||
/>
|
||||
);
|
||||
return component;
|
||||
}
|
||||
|
||||
// For internal links, use RouterProvider
|
||||
return (
|
||||
<RouterProvider navigate={navigate} useHref={useHref}>
|
||||
<AriaLink
|
||||
ref={ref}
|
||||
className={clsx(
|
||||
classNamesText.root,
|
||||
classNamesLink.root,
|
||||
stylesText[classNamesText.root],
|
||||
stylesLink[classNamesLink.root],
|
||||
className,
|
||||
)}
|
||||
data-truncate={truncate}
|
||||
{...textDataAttributes}
|
||||
href={href}
|
||||
{...restProps}
|
||||
/>
|
||||
{component}
|
||||
</RouterProvider>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -228,6 +228,8 @@ export const componentDefinitions = {
|
||||
dataAttributes: {
|
||||
variant: ['subtitle', 'body', 'caption', 'label'] as const,
|
||||
weight: ['regular', 'bold'] as const,
|
||||
color: ['primary', 'secondary', 'danger', 'warning', 'success'] as const,
|
||||
truncate: [true, false] as const,
|
||||
},
|
||||
},
|
||||
List: {
|
||||
|
||||
Reference in New Issue
Block a user