Merge pull request #30524 from backstage/bui-link
UI - Move Link to React Aria
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/canon': minor
|
||||
---
|
||||
|
||||
**Breaking changes** We are updating our Link component to use React Aria under the hood. To match their API we are updating the `to` prop to `href` to match both internal and external routing. We are also updating our variant naming to include all our new font sizes.
|
||||
File diff suppressed because one or more lines are too long
@@ -9790,14 +9790,12 @@
|
||||
|
||||
.bui-Link {
|
||||
font-family: var(--bui-font-regular);
|
||||
color: var(--bui-fg-link);
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-decoration-line: none;
|
||||
|
||||
&:hover {
|
||||
color: var(--bui-fg-link-hover);
|
||||
text-underline-offset: calc(.025em + 2px);
|
||||
text-decoration-line: underline;
|
||||
text-decoration-style: solid;
|
||||
@@ -9806,22 +9804,42 @@
|
||||
}
|
||||
}
|
||||
|
||||
.bui-Link[data-variant="body"] {
|
||||
font-size: var(--bui-font-size-3);
|
||||
.bui-Link[data-variant="title-large"] {
|
||||
font-size: var(--bui-font-size-8);
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
.bui-Link[data-variant="subtitle"] {
|
||||
.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="caption"] {
|
||||
.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="label"] {
|
||||
.bui-Link[data-variant="body-x-small"] {
|
||||
font-size: var(--bui-font-size-1);
|
||||
line-height: 140%;
|
||||
}
|
||||
@@ -9834,6 +9852,14 @@
|
||||
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-MenuPositioner {
|
||||
z-index: 100;
|
||||
outline: 0;
|
||||
|
||||
@@ -10,7 +10,6 @@ import { Collapsible as Collapsible_2 } from '@base-ui-components/react/collapsi
|
||||
import { ComponentProps } from 'react';
|
||||
import type { ComponentPropsWithRef } from 'react';
|
||||
import { Context } from 'react';
|
||||
import type { CSSProperties } from 'react';
|
||||
import type { ElementType } from 'react';
|
||||
import { FocusEvent as FocusEvent_2 } from 'react';
|
||||
import { ForwardRefExoticComponent } from 'react';
|
||||
@@ -1219,26 +1218,39 @@ export type JustifyContent =
|
||||
|
||||
// @public (undocumented)
|
||||
export const Link: ForwardRefExoticComponent<
|
||||
Omit<LinkProps, 'ref'> & RefAttributes<HTMLElement>
|
||||
LinkProps & RefAttributes<HTMLAnchorElement>
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface LinkProps extends useRender.ComponentProps<'a'> {
|
||||
export interface LinkProps extends LinkProps_2 {
|
||||
// (undocumented)
|
||||
children: ReactNode;
|
||||
// (undocumented)
|
||||
className?: string;
|
||||
// (undocumented)
|
||||
style?: CSSProperties;
|
||||
// (undocumented)
|
||||
to?: string;
|
||||
color?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| Partial<Record<Breakpoint, 'primary' | 'secondary'>>;
|
||||
// (undocumented)
|
||||
variant?:
|
||||
| 'subtitle'
|
||||
| 'body'
|
||||
| 'caption'
|
||||
| 'label'
|
||||
| Partial<Record<Breakpoint, 'subtitle' | 'body' | 'caption' | 'label'>>;
|
||||
| 'title-large'
|
||||
| 'title-medium'
|
||||
| 'title-small'
|
||||
| 'title-x-small'
|
||||
| 'body-large'
|
||||
| 'body-medium'
|
||||
| 'body-small'
|
||||
| 'body-x-small'
|
||||
| Partial<
|
||||
Record<
|
||||
Breakpoint,
|
||||
| 'title-large'
|
||||
| 'title-medium'
|
||||
| 'title-small'
|
||||
| 'title-x-small'
|
||||
| 'body-large'
|
||||
| 'body-medium'
|
||||
| 'body-small'
|
||||
| 'body-x-small'
|
||||
>
|
||||
>;
|
||||
// (undocumented)
|
||||
weight?: 'regular' | 'bold' | Partial<Record<Breakpoint, 'regular' | 'bold'>>;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import type { Meta, StoryFn, StoryObj } from '@storybook/react';
|
||||
import { DataTable } from '.';
|
||||
import { data, DataProps } from './mocked-components';
|
||||
import { columns } from './mocked-columns';
|
||||
@@ -26,9 +26,17 @@ import {
|
||||
PaginationState,
|
||||
} from '@tanstack/react-table';
|
||||
import { useState } from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/DataTable',
|
||||
decorators: [
|
||||
(Story: StoryFn) => (
|
||||
<MemoryRouter>
|
||||
<Story />
|
||||
</MemoryRouter>
|
||||
),
|
||||
],
|
||||
} satisfies Meta;
|
||||
|
||||
export default meta;
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import type { Meta, StoryFn, StoryObj } from '@storybook/react';
|
||||
import { Link } from './Link';
|
||||
import { Flex } from '../Flex';
|
||||
import { Text } from '../Text';
|
||||
import { Link as RouterLink, MemoryRouter } from 'react-router-dom';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Link',
|
||||
@@ -26,6 +26,13 @@ const meta = {
|
||||
args: {
|
||||
children: 'Link',
|
||||
},
|
||||
decorators: [
|
||||
(Story: StoryFn) => (
|
||||
<MemoryRouter>
|
||||
<Story />
|
||||
</MemoryRouter>
|
||||
),
|
||||
],
|
||||
} satisfies Meta<typeof Link>;
|
||||
|
||||
export default meta;
|
||||
@@ -33,21 +40,55 @@ type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
to: 'https://ui.backstage.io',
|
||||
href: '/home',
|
||||
children: 'Sign up for Backstage',
|
||||
},
|
||||
};
|
||||
|
||||
export const ExternalLink: Story = {
|
||||
args: {
|
||||
href: 'https://backstage.io',
|
||||
children: 'Sign up for Backstage',
|
||||
target: '_blank',
|
||||
},
|
||||
};
|
||||
|
||||
export const AllVariants: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
},
|
||||
render: args => (
|
||||
<Flex gap="4" direction="column">
|
||||
<Link href="https://ui.backstage.io" variant="subtitle" {...args} />
|
||||
<Link href="https://ui.backstage.io" variant="body" {...args} />
|
||||
<Link href="https://ui.backstage.io" variant="caption" {...args} />
|
||||
<Link href="https://ui.backstage.io" variant="label" {...args} />
|
||||
<Link href="https://ui.backstage.io" variant="title-large" {...args} />
|
||||
<Link href="https://ui.backstage.io" variant="title-medium" {...args} />
|
||||
<Link href="https://ui.backstage.io" variant="title-small" {...args} />
|
||||
<Link href="https://ui.backstage.io" variant="title-x-small" {...args} />
|
||||
<Link href="https://ui.backstage.io" variant="body-large" {...args} />
|
||||
<Link href="https://ui.backstage.io" variant="body-medium" {...args} />
|
||||
<Link href="https://ui.backstage.io" variant="body-small" {...args} />
|
||||
<Link href="https://ui.backstage.io" variant="body-x-small" {...args} />
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const AllColors: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
},
|
||||
render: args => (
|
||||
<Flex gap="4" direction="column">
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="title-small"
|
||||
color="primary"
|
||||
{...args}
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="title-small"
|
||||
color="secondary"
|
||||
{...args}
|
||||
/>
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
@@ -58,8 +99,102 @@ export const AllWeights: Story = {
|
||||
},
|
||||
render: args => (
|
||||
<Flex gap="4" direction="column">
|
||||
<Link weight="regular" style={{ maxWidth: '600px' }} {...args} />
|
||||
<Link weight="bold" style={{ maxWidth: '600px' }} {...args} />
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="title-large"
|
||||
weight="regular"
|
||||
{...args}
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="title-large"
|
||||
weight="bold"
|
||||
{...args}
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="title-medium"
|
||||
weight="regular"
|
||||
{...args}
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="title-medium"
|
||||
weight="bold"
|
||||
{...args}
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="title-small"
|
||||
weight="regular"
|
||||
{...args}
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="title-small"
|
||||
weight="bold"
|
||||
{...args}
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="title-x-small"
|
||||
weight="regular"
|
||||
{...args}
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="title-x-small"
|
||||
weight="bold"
|
||||
{...args}
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="body-large"
|
||||
weight="regular"
|
||||
{...args}
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="body-large"
|
||||
weight="bold"
|
||||
{...args}
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="body-medium"
|
||||
weight="regular"
|
||||
{...args}
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="body-medium"
|
||||
weight="bold"
|
||||
{...args}
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="body-small"
|
||||
weight="regular"
|
||||
{...args}
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="body-small"
|
||||
weight="bold"
|
||||
{...args}
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="body-x-small"
|
||||
weight="regular"
|
||||
{...args}
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="body-x-small"
|
||||
weight="bold"
|
||||
{...args}
|
||||
/>
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
@@ -68,43 +203,32 @@ export const Responsive: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: {
|
||||
xs: 'label',
|
||||
md: 'body',
|
||||
xs: 'title-x-small',
|
||||
md: 'body-x-small',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const CustomRender: Story = {
|
||||
render: () => {
|
||||
return (
|
||||
<Flex gap="4" direction="column" align="start">
|
||||
<Link render={<RouterLink to="/catalog" />}>Go to Catalog</Link>
|
||||
</Flex>
|
||||
);
|
||||
},
|
||||
decorators: [
|
||||
Story => (
|
||||
<MemoryRouter>
|
||||
<Story />
|
||||
</MemoryRouter>
|
||||
),
|
||||
],
|
||||
};
|
||||
|
||||
export const Playground: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
},
|
||||
render: args => (
|
||||
<Flex gap="4" direction="column">
|
||||
<Text>Subtitle</Text>
|
||||
<Link variant="subtitle" style={{ maxWidth: '600px' }} {...args} />
|
||||
<Text>Body</Text>
|
||||
<Link variant="body" style={{ maxWidth: '600px' }} {...args} />
|
||||
<Text>Caption</Text>
|
||||
<Link variant="caption" style={{ maxWidth: '600px' }} {...args} />
|
||||
<Text>Label</Text>
|
||||
<Link variant="label" style={{ maxWidth: '600px' }} {...args} />
|
||||
<Text>Title X Small</Text>
|
||||
<Link variant="title-x-small" style={{ maxWidth: '600px' }} {...args} />
|
||||
<Text>Body X Small</Text>
|
||||
<Link variant="body-x-small" style={{ maxWidth: '600px' }} {...args} />
|
||||
<Text>Body Small</Text>
|
||||
<Link variant="body-small" style={{ maxWidth: '600px' }} {...args} />
|
||||
<Text>Body Medium</Text>
|
||||
<Link variant="body-medium" style={{ maxWidth: '600px' }} {...args} />
|
||||
<Text>Body Large</Text>
|
||||
<Link variant="body-large" style={{ maxWidth: '600px' }} {...args} />
|
||||
<Text>Title Small</Text>
|
||||
<Link variant="title-small" style={{ maxWidth: '600px' }} {...args} />
|
||||
<Text>Title Medium</Text>
|
||||
<Link variant="title-medium" style={{ maxWidth: '600px' }} {...args} />
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
@@ -14,37 +14,80 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { useRef, forwardRef } from 'react';
|
||||
import { useRender } from '@base-ui-components/react/use-render';
|
||||
import { forwardRef } from 'react';
|
||||
import { Link as AriaLink, RouterProvider } from 'react-aria-components';
|
||||
import clsx from 'clsx';
|
||||
import { useStyles } from '../../hooks/useStyles';
|
||||
|
||||
import type { LinkProps } from './types';
|
||||
import { useNavigate, useHref } from 'react-router-dom';
|
||||
|
||||
// Helper function to determine if a link is external
|
||||
function isExternalLink(href?: string): boolean {
|
||||
if (!href) return false;
|
||||
|
||||
// Check if it's an absolute URL with protocol
|
||||
if (href.startsWith('http://') || href.startsWith('https://')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if it's a protocol-relative URL
|
||||
if (href.startsWith('//')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if it's a mailto: or tel: link
|
||||
if (href.startsWith('mailto:') || href.startsWith('tel:')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export const Link = forwardRef<HTMLElement, LinkProps>((props, ref) => {
|
||||
export const Link = forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => {
|
||||
const navigate = useNavigate();
|
||||
const {
|
||||
className,
|
||||
variant = 'body',
|
||||
weight = 'regular',
|
||||
render = <a />,
|
||||
color = 'primary',
|
||||
href,
|
||||
...restProps
|
||||
} = props;
|
||||
|
||||
const { classNames, dataAttributes } = useStyles('Link', { variant, weight });
|
||||
const internalRef = useRef<HTMLElement | null>(null);
|
||||
|
||||
const { renderElement } = useRender({
|
||||
render,
|
||||
props: {
|
||||
className: clsx(classNames.root, className),
|
||||
...dataAttributes,
|
||||
...restProps,
|
||||
},
|
||||
refs: [ref, internalRef],
|
||||
const { classNames, dataAttributes } = useStyles('Link', {
|
||||
variant,
|
||||
weight,
|
||||
color,
|
||||
});
|
||||
|
||||
return renderElement();
|
||||
const isExternal = isExternalLink(href);
|
||||
|
||||
// If it's an external link, render AriaLink without RouterProvider
|
||||
if (isExternal) {
|
||||
return (
|
||||
<AriaLink
|
||||
ref={ref}
|
||||
className={clsx(classNames.root, className)}
|
||||
href={href}
|
||||
{...dataAttributes}
|
||||
{...restProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// For internal links, use RouterProvider
|
||||
return (
|
||||
<RouterProvider navigate={navigate} useHref={useHref}>
|
||||
<AriaLink
|
||||
ref={ref}
|
||||
className={clsx(classNames.root, className)}
|
||||
href={href}
|
||||
{...dataAttributes}
|
||||
{...restProps}
|
||||
/>
|
||||
</RouterProvider>
|
||||
);
|
||||
});
|
||||
|
||||
Link.displayName = 'Link';
|
||||
|
||||
@@ -16,14 +16,12 @@
|
||||
|
||||
.bui-Link {
|
||||
font-family: var(--bui-font-regular);
|
||||
color: var(--bui-fg-link);
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
text-decoration-line: none;
|
||||
|
||||
&:hover {
|
||||
color: var(--bui-fg-link-hover);
|
||||
text-decoration-line: underline;
|
||||
text-decoration-style: solid;
|
||||
text-decoration-thickness: min(2px, max(1px, 0.05em));
|
||||
@@ -36,22 +34,42 @@
|
||||
}
|
||||
}
|
||||
|
||||
.bui-Link[data-variant='body'] {
|
||||
font-size: var(--bui-font-size-3);
|
||||
.bui-Link[data-variant='title-large'] {
|
||||
font-size: var(--bui-font-size-8);
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
.bui-Link[data-variant='subtitle'] {
|
||||
.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='caption'] {
|
||||
.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='label'] {
|
||||
.bui-Link[data-variant='body-x-small'] {
|
||||
font-size: var(--bui-font-size-1);
|
||||
line-height: 140%;
|
||||
}
|
||||
@@ -63,3 +81,11 @@
|
||||
.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);
|
||||
}
|
||||
|
||||
@@ -14,21 +14,36 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { CSSProperties, ReactNode } from 'react';
|
||||
import type { Breakpoint } from '../../types';
|
||||
import type { useRender } from '@base-ui-components/react/use-render';
|
||||
import type { LinkProps as AriaLinkProps } from 'react-aria-components';
|
||||
|
||||
/** @public */
|
||||
export interface LinkProps extends useRender.ComponentProps<'a'> {
|
||||
children: ReactNode;
|
||||
to?: string;
|
||||
export interface LinkProps extends AriaLinkProps {
|
||||
variant?:
|
||||
| 'subtitle'
|
||||
| 'body'
|
||||
| 'caption'
|
||||
| 'label'
|
||||
| Partial<Record<Breakpoint, 'subtitle' | 'body' | 'caption' | 'label'>>;
|
||||
| 'title-large'
|
||||
| 'title-medium'
|
||||
| 'title-small'
|
||||
| 'title-x-small'
|
||||
| 'body-large'
|
||||
| 'body-medium'
|
||||
| 'body-small'
|
||||
| 'body-x-small'
|
||||
| Partial<
|
||||
Record<
|
||||
Breakpoint,
|
||||
| 'title-large'
|
||||
| 'title-medium'
|
||||
| 'title-small'
|
||||
| 'title-x-small'
|
||||
| 'body-large'
|
||||
| 'body-medium'
|
||||
| 'body-small'
|
||||
| 'body-x-small'
|
||||
>
|
||||
>;
|
||||
weight?: 'regular' | 'bold' | Partial<Record<Breakpoint, 'regular' | 'bold'>>;
|
||||
className?: string;
|
||||
style?: CSSProperties;
|
||||
color?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| Partial<Record<Breakpoint, 'primary' | 'secondary'>>;
|
||||
}
|
||||
|
||||
@@ -14,12 +14,20 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import type { Meta, StoryFn, StoryObj } from '@storybook/react';
|
||||
import { TableCellLink } from './TableCellLink';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Table/TableCellLink',
|
||||
component: TableCellLink,
|
||||
decorators: [
|
||||
(Story: StoryFn) => (
|
||||
<MemoryRouter>
|
||||
<Story />
|
||||
</MemoryRouter>
|
||||
),
|
||||
],
|
||||
} satisfies Meta<typeof TableCellLink>;
|
||||
|
||||
export default meta;
|
||||
|
||||
@@ -32,11 +32,7 @@ const TableCellLink = forwardRef<HTMLDivElement, TableCellLinkProps>(
|
||||
className={clsx(classNames.cellLink, className)}
|
||||
{...props}
|
||||
>
|
||||
{title && (
|
||||
<Link href={href} render={render}>
|
||||
{title}
|
||||
</Link>
|
||||
)}
|
||||
{title && <Link href={href}>{title}</Link>}
|
||||
{description && (
|
||||
<Text variant="body" color="secondary">
|
||||
{description}
|
||||
|
||||
@@ -14,12 +14,20 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import type { Meta, StoryFn, StoryObj } from '@storybook/react';
|
||||
import { TableCellProfile } from './TableCellProfile';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Table/TableCellProfile',
|
||||
component: TableCellProfile,
|
||||
decorators: [
|
||||
(Story: StoryFn) => (
|
||||
<MemoryRouter>
|
||||
<Story />
|
||||
</MemoryRouter>
|
||||
),
|
||||
],
|
||||
} satisfies Meta<typeof TableCellProfile>;
|
||||
|
||||
export default meta;
|
||||
|
||||
@@ -52,7 +52,7 @@ const TableCellProfile = forwardRef<HTMLDivElement, TableCellProfileProps>(
|
||||
</Avatar.Root>
|
||||
)}
|
||||
{name && to ? (
|
||||
<Link to={to}>{name}</Link>
|
||||
<Link href={to}>{name}</Link>
|
||||
) : (
|
||||
<Text variant="body">{name}</Text>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user