Merge branch 'master' into docs-ui
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/ui': minor
|
||||
---
|
||||
|
||||
**Breaking** We are upgrading our `Text` component to support all font sizes making the `Heading` component redundant. The new `Text` component introduces 4 sizes for title and 4 sizes for body text. All of these work in multiple colors and font weights. We improved the `as` prop to include all possible values. The `Link` component has also been updated to match the new `Text` component.
|
||||
File diff suppressed because one or more lines are too long
@@ -1,71 +0,0 @@
|
||||
import { PropsTable } from '@/components/PropsTable';
|
||||
import { HeadingSnippet } from '@/snippets/stories-snippets';
|
||||
import { Snippet } from '@/components/Snippet';
|
||||
import { CodeBlock } from '@/components/CodeBlock';
|
||||
import {
|
||||
headingPropDefs,
|
||||
headingUsageSnippet,
|
||||
headingDefaultSnippet,
|
||||
headingVariantsSnippet,
|
||||
headingTruncateSnippet,
|
||||
headingResponsiveSnippet,
|
||||
} from './heading.props';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
|
||||
<PageTitle
|
||||
title="Heading"
|
||||
description="Headings are used to structure the content of your page."
|
||||
/>
|
||||
|
||||
<Snippet
|
||||
py={4}
|
||||
preview={<HeadingSnippet story="Title1" />}
|
||||
code={headingDefaultSnippet}
|
||||
/>
|
||||
|
||||
## Usage
|
||||
|
||||
<CodeBlock code={headingUsageSnippet} />
|
||||
|
||||
## API reference
|
||||
|
||||
<PropsTable data={headingPropDefs} />
|
||||
|
||||
## Examples
|
||||
|
||||
### All variants
|
||||
|
||||
The `Heading` component has a `variant` prop that can be used to change the
|
||||
appearance of the heading.
|
||||
|
||||
<Snippet
|
||||
py={2}
|
||||
open
|
||||
preview={<HeadingSnippet story="AllVariants" />}
|
||||
code={headingVariantsSnippet}
|
||||
/>
|
||||
|
||||
### Truncate
|
||||
|
||||
The `Heading` component has a `truncate` prop that can be used to truncate the
|
||||
heading.
|
||||
|
||||
<Snippet
|
||||
py={2}
|
||||
open
|
||||
preview={<HeadingSnippet story="Truncate" />}
|
||||
code={headingTruncateSnippet}
|
||||
/>
|
||||
|
||||
### Responsive
|
||||
|
||||
You can also use the `variant` prop to change the appearance of the text based
|
||||
on the screen size.
|
||||
|
||||
<CodeBlock code={headingResponsiveSnippet} />
|
||||
|
||||
<Theming component="Heading" />
|
||||
|
||||
<ChangelogComponent component="heading" />
|
||||
@@ -1,48 +0,0 @@
|
||||
import {
|
||||
classNamePropDefs,
|
||||
stylePropDefs,
|
||||
type PropDef,
|
||||
} from '@/utils/propDefs';
|
||||
|
||||
export const headingPropDefs: Record<string, PropDef> = {
|
||||
variant: {
|
||||
type: 'enum',
|
||||
values: ['display', 'title1', 'title2', 'title3', 'title4', 'title5'],
|
||||
responsive: true,
|
||||
},
|
||||
children: {
|
||||
type: 'enum',
|
||||
values: ['ReactNode'],
|
||||
responsive: false,
|
||||
},
|
||||
truncate: {
|
||||
type: 'boolean',
|
||||
default: 'false',
|
||||
},
|
||||
...classNamePropDefs,
|
||||
...stylePropDefs,
|
||||
};
|
||||
|
||||
export const headingUsageSnippet = `import { Heading } from '@backstage/ui';
|
||||
|
||||
<Heading />`;
|
||||
|
||||
export const headingDefaultSnippet = `<Heading variant="title1">Hello World!</Heading>`;
|
||||
|
||||
export const headingVariantsSnippet = `<Flex direction="column" gap="4">
|
||||
<Heading variant="display">Display</Heading>
|
||||
<Heading variant="title1">Title 1</Heading>
|
||||
<Heading variant="title2">Title 2</Heading>
|
||||
<Heading variant="title3">Title 3</Heading>
|
||||
<Heading variant="title4">Title 4</Heading>
|
||||
</Flex>`;
|
||||
|
||||
export const headingTruncateSnippet = `<Heading style={{ maxWidth: '400px' }} truncate>
|
||||
A man looks at a painting in a museum and says, "Brothers and sisters I
|
||||
have none, but that man's father is my father's son." Who is
|
||||
in the painting?
|
||||
</Heading>`;
|
||||
|
||||
export const headingResponsiveSnippet = `<Heading variant={{ initial: 'title2', lg: 'title1' }}>
|
||||
Responsive heading
|
||||
</Heading>`;
|
||||
@@ -12,6 +12,9 @@ import {
|
||||
linkDefaultSnippet,
|
||||
linkVariantsSnippet,
|
||||
linkWeightsSnippet,
|
||||
linkColorsSnippet,
|
||||
linkRouterSnippet,
|
||||
linkTruncateSnippet,
|
||||
} from './link.props';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
@@ -37,6 +40,15 @@ import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
|
||||
<PropsTable data={linkPropDefs} />
|
||||
|
||||
## Router Integration
|
||||
|
||||
The `Link` component handles both internal and external navigation. It automatically detects whether the provided URL is internal (relative path) or external (absolute URL with protocol) and renders the appropriate element:
|
||||
|
||||
- **Internal routes**: Uses `react-router-dom`'s `Link` component for client-side navigation
|
||||
- **External URLs**: Renders a standard `<a>` element for traditional navigation
|
||||
|
||||
<CodeBlock language="tsx" code={linkRouterSnippet} />
|
||||
|
||||
## Examples
|
||||
|
||||
### Variants
|
||||
@@ -63,6 +75,28 @@ Here's a view when links have different weights.
|
||||
code={linkWeightsSnippet}
|
||||
/>
|
||||
|
||||
### Colors
|
||||
|
||||
Here's a view when links have different colors.
|
||||
|
||||
<Snippet
|
||||
align="center"
|
||||
py={4}
|
||||
open
|
||||
preview={<LinkSnippet story="AllColors" />}
|
||||
code={linkColorsSnippet}
|
||||
/>
|
||||
|
||||
### Truncate
|
||||
|
||||
The `Link` component has a `truncate` prop that can be used to truncate the text.
|
||||
|
||||
<Snippet
|
||||
open
|
||||
preview={<LinkSnippet story="Truncate" />}
|
||||
code={linkTruncateSnippet}
|
||||
/>
|
||||
|
||||
<Theming component="Link" />
|
||||
|
||||
<ChangelogComponent component="link" />
|
||||
|
||||
@@ -5,13 +5,22 @@ import {
|
||||
} from '@/utils/propDefs';
|
||||
|
||||
export const linkPropDefs: Record<string, PropDef> = {
|
||||
to: {
|
||||
href: {
|
||||
type: 'string',
|
||||
},
|
||||
variant: {
|
||||
type: 'enum',
|
||||
values: ['subtitle', 'body', 'caption', 'label'],
|
||||
default: 'body',
|
||||
values: [
|
||||
'title-large',
|
||||
'title-medium',
|
||||
'title-small',
|
||||
'title-x-small',
|
||||
'body-large',
|
||||
'body-medium',
|
||||
'body-small',
|
||||
'body-x-small',
|
||||
],
|
||||
default: 'body-medium',
|
||||
responsive: true,
|
||||
},
|
||||
weight: {
|
||||
@@ -20,24 +29,53 @@ export const linkPropDefs: Record<string, PropDef> = {
|
||||
default: 'regular',
|
||||
responsive: true,
|
||||
},
|
||||
color: {
|
||||
type: 'enum',
|
||||
values: ['primary', 'secondary', 'danger', 'warning', 'success'],
|
||||
default: 'primary',
|
||||
responsive: true,
|
||||
},
|
||||
...classNamePropDefs,
|
||||
...stylePropDefs,
|
||||
};
|
||||
|
||||
export const linkUsageSnippet = `import { Link } from '@backstage/ui';
|
||||
|
||||
<Link href="https://backstage.io">Sign up for Backstage</Link>`;
|
||||
<Link href="/sign-up">Sign up for Backstage</Link>`;
|
||||
|
||||
export const linkDefaultSnippet = `<Link href="https://backstage.io">Sign up for Backstage</Link>`;
|
||||
export const linkDefaultSnippet = `<Link href="/">Sign up for Backstage</Link>`;
|
||||
|
||||
export const linkVariantsSnippet = `<Flex gap="4" direction="column">
|
||||
<Link href="https://ui.backstage.io" variant="subtitle" />
|
||||
<Link href="https://ui.backstage.io" variant="body" />
|
||||
<Link href="https://ui.backstage.io" variant="caption" />
|
||||
<Link href="https://ui.backstage.io" variant="label" />
|
||||
<Link href="/" variant="title-large">...</Link>
|
||||
<Link href="/" variant="title-medium">...</Link>
|
||||
<Link href="/" variant="title-small">...</Link>
|
||||
<Link href="/" variant="title-x-small">...</Link>
|
||||
<Link href="/" variant="body-large">...</Link>
|
||||
<Link href="/" variant="body-medium">...</Link>
|
||||
<Link href="/" variant="body-small">...</Link>
|
||||
<Link href="/" variant="body-x-small">...</Link>
|
||||
</Flex>`;
|
||||
|
||||
export const linkWeightsSnippet = `<Flex gap="4" direction="column">
|
||||
<Link href="https://ui.backstage.io" weight="regular" />
|
||||
<Link href="https://ui.backstage.io" weight="bold" />
|
||||
<Link href="/" weight="regular" />
|
||||
<Link href="/" weight="bold" />
|
||||
</Flex>`;
|
||||
|
||||
export const linkColorsSnippet = `<Flex gap="4" direction="column">
|
||||
<Link href="/" color="primary">I am primary</Link>
|
||||
<Link href="/" color="secondary">I am secondary</Link>
|
||||
<Link href="/" color="danger">I am danger</Link>
|
||||
<Link href="/" color="warning">I am warning</Link>
|
||||
<Link href="/" color="success">I am success</Link>
|
||||
</Flex>`;
|
||||
|
||||
export const linkRouterSnippet = `import { Link } from '@backstage/ui';
|
||||
|
||||
// Internal route
|
||||
<Link href="/home">Home</Link>
|
||||
|
||||
// External URL
|
||||
<Link href="https://backstage.io">Backstage</Link>
|
||||
`;
|
||||
|
||||
export const linkTruncateSnippet = `<Link href="/" truncate>...</Link>`;
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
textWeightsSnippet,
|
||||
textTruncateSnippet,
|
||||
textResponsiveSnippet,
|
||||
textColorsSnippet,
|
||||
} from './text.props';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
@@ -58,10 +59,20 @@ appearance of the text.
|
||||
code={textWeightsSnippet}
|
||||
/>
|
||||
|
||||
### All colors
|
||||
|
||||
The `Text` component has a `color` prop that can be used to change the
|
||||
appearance of the text.
|
||||
|
||||
<Snippet
|
||||
open
|
||||
preview={<TextSnippet story="AllColors" />}
|
||||
code={textColorsSnippet}
|
||||
/>
|
||||
|
||||
### Truncate
|
||||
|
||||
The `Text` component has a `truncate` prop that can be used to truncate the
|
||||
text.
|
||||
The `Text` component has a `truncate` prop that can be used to truncate the text.
|
||||
|
||||
<Snippet
|
||||
open
|
||||
|
||||
@@ -6,9 +6,38 @@ import {
|
||||
import type { PropDef } from '@/utils/propDefs';
|
||||
|
||||
export const textPropDefs: Record<string, PropDef> = {
|
||||
as: {
|
||||
type: 'enum',
|
||||
values: [
|
||||
'h1',
|
||||
'h2',
|
||||
'h3',
|
||||
'h4',
|
||||
'h5',
|
||||
'h6',
|
||||
'p',
|
||||
'span',
|
||||
'label',
|
||||
'div',
|
||||
'strong',
|
||||
'em',
|
||||
'small',
|
||||
],
|
||||
default: 'span',
|
||||
responsive: true,
|
||||
},
|
||||
variant: {
|
||||
type: 'enum',
|
||||
values: ['display', 'title1', 'title2', 'title3', 'title4', 'title5'],
|
||||
values: [
|
||||
'title-large',
|
||||
'title-medium',
|
||||
'title-small',
|
||||
'title-x-small',
|
||||
'body-large',
|
||||
'body-medium',
|
||||
'body-small',
|
||||
'body-x-small',
|
||||
],
|
||||
responsive: true,
|
||||
},
|
||||
weight: {
|
||||
@@ -16,6 +45,12 @@ export const textPropDefs: Record<string, PropDef> = {
|
||||
values: ['regular', 'bold'],
|
||||
responsive: true,
|
||||
},
|
||||
color: {
|
||||
type: 'enum',
|
||||
values: ['primary', 'secondary', 'danger', 'warning', 'success'],
|
||||
default: 'primary',
|
||||
responsive: true,
|
||||
},
|
||||
truncate: {
|
||||
type: 'boolean',
|
||||
default: 'false',
|
||||
@@ -36,46 +71,60 @@ export const textDefaultSnippet = `<Text style={{ maxWidth: '600px' }}>
|
||||
</Text>`;
|
||||
|
||||
export const textVariantsSnippet = `<Flex direction="column" gap="4">
|
||||
<Text variant="subtitle" style={{ maxWidth: '600px' }}>
|
||||
A man looks at a painting in a museum and says, "Brothers and sisters I
|
||||
have none, but that man's father is my father's son." Who is
|
||||
in the painting?
|
||||
</Text>
|
||||
<Text variant="body" style={{ maxWidth: '600px' }}>
|
||||
A man looks at a painting in a museum and says, "Brothers and sisters I
|
||||
have none, but that man's father is my father's son." Who is
|
||||
in the painting?
|
||||
</Text>
|
||||
<Text variant="caption" style={{ maxWidth: '600px' }}>
|
||||
A man looks at a painting in a museum and says, "Brothers and sisters I
|
||||
have none, but that man's father is my father's son." Who is
|
||||
in the painting?
|
||||
</Text>
|
||||
<Text variant="label" style={{ maxWidth: '600px' }}>
|
||||
A man looks at a painting in a museum and says, "Brothers and sisters I
|
||||
have none, but that man's father is my father's son." Who is
|
||||
in the painting?
|
||||
</Text>
|
||||
<Text variant="title-large">...</Text>
|
||||
<Text variant="title-medium">...</Text>
|
||||
<Text variant="title-small">...</Text>
|
||||
<Text variant="title-x-small">...</Text>
|
||||
<Text variant="body-large">...</Text>
|
||||
<Text variant="body-medium">...</Text>
|
||||
<Text variant="body-small">...</Text>
|
||||
<Text variant="body-x-small">...</Text>
|
||||
</Flex>`;
|
||||
|
||||
export const textWeightsSnippet = `<Flex direction="column" gap="4">
|
||||
<Text weight="regular" style={{ maxWidth: '600px' }}>
|
||||
A man looks at a painting in a museum and says, "Brothers and sisters I
|
||||
have none, but that man's father is my father's son." Who is
|
||||
in the painting?
|
||||
</Text>
|
||||
<Text weight="bold" style={{ maxWidth: '600px' }}>
|
||||
A man looks at a painting in a museum and says, "Brothers and sisters I
|
||||
have none, but that man's father is my father's son." Who is
|
||||
in the painting?
|
||||
</Text>
|
||||
<Flex>
|
||||
<Text variant="title-large" weight="regular">A fox</Text>
|
||||
<Text variant="title-large" weight="bold">A turtle</Text>
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Text variant="title-medium" weight="regular">A fox</Text>
|
||||
<Text variant="title-medium" weight="bold">A turtle</Text>
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Text variant="title-small" weight="regular">A fox</Text>
|
||||
<Text variant="title-small" weight="bold">A turtle</Text>
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Text variant="title-x-small" weight="regular">A fox</Text>
|
||||
<Text variant="title-x-small" weight="bold">A turtle</Text>
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Text variant="body-large" weight="regular">A fox</Text>
|
||||
<Text variant="body-large" weight="bold">A turtle</Text>
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Text variant="body-medium" weight="regular">A fox</Text>
|
||||
<Text variant="body-medium" weight="bold">A turtle</Text>
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Text variant="body-small" weight="regular">A fox</Text>
|
||||
<Text variant="body-small" weight="bold">A turtle</Text>
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Text variant="body-x-small" weight="regular">A fox</Text>
|
||||
<Text variant="body-x-small" weight="bold">A turtle</Text>
|
||||
</Flex>
|
||||
</Flex>`;
|
||||
|
||||
export const textTruncateSnippet = `<Text weight="regular" style={{ maxWidth: '600px' }} truncate>
|
||||
A man looks at a painting in a museum and says, "Brothers and sisters I
|
||||
have none, but that man's father is my father's son." Who is
|
||||
in the painting?
|
||||
</Text>`;
|
||||
export const textColorsSnippet = `<Flex direction="column" gap="4">
|
||||
<Text color="primary">I am primary</Text>
|
||||
<Text color="secondary">I am secondary</Text>
|
||||
<Text color="danger">I am danger</Text>
|
||||
<Text color="warning">I am warning</Text>
|
||||
<Text color="success">I am success</Text>
|
||||
</Flex>`;
|
||||
|
||||
export const textTruncateSnippet = `<Text as="p" truncate>...</Text>`;
|
||||
|
||||
export const textResponsiveSnippet = `<Text variant={{ initial: 'body', lg: 'subtitle' }}>
|
||||
Responsive text
|
||||
|
||||
@@ -8,7 +8,6 @@ import * as ButtonLinkStories from '../../../packages/ui/src/components/ButtonLi
|
||||
import * as CheckboxStories from '../../../packages/ui/src/components/Checkbox/Checkbox.stories';
|
||||
import * as ContainerStories from '../../../packages/ui/src/components/Container/Container.stories';
|
||||
import * as GridStories from '../../../packages/ui/src/components/Grid/Grid.stories';
|
||||
import * as HeadingStories from '../../../packages/ui/src/components/Heading/Heading.stories';
|
||||
import * as IconStories from '../../../packages/ui/src/components/Icon/Icon.stories';
|
||||
import * as TextFieldStories from '../../../packages/ui/src/components/TextField/TextField.stories';
|
||||
import * as TextStories from '../../../packages/ui/src/components/Text/Text.stories';
|
||||
@@ -113,17 +112,6 @@ export const GridSnippet = ({ story }: { story: keyof typeof GridStories }) => {
|
||||
return StoryComponent ? <StoryComponent /> : null;
|
||||
};
|
||||
|
||||
export const HeadingSnippet = ({
|
||||
story,
|
||||
}: {
|
||||
story: keyof typeof HeadingStories;
|
||||
}) => {
|
||||
const stories = composeStories(HeadingStories);
|
||||
const StoryComponent = stories[story as keyof typeof stories];
|
||||
|
||||
return StoryComponent ? <StoryComponent /> : null;
|
||||
};
|
||||
|
||||
export const IconSnippet = ({ story }: { story: keyof typeof IconStories }) => {
|
||||
const stories = composeStories(IconStories);
|
||||
const StoryComponent = stories[story as keyof typeof stories];
|
||||
|
||||
@@ -101,11 +101,6 @@ export const components: Page[] = [
|
||||
slug: 'collapsible',
|
||||
status: 'alpha',
|
||||
},
|
||||
{
|
||||
title: 'Heading',
|
||||
slug: 'heading',
|
||||
status: 'alpha',
|
||||
},
|
||||
{
|
||||
title: 'Icon',
|
||||
slug: 'icon',
|
||||
|
||||
+31
-114
@@ -9732,58 +9732,6 @@
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.bui-Heading {
|
||||
font-family: var(--bui-font-regular);
|
||||
color: var(--bui-fg-primary);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
line-height: 100%;
|
||||
}
|
||||
|
||||
.bui-Heading[data-variant="display"] {
|
||||
font-size: var(--bui-font-size-10);
|
||||
font-weight: var(--bui-font-weight-bold);
|
||||
}
|
||||
|
||||
.bui-Heading[data-variant="title1"] {
|
||||
font-size: var(--bui-font-size-9);
|
||||
font-weight: var(--bui-font-weight-bold);
|
||||
}
|
||||
|
||||
.bui-Heading[data-variant="title2"] {
|
||||
font-size: var(--bui-font-size-8);
|
||||
font-weight: var(--bui-font-weight-bold);
|
||||
}
|
||||
|
||||
.bui-Heading[data-variant="title3"] {
|
||||
font-size: var(--bui-font-size-7);
|
||||
font-weight: var(--bui-font-weight-bold);
|
||||
}
|
||||
|
||||
.bui-Heading[data-variant="title4"] {
|
||||
font-size: var(--bui-font-size-6);
|
||||
font-weight: var(--bui-font-weight-bold);
|
||||
}
|
||||
|
||||
.bui-Heading[data-variant="title5"] {
|
||||
font-size: var(--bui-font-size-5);
|
||||
font-weight: var(--bui-font-weight-bold);
|
||||
}
|
||||
|
||||
.bui-Heading[data-color="primary"] {
|
||||
color: var(--bui-fg-primary);
|
||||
}
|
||||
|
||||
.bui-Heading[data-color="secondary"] {
|
||||
color: var(--bui-fg-secondary);
|
||||
}
|
||||
|
||||
.bui-Heading[data-truncate] {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.bui-Icon {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
@@ -9795,72 +9743,17 @@
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-decoration-line: none;
|
||||
display: inline-block;
|
||||
|
||||
&:hover {
|
||||
text-underline-offset: calc(.025em + 2px);
|
||||
text-decoration-line: underline;
|
||||
text-decoration-style: solid;
|
||||
text-decoration-thickness: min(2px, max(1px, .05em));
|
||||
text-decoration-color: color-mix(in srgb, var(--bui-fg-link-hover) 30%, transparent);
|
||||
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-MenuPositioner {
|
||||
z-index: 100;
|
||||
outline: 0;
|
||||
@@ -10303,22 +10196,42 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.bui-Text[data-variant="body"] {
|
||||
font-size: var(--bui-font-size-3);
|
||||
.bui-Text[data-variant="title-large"] {
|
||||
font-size: var(--bui-font-size-8);
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
.bui-Text[data-variant="subtitle"] {
|
||||
.bui-Text[data-variant="title-medium"] {
|
||||
font-size: var(--bui-font-size-7);
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
.bui-Text[data-variant="title-small"] {
|
||||
font-size: var(--bui-font-size-6);
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
.bui-Text[data-variant="title-x-small"] {
|
||||
font-size: var(--bui-font-size-5);
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
.bui-Text[data-variant="body-large"] {
|
||||
font-size: var(--bui-font-size-4);
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
.bui-Text[data-variant="caption"] {
|
||||
.bui-Text[data-variant="body-medium"] {
|
||||
font-size: var(--bui-font-size-3);
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
.bui-Text[data-variant="body-small"] {
|
||||
font-size: var(--bui-font-size-2);
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
.bui-Text[data-variant="label"] {
|
||||
.bui-Text[data-variant="body-x-small"] {
|
||||
font-size: var(--bui-font-size-1);
|
||||
line-height: 140%;
|
||||
}
|
||||
@@ -10357,6 +10270,10 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.bui-Text[data-as="span"], .bui-Text[data-as="label"], .bui-Text[data-as="strong"], .bui-Text[data-as="em"], .bui-Text[data-as="small"] {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.bui-TextField {
|
||||
font-family: var(--bui-font-regular);
|
||||
flex-direction: column;
|
||||
|
||||
+47
-105
@@ -47,25 +47,6 @@ export type ArbitraryStylingPropDef = {
|
||||
parseValue?: (value: string) => string | undefined;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export type AsProps =
|
||||
| 'div'
|
||||
| 'span'
|
||||
| 'p'
|
||||
| 'article'
|
||||
| 'section'
|
||||
| 'main'
|
||||
| 'nav'
|
||||
| 'aside'
|
||||
| 'ul'
|
||||
| 'ol'
|
||||
| 'li'
|
||||
| 'details'
|
||||
| 'summary'
|
||||
| 'dd'
|
||||
| 'dl'
|
||||
| 'dt';
|
||||
|
||||
// @public (undocumented)
|
||||
export const Avatar: ForwardRefExoticComponent<
|
||||
AvatarProps & RefAttributes<HTMLSpanElement>
|
||||
@@ -1060,45 +1041,6 @@ export interface HeaderTab {
|
||||
matchStrategy?: TabMatchStrategy;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export const Heading: {
|
||||
<T extends ElementType = 'h1'>(
|
||||
props: HeadingProps<T> & {
|
||||
ref?: React.ComponentPropsWithRef<T>['ref'];
|
||||
},
|
||||
): React.ReactElement<HeadingProps<T>, T>;
|
||||
displayName: string;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export type HeadingOwnProps = {
|
||||
as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
|
||||
variant?:
|
||||
| 'display'
|
||||
| 'title1'
|
||||
| 'title2'
|
||||
| 'title3'
|
||||
| 'title4'
|
||||
| 'title5'
|
||||
| Partial<
|
||||
Record<
|
||||
Breakpoint,
|
||||
'display' | 'title1' | 'title2' | 'title3' | 'title4' | 'title5'
|
||||
>
|
||||
>;
|
||||
color?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| Partial<Record<Breakpoint, 'primary' | 'secondary'>>;
|
||||
truncate?: boolean;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export type HeadingProps<T extends ElementType = 'h1'> = HeadingOwnProps &
|
||||
Omit<ComponentPropsWithRef<T>, keyof HeadingOwnProps>;
|
||||
|
||||
// @public (undocumented)
|
||||
export const heightPropDefs: {
|
||||
height: {
|
||||
@@ -1238,34 +1180,15 @@ export const Link: ForwardRefExoticComponent<
|
||||
export interface LinkProps extends LinkProps_2 {
|
||||
// (undocumented)
|
||||
color?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| Partial<Record<Breakpoint, 'primary' | 'secondary'>>;
|
||||
| TextColors
|
||||
| TextColorStatus
|
||||
| Partial<Record<Breakpoint, TextColors | TextColorStatus>>;
|
||||
// (undocumented)
|
||||
variant?:
|
||||
| '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'
|
||||
>
|
||||
>;
|
||||
truncate?: boolean;
|
||||
// (undocumented)
|
||||
weight?: 'regular' | 'bold' | Partial<Record<Breakpoint, 'regular' | 'bold'>>;
|
||||
variant?: TextVariants | Partial<Record<Breakpoint, TextVariants>>;
|
||||
// (undocumented)
|
||||
weight?: TextWeights | Partial<Record<Breakpoint, TextWeights>>;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
@@ -1753,6 +1676,12 @@ const Text_2: {
|
||||
};
|
||||
export { Text_2 as Text };
|
||||
|
||||
// @public (undocumented)
|
||||
export type TextColors = 'primary' | 'secondary';
|
||||
|
||||
// @public (undocumented)
|
||||
export type TextColorStatus = 'danger' | 'warning' | 'success';
|
||||
|
||||
// @public (undocumented)
|
||||
export const TextField: ForwardRefExoticComponent<
|
||||
TextFieldProps & RefAttributes<HTMLDivElement>
|
||||
@@ -1769,35 +1698,48 @@ export interface TextFieldProps
|
||||
|
||||
// @public (undocumented)
|
||||
export type TextOwnProps = {
|
||||
as?: 'p' | 'span' | 'label';
|
||||
variant?:
|
||||
| 'subtitle'
|
||||
| 'body'
|
||||
| 'caption'
|
||||
as?:
|
||||
| 'h1'
|
||||
| 'h2'
|
||||
| 'h3'
|
||||
| 'h4'
|
||||
| 'h5'
|
||||
| 'h6'
|
||||
| 'p'
|
||||
| 'span'
|
||||
| 'label'
|
||||
| Partial<Record<Breakpoint, 'subtitle' | 'body' | 'caption' | 'label'>>;
|
||||
weight?: 'regular' | 'bold' | Partial<Record<Breakpoint, 'regular' | 'bold'>>;
|
||||
| 'div'
|
||||
| 'strong'
|
||||
| 'em'
|
||||
| 'small'
|
||||
| 'legend';
|
||||
variant?: TextVariants | Partial<Record<Breakpoint, TextVariants>>;
|
||||
weight?: TextWeights | Partial<Record<Breakpoint, TextWeights>>;
|
||||
color?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| 'danger'
|
||||
| 'warning'
|
||||
| 'success'
|
||||
| Partial<
|
||||
Record<
|
||||
Breakpoint,
|
||||
'primary' | 'secondary' | 'danger' | 'warning' | 'success'
|
||||
>
|
||||
>;
|
||||
| TextColors
|
||||
| TextColorStatus
|
||||
| Partial<Record<Breakpoint, TextColors | TextColorStatus>>;
|
||||
truncate?: boolean;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export type TextProps<T extends ElementType = 'p'> = TextOwnProps &
|
||||
export type TextProps<T extends ElementType = 'span'> = TextOwnProps &
|
||||
Omit<ComponentPropsWithRef<T>, keyof TextOwnProps>;
|
||||
|
||||
// @public (undocumented)
|
||||
export type TextVariants =
|
||||
| 'title-large'
|
||||
| 'title-medium'
|
||||
| 'title-small'
|
||||
| 'title-x-small'
|
||||
| 'body-large'
|
||||
| 'body-medium'
|
||||
| 'body-small'
|
||||
| 'body-x-small';
|
||||
|
||||
// @public (undocumented)
|
||||
export type TextWeights = 'regular' | 'bold';
|
||||
|
||||
// @public (undocumented)
|
||||
export const Tooltip: ForwardRefExoticComponent<
|
||||
TooltipProps & RefAttributes<HTMLDivElement>
|
||||
|
||||
@@ -70,7 +70,7 @@ const DataTablePagination = forwardRef(
|
||||
)}
|
||||
</div>
|
||||
<div className="bui-DataTablePagination--right">
|
||||
<Text variant="body">{`${fromCount} - ${toCount} of ${rowCount}`}</Text>
|
||||
<Text variant="body-medium">{`${fromCount} - ${toCount} of ${rowCount}`}</Text>
|
||||
<ButtonIcon
|
||||
variant="secondary"
|
||||
size="small"
|
||||
|
||||
@@ -268,10 +268,10 @@ export const WithMockedURLCampaigns: Story = {
|
||||
<MemoryRouter initialEntries={['/campaigns']}>
|
||||
<Header {...args} />
|
||||
<Container>
|
||||
<Text>
|
||||
<Text as="p">
|
||||
Current URL is mocked to be: <strong>/campaigns</strong>
|
||||
</Text>
|
||||
<Text>
|
||||
<Text as="p">
|
||||
Notice how the "Campaigns" tab is selected (highlighted) because it
|
||||
matches the current path.
|
||||
</Text>
|
||||
@@ -288,10 +288,10 @@ export const WithMockedURLIntegrations: Story = {
|
||||
<MemoryRouter initialEntries={['/integrations']}>
|
||||
<Header {...args} />
|
||||
<Container>
|
||||
<Text>
|
||||
<Text as="p">
|
||||
Current URL is mocked to be: <strong>/integrations</strong>
|
||||
</Text>
|
||||
<Text>
|
||||
<Text as="p">
|
||||
Notice how the "Integrations" tab is selected (highlighted) because it
|
||||
matches the current path.
|
||||
</Text>
|
||||
@@ -308,14 +308,14 @@ export const WithMockedURLNoMatch: Story = {
|
||||
<MemoryRouter initialEntries={['/some-other-page']}>
|
||||
<Header {...args} />
|
||||
<Container>
|
||||
<Text>
|
||||
<Text as="p">
|
||||
Current URL is mocked to be: <strong>/some-other-page</strong>
|
||||
</Text>
|
||||
<Text>
|
||||
<Text as="p">
|
||||
No tab is selected because the current path doesn't match any tab's
|
||||
href.
|
||||
</Text>
|
||||
<Text>
|
||||
<Text as="p">
|
||||
Tabs without href (like "Overview", "Checks", "Tracks") fall back to
|
||||
React Aria's internal state.
|
||||
</Text>
|
||||
|
||||
@@ -99,7 +99,7 @@ export const HeaderToolbar = (props: HeaderToolbarProps) => {
|
||||
const titleContent = (
|
||||
<>
|
||||
<div className={classNames.toolbarIcon}>{icon || <RiShapesLine />}</div>
|
||||
<Text variant="body">{title || 'Your plugin'}</Text>
|
||||
<Text variant="body-medium">{title || 'Your plugin'}</Text>
|
||||
</>
|
||||
);
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
|
||||
import type { HeaderPageProps } from './types';
|
||||
import { Heading } from '../Heading';
|
||||
import { Menu } from '../Menu';
|
||||
import { Text } from '../Text';
|
||||
import { ButtonIcon } from '../ButtonIcon';
|
||||
import { RiMore2Line } from '@remixicon/react';
|
||||
import { Tabs, TabList, Tab } from '../Tabs';
|
||||
@@ -34,7 +34,9 @@ export const HeaderPage = (props: HeaderPageProps) => {
|
||||
return (
|
||||
<div className={classNames.root}>
|
||||
<div className={classNames.content}>
|
||||
<Heading variant="title4">{title}</Heading>
|
||||
<Text variant="title-small" weight="bold">
|
||||
{title}
|
||||
</Text>
|
||||
<div className={classNames.controls}>
|
||||
{customActions}
|
||||
{menuItems && (
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { Heading } from './Heading';
|
||||
import { Flex } from '../Flex';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Heading',
|
||||
component: Heading,
|
||||
args: {
|
||||
children: 'Heading',
|
||||
},
|
||||
} satisfies Meta<typeof Heading>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Default: Story = {};
|
||||
|
||||
export const Title1: Story = {
|
||||
args: {
|
||||
children: 'Look mum, no hands!',
|
||||
variant: 'title1',
|
||||
},
|
||||
};
|
||||
|
||||
export const AllVariants: Story = {
|
||||
render: () => (
|
||||
<Flex direction="column" gap="4">
|
||||
<Heading variant="display">Display</Heading>
|
||||
<Heading variant="title1">Title 1</Heading>
|
||||
<Heading variant="title2">Title 2</Heading>
|
||||
<Heading variant="title3">Title 3</Heading>
|
||||
<Heading variant="title4">Title 4</Heading>
|
||||
<Heading variant="title5">Title 5</Heading>
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const AllColors: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
},
|
||||
render: args => (
|
||||
<Flex gap="4" direction="column">
|
||||
<Heading color="primary" {...args} />
|
||||
<Heading color="secondary" {...args} />
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const Truncate: Story = {
|
||||
args: {
|
||||
...Title1.args,
|
||||
truncate: true,
|
||||
style: { maxWidth: '400px' },
|
||||
},
|
||||
};
|
||||
|
||||
export const Responsive: Story = {
|
||||
args: {
|
||||
variant: {
|
||||
xs: 'title4',
|
||||
md: 'display',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const WrappedInLink: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
},
|
||||
decorators: [
|
||||
Story => (
|
||||
<a href="/">
|
||||
<Story />
|
||||
</a>
|
||||
),
|
||||
],
|
||||
};
|
||||
|
||||
export const CustomRender: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
as: 'h4',
|
||||
},
|
||||
};
|
||||
|
||||
export const Playground: Story = {
|
||||
render: () => (
|
||||
<Flex direction="column" gap="4">
|
||||
<Heading variant="display">Display</Heading>
|
||||
<Heading variant="title1">Title 1</Heading>
|
||||
<Heading variant="title2">Title 2</Heading>
|
||||
<Heading variant="title3">Title 3</Heading>
|
||||
<Heading variant="title4">Title 4</Heading>
|
||||
<Heading variant="title5">Title 5</Heading>
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { forwardRef } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import type { ElementType } from 'react';
|
||||
import type { HeadingProps } from './types';
|
||||
import { useStyles } from '../../hooks/useStyles';
|
||||
|
||||
function HeadingComponent<T extends ElementType = 'h1'>(
|
||||
{
|
||||
as,
|
||||
variant = 'title1',
|
||||
color = 'primary',
|
||||
truncate,
|
||||
className,
|
||||
style,
|
||||
...restProps
|
||||
}: HeadingProps<T>,
|
||||
ref: React.Ref<any>,
|
||||
) {
|
||||
const Component = as || 'h1';
|
||||
|
||||
const { classNames, dataAttributes } = useStyles('Heading', {
|
||||
variant,
|
||||
color,
|
||||
});
|
||||
|
||||
return (
|
||||
<Component
|
||||
ref={ref}
|
||||
className={clsx(classNames.root, className)}
|
||||
data-truncate={truncate}
|
||||
{...dataAttributes}
|
||||
style={style}
|
||||
{...restProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
HeadingComponent.displayName = 'Heading';
|
||||
|
||||
/** @public */
|
||||
export const Heading = forwardRef(HeadingComponent) as {
|
||||
<T extends ElementType = 'h1'>(
|
||||
props: HeadingProps<T> & { ref?: React.ComponentPropsWithRef<T>['ref'] },
|
||||
): React.ReactElement<HeadingProps<T>, T>;
|
||||
displayName: string;
|
||||
};
|
||||
|
||||
Heading.displayName = 'Heading';
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from './Heading';
|
||||
export * from './types';
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
.bui-Heading {
|
||||
font-family: var(--bui-font-regular);
|
||||
color: var(--bui-fg-primary);
|
||||
line-height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.bui-Heading[data-variant='display'] {
|
||||
font-size: var(--bui-font-size-10);
|
||||
font-weight: var(--bui-font-weight-bold);
|
||||
}
|
||||
|
||||
.bui-Heading[data-variant='title1'] {
|
||||
font-size: var(--bui-font-size-9);
|
||||
font-weight: var(--bui-font-weight-bold);
|
||||
}
|
||||
|
||||
.bui-Heading[data-variant='title2'] {
|
||||
font-size: var(--bui-font-size-8);
|
||||
font-weight: var(--bui-font-weight-bold);
|
||||
}
|
||||
|
||||
.bui-Heading[data-variant='title3'] {
|
||||
font-size: var(--bui-font-size-7);
|
||||
font-weight: var(--bui-font-weight-bold);
|
||||
}
|
||||
|
||||
.bui-Heading[data-variant='title4'] {
|
||||
font-size: var(--bui-font-size-6);
|
||||
font-weight: var(--bui-font-weight-bold);
|
||||
}
|
||||
|
||||
.bui-Heading[data-variant='title5'] {
|
||||
font-size: var(--bui-font-size-5);
|
||||
font-weight: var(--bui-font-weight-bold);
|
||||
}
|
||||
|
||||
.bui-Heading[data-color='primary'] {
|
||||
color: var(--bui-fg-primary);
|
||||
}
|
||||
|
||||
.bui-Heading[data-color='secondary'] {
|
||||
color: var(--bui-fg-secondary);
|
||||
}
|
||||
|
||||
.bui-Heading[data-truncate] {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { ElementType, ComponentPropsWithRef } from 'react';
|
||||
import type { Breakpoint } from '../../types';
|
||||
|
||||
/** @public */
|
||||
export type HeadingOwnProps = {
|
||||
as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
|
||||
variant?:
|
||||
| 'display'
|
||||
| 'title1'
|
||||
| 'title2'
|
||||
| 'title3'
|
||||
| 'title4'
|
||||
| 'title5'
|
||||
| Partial<
|
||||
Record<
|
||||
Breakpoint,
|
||||
'display' | 'title1' | 'title2' | 'title3' | 'title4' | 'title5'
|
||||
>
|
||||
>;
|
||||
color?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| Partial<Record<Breakpoint, 'primary' | 'secondary'>>;
|
||||
truncate?: boolean;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export type HeadingProps<T extends ElementType = 'h1'> = HeadingOwnProps &
|
||||
Omit<ComponentPropsWithRef<T>, keyof HeadingOwnProps>;
|
||||
@@ -40,7 +40,7 @@ type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
href: '/home',
|
||||
href: '/',
|
||||
children: 'Sign up for Backstage',
|
||||
},
|
||||
};
|
||||
@@ -72,133 +72,171 @@ export const AllVariants: Story = {
|
||||
};
|
||||
|
||||
export const AllColors: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
},
|
||||
render: args => (
|
||||
render: () => (
|
||||
<Flex gap="4" direction="column">
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="title-small"
|
||||
color="primary"
|
||||
{...args}
|
||||
children="I am primary"
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="title-small"
|
||||
color="secondary"
|
||||
{...args}
|
||||
children="I am secondary"
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="title-small"
|
||||
color="danger"
|
||||
children="I am danger"
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="title-small"
|
||||
color="warning"
|
||||
children="I am warning"
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="title-small"
|
||||
color="success"
|
||||
children="I am success"
|
||||
/>
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const AllWeights: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
},
|
||||
render: args => (
|
||||
render: () => (
|
||||
<Flex gap="4" direction="column">
|
||||
<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>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="title-large"
|
||||
weight="regular"
|
||||
children="A fox"
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="title-large"
|
||||
weight="bold"
|
||||
children="A turtle"
|
||||
/>
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="title-medium"
|
||||
weight="regular"
|
||||
children="A fox"
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="title-medium"
|
||||
weight="bold"
|
||||
children="A turtle"
|
||||
/>
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="title-small"
|
||||
weight="regular"
|
||||
children="A fox"
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="title-small"
|
||||
weight="bold"
|
||||
children="A turtle"
|
||||
/>
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="title-x-small"
|
||||
weight="regular"
|
||||
children="A fox"
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="title-x-small"
|
||||
weight="bold"
|
||||
children="A turtle"
|
||||
/>
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="body-large"
|
||||
weight="regular"
|
||||
children="A fox"
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="body-large"
|
||||
weight="bold"
|
||||
children="A turtle"
|
||||
/>
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="body-medium"
|
||||
weight="regular"
|
||||
children="A fox"
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="body-medium"
|
||||
weight="bold"
|
||||
children="A turtle"
|
||||
/>
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="body-small"
|
||||
weight="regular"
|
||||
children="A fox"
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="body-small"
|
||||
weight="bold"
|
||||
children="A turtle"
|
||||
/>
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="body-x-small"
|
||||
weight="regular"
|
||||
children="A fox"
|
||||
/>
|
||||
<Link
|
||||
href="https://ui.backstage.io"
|
||||
variant="body-x-small"
|
||||
weight="bold"
|
||||
children="A turtle"
|
||||
/>
|
||||
</Flex>
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const Truncate: Story = {
|
||||
args: {
|
||||
children:
|
||||
"A man looks at a painting in a museum and says, “Brothers and sisters I have none, but that man's father is my father's son.” Who is in the painting?",
|
||||
href: '/',
|
||||
truncate: true,
|
||||
style: { width: '480px' },
|
||||
},
|
||||
};
|
||||
|
||||
export const Responsive: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
|
||||
@@ -51,15 +51,18 @@ export const Link = forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => {
|
||||
variant = 'body',
|
||||
weight = 'regular',
|
||||
color = 'primary',
|
||||
truncate,
|
||||
href,
|
||||
...restProps
|
||||
} = props;
|
||||
|
||||
const { classNames, dataAttributes } = useStyles('Link', {
|
||||
variant,
|
||||
weight,
|
||||
color,
|
||||
});
|
||||
const { classNames: linkClassNames } = useStyles('Link');
|
||||
const { classNames: textClassNames, dataAttributes: textDataAttributes } =
|
||||
useStyles('Text', {
|
||||
variant,
|
||||
weight,
|
||||
color,
|
||||
});
|
||||
|
||||
const isExternal = isExternalLink(href);
|
||||
|
||||
@@ -68,9 +71,10 @@ export const Link = forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => {
|
||||
return (
|
||||
<AriaLink
|
||||
ref={ref}
|
||||
className={clsx(classNames.root, className)}
|
||||
className={clsx(textClassNames.root, linkClassNames.root, className)}
|
||||
data-truncate={truncate}
|
||||
href={href}
|
||||
{...dataAttributes}
|
||||
{...textDataAttributes}
|
||||
{...restProps}
|
||||
/>
|
||||
);
|
||||
@@ -81,9 +85,10 @@ export const Link = forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => {
|
||||
<RouterProvider navigate={navigate} useHref={useHref}>
|
||||
<AriaLink
|
||||
ref={ref}
|
||||
className={clsx(classNames.root, className)}
|
||||
className={clsx(textClassNames.root, linkClassNames.root, className)}
|
||||
data-truncate={truncate}
|
||||
{...textDataAttributes}
|
||||
href={href}
|
||||
{...dataAttributes}
|
||||
{...restProps}
|
||||
/>
|
||||
</RouterProvider>
|
||||
|
||||
@@ -20,72 +20,13 @@
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
text-decoration-line: none;
|
||||
display: inline-block;
|
||||
|
||||
&:hover {
|
||||
text-decoration-line: underline;
|
||||
text-decoration-style: solid;
|
||||
text-decoration-thickness: min(2px, max(1px, 0.05em));
|
||||
text-underline-offset: calc(0.025em + 2px);
|
||||
text-decoration-color: color-mix(
|
||||
in srgb,
|
||||
var(--bui-fg-link-hover) 30%,
|
||||
transparent
|
||||
);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -14,36 +14,22 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { Breakpoint } from '../../types';
|
||||
import type {
|
||||
Breakpoint,
|
||||
TextColors,
|
||||
TextColorStatus,
|
||||
TextVariants,
|
||||
TextWeights,
|
||||
} from '../../types';
|
||||
import type { LinkProps as AriaLinkProps } from 'react-aria-components';
|
||||
|
||||
/** @public */
|
||||
export interface LinkProps extends AriaLinkProps {
|
||||
variant?:
|
||||
| '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'>>;
|
||||
variant?: TextVariants | Partial<Record<Breakpoint, TextVariants>>;
|
||||
weight?: TextWeights | Partial<Record<Breakpoint, TextWeights>>;
|
||||
color?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| Partial<Record<Breakpoint, 'primary' | 'secondary'>>;
|
||||
| TextColors
|
||||
| TextColorStatus
|
||||
| Partial<Record<Breakpoint, TextColors | TextColorStatus>>;
|
||||
truncate?: boolean;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ const TableCellLink = forwardRef<HTMLDivElement, TableCellLinkProps>(
|
||||
>
|
||||
{title && <Link href={href}>{title}</Link>}
|
||||
{description && (
|
||||
<Text variant="body" color="secondary">
|
||||
<Text variant="body-medium" color="secondary">
|
||||
{description}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
@@ -54,7 +54,7 @@ const TableCellProfile = forwardRef<HTMLDivElement, TableCellProfileProps>(
|
||||
{name && to ? (
|
||||
<Link href={to}>{name}</Link>
|
||||
) : (
|
||||
<Text variant="body">{name}</Text>
|
||||
<Text variant="body-medium">{name}</Text>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -31,9 +31,9 @@ const TableCellText = forwardRef<HTMLDivElement, TableCellTextProps>(
|
||||
className={clsx(classNames.cellText, className)}
|
||||
{...props}
|
||||
>
|
||||
{title && <Text variant="body">{title}</Text>}
|
||||
{title && <Text variant="body-medium">{title}</Text>}
|
||||
{description && (
|
||||
<Text variant="body" color="secondary">
|
||||
<Text variant="body-medium" color="secondary">
|
||||
{description}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
@@ -33,7 +33,6 @@ export const Default: Story = {
|
||||
args: {
|
||||
children:
|
||||
"A man looks at a painting in a museum and says, “Brothers and sisters I have none, but that man's father is my father's son.” Who is in the painting?",
|
||||
style: { maxWidth: '600px' },
|
||||
},
|
||||
};
|
||||
|
||||
@@ -42,23 +41,54 @@ export const AllVariants: Story = {
|
||||
...Default.args,
|
||||
},
|
||||
render: args => (
|
||||
<Flex gap="4" direction="column">
|
||||
<Text variant="subtitle" {...args} />
|
||||
<Text variant="body" {...args} />
|
||||
<Text variant="caption" {...args} />
|
||||
<Text variant="label" {...args} />
|
||||
<Flex gap="6" direction="column">
|
||||
<Text {...args} variant="title-large" style={{ maxWidth: '1160px' }} />
|
||||
<Text {...args} variant="title-medium" style={{ maxWidth: '760px' }} />
|
||||
<Text {...args} variant="title-small" style={{ maxWidth: '580px' }} />
|
||||
<Text {...args} variant="title-x-small" style={{ maxWidth: '480px' }} />
|
||||
<Text {...args} variant="body-large" style={{ maxWidth: '380px' }} />
|
||||
<Text {...args} variant="body-medium" style={{ maxWidth: '320px' }} />
|
||||
<Text {...args} variant="body-small" style={{ maxWidth: '264px' }} />
|
||||
<Text {...args} variant="body-x-small" style={{ maxWidth: '224px' }} />
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const AllWeights: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
},
|
||||
render: args => (
|
||||
render: () => (
|
||||
<Flex gap="4" direction="column">
|
||||
<Text weight="regular" {...args} />
|
||||
<Text weight="bold" {...args} />
|
||||
<Flex>
|
||||
<Text variant="title-large" weight="regular" children="A fox" />
|
||||
<Text variant="title-large" weight="bold" children="A turtle" />
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Text variant="title-medium" weight="regular" children="A fox" />
|
||||
<Text variant="title-medium" weight="bold" children="A turtle" />
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Text variant="title-small" weight="regular" children="A fox" />
|
||||
<Text variant="title-small" weight="bold" children="A turtle" />
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Text variant="title-x-small" weight="regular" children="A fox" />
|
||||
<Text variant="title-x-small" weight="bold" children="A turtle" />
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Text variant="body-large" weight="regular" children="A fox" />
|
||||
<Text variant="body-large" weight="bold" children="A turtle" />
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Text variant="body-medium" weight="regular" children="A fox" />
|
||||
<Text variant="body-medium" weight="bold" children="A turtle" />
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Text variant="body-small" weight="regular" children="A fox" />
|
||||
<Text variant="body-small" weight="bold" children="A turtle" />
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Text variant="body-x-small" weight="regular" children="A fox" />
|
||||
<Text variant="body-x-small" weight="bold" children="A turtle" />
|
||||
</Flex>
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
@@ -69,11 +99,11 @@ export const AllColors: Story = {
|
||||
},
|
||||
render: args => (
|
||||
<Flex gap="4" direction="column">
|
||||
<Text color="primary" {...args} />
|
||||
<Text color="secondary" {...args} />
|
||||
<Text color="danger" {...args} />
|
||||
<Text color="warning" {...args} />
|
||||
<Text color="success" {...args} />
|
||||
<Text {...args} color="primary" children="I am primary" />
|
||||
<Text {...args} color="secondary" children="I am secondary" />
|
||||
<Text {...args} color="danger" children="I am danger" />
|
||||
<Text {...args} color="warning" children="I am warning" />
|
||||
<Text {...args} color="success" children="I am success" />
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
@@ -82,6 +112,8 @@ export const Truncate: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
truncate: true,
|
||||
as: 'p',
|
||||
style: { width: '480px' },
|
||||
},
|
||||
};
|
||||
|
||||
@@ -89,8 +121,8 @@ export const Responsive: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: {
|
||||
xs: 'label',
|
||||
md: 'body',
|
||||
xs: 'title-x-small',
|
||||
md: 'body-large',
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -111,7 +143,7 @@ export const WrappedInLink: Story = {
|
||||
export const CustomRender: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
as: 'span',
|
||||
as: 'label',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -119,25 +151,25 @@ export const Playground: Story = {
|
||||
render: () => (
|
||||
<Flex gap="4" direction="column">
|
||||
<Text>Subtitle</Text>
|
||||
<Text variant="subtitle" style={{ maxWidth: '600px' }}>
|
||||
<Text variant="title-large" style={{ maxWidth: '600px' }}>
|
||||
A man looks at a painting in a museum and says, “Brothers and sisters I
|
||||
have none, but that man's father is my father's son.” Who is
|
||||
in the painting?
|
||||
</Text>
|
||||
<Text>Body</Text>
|
||||
<Text variant="body" style={{ maxWidth: '600px' }}>
|
||||
<Text variant="body-medium" style={{ maxWidth: '600px' }}>
|
||||
A man looks at a painting in a museum and says, “Brothers and sisters I
|
||||
have none, but that man's father is my father's son.” Who is
|
||||
in the painting?
|
||||
</Text>
|
||||
<Text>Caption</Text>
|
||||
<Text variant="caption" style={{ maxWidth: '600px' }}>
|
||||
<Text variant="body-x-small" style={{ maxWidth: '600px' }}>
|
||||
A man looks at a painting in a museum and says, “Brothers and sisters I
|
||||
have none, but that man's father is my father's son.” Who is
|
||||
in the painting?
|
||||
</Text>
|
||||
<Text>Label</Text>
|
||||
<Text variant="label" style={{ maxWidth: '600px' }}>
|
||||
<Text variant="title-x-small" style={{ maxWidth: '600px' }}>
|
||||
A man looks at a painting in a museum and says, “Brothers and sisters I
|
||||
have none, but that man's father is my father's son.” Who is
|
||||
in the painting?
|
||||
|
||||
@@ -20,10 +20,10 @@ import type { ElementType } from 'react';
|
||||
import type { TextProps } from './types';
|
||||
import { useStyles } from '../../hooks/useStyles';
|
||||
|
||||
function TextComponent<T extends ElementType = 'p'>(
|
||||
function TextComponent<T extends ElementType = 'span'>(
|
||||
{
|
||||
as,
|
||||
variant = 'body',
|
||||
variant = 'body-medium',
|
||||
weight = 'regular',
|
||||
color = 'primary',
|
||||
className,
|
||||
@@ -33,7 +33,7 @@ function TextComponent<T extends ElementType = 'p'>(
|
||||
}: TextProps<T>,
|
||||
ref: React.Ref<any>,
|
||||
) {
|
||||
const Component = as || 'p';
|
||||
const Component = as || 'span';
|
||||
|
||||
const { classNames, dataAttributes } = useStyles('Text', {
|
||||
variant,
|
||||
@@ -46,6 +46,7 @@ function TextComponent<T extends ElementType = 'p'>(
|
||||
ref={ref}
|
||||
className={clsx(classNames.root, className)}
|
||||
data-truncate={truncate}
|
||||
data-as={as}
|
||||
{...dataAttributes}
|
||||
style={style}
|
||||
{...restProps}
|
||||
|
||||
@@ -20,22 +20,42 @@
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.bui-Text[data-variant='body'] {
|
||||
font-size: var(--bui-font-size-3);
|
||||
.bui-Text[data-variant='title-large'] {
|
||||
font-size: var(--bui-font-size-8);
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
.bui-Text[data-variant='subtitle'] {
|
||||
.bui-Text[data-variant='title-medium'] {
|
||||
font-size: var(--bui-font-size-7);
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
.bui-Text[data-variant='title-small'] {
|
||||
font-size: var(--bui-font-size-6);
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
.bui-Text[data-variant='title-x-small'] {
|
||||
font-size: var(--bui-font-size-5);
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
.bui-Text[data-variant='body-large'] {
|
||||
font-size: var(--bui-font-size-4);
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
.bui-Text[data-variant='caption'] {
|
||||
.bui-Text[data-variant='body-medium'] {
|
||||
font-size: var(--bui-font-size-3);
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
.bui-Text[data-variant='body-small'] {
|
||||
font-size: var(--bui-font-size-2);
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
.bui-Text[data-variant='label'] {
|
||||
.bui-Text[data-variant='body-x-small'] {
|
||||
font-size: var(--bui-font-size-1);
|
||||
line-height: 140%;
|
||||
}
|
||||
@@ -73,3 +93,11 @@
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.bui-Text[data-as='span'],
|
||||
.bui-Text[data-as='label'],
|
||||
.bui-Text[data-as='strong'],
|
||||
.bui-Text[data-as='em'],
|
||||
.bui-Text[data-as='small'] {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@@ -15,35 +15,40 @@
|
||||
*/
|
||||
|
||||
import type { ElementType, ComponentPropsWithRef } from 'react';
|
||||
import type { Breakpoint } from '../../types';
|
||||
import type {
|
||||
Breakpoint,
|
||||
TextVariants,
|
||||
TextWeights,
|
||||
TextColors,
|
||||
TextColorStatus,
|
||||
} from '../../types';
|
||||
|
||||
/** @public */
|
||||
export type TextOwnProps = {
|
||||
as?: 'p' | 'span' | 'label';
|
||||
variant?:
|
||||
| 'subtitle'
|
||||
| 'body'
|
||||
| 'caption'
|
||||
as?:
|
||||
| 'h1'
|
||||
| 'h2'
|
||||
| 'h3'
|
||||
| 'h4'
|
||||
| 'h5'
|
||||
| 'h6'
|
||||
| 'p'
|
||||
| 'span'
|
||||
| 'label'
|
||||
| Partial<Record<Breakpoint, 'subtitle' | 'body' | 'caption' | 'label'>>;
|
||||
weight?: 'regular' | 'bold' | Partial<Record<Breakpoint, 'regular' | 'bold'>>;
|
||||
| 'div'
|
||||
| 'strong'
|
||||
| 'em'
|
||||
| 'small'
|
||||
| 'legend';
|
||||
variant?: TextVariants | Partial<Record<Breakpoint, TextVariants>>;
|
||||
weight?: TextWeights | Partial<Record<Breakpoint, TextWeights>>;
|
||||
color?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| 'danger'
|
||||
| 'warning'
|
||||
| 'success'
|
||||
| Partial<
|
||||
Record<
|
||||
Breakpoint,
|
||||
'primary' | 'secondary' | 'danger' | 'warning' | 'success'
|
||||
>
|
||||
>;
|
||||
| TextColors
|
||||
| TextColorStatus
|
||||
| Partial<Record<Breakpoint, TextColors | TextColorStatus>>;
|
||||
truncate?: boolean;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export type TextProps<T extends ElementType = 'p'> = TextOwnProps &
|
||||
export type TextProps<T extends ElementType = 'span'> = TextOwnProps &
|
||||
Omit<ComponentPropsWithRef<T>, keyof TextOwnProps>;
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
@import '../components/Grid/styles.css';
|
||||
@import '../components/Header/Header.styles.css';
|
||||
@import '../components/HeaderPage/HeaderPage.styles.css';
|
||||
@import '../components/Heading/styles.css';
|
||||
@import '../components/Icon/styles.css';
|
||||
@import '../components/Link/styles.css';
|
||||
@import '../components/Menu/Menu.styles.css';
|
||||
|
||||
@@ -28,8 +28,6 @@ export * from './components/Box';
|
||||
export * from './components/Grid';
|
||||
export * from './components/Flex';
|
||||
export * from './components/Container';
|
||||
export * from './components/Text';
|
||||
export * from './components/Heading';
|
||||
|
||||
// UI components
|
||||
export * from './components/Avatar';
|
||||
@@ -47,6 +45,7 @@ export * from './components/Checkbox';
|
||||
export * from './components/RadioGroup';
|
||||
export * from './components/Table';
|
||||
export * from './components/Tabs';
|
||||
export * from './components/Text';
|
||||
export * from './components/TextField';
|
||||
export * from './components/Tooltip';
|
||||
export * from './components/Menu';
|
||||
|
||||
+20
-19
@@ -16,25 +16,6 @@
|
||||
|
||||
import { componentDefinitions } from './utils/componentDefinitions';
|
||||
|
||||
/** @public */
|
||||
export type AsProps =
|
||||
| 'div'
|
||||
| 'span'
|
||||
| 'p'
|
||||
| 'article'
|
||||
| 'section'
|
||||
| 'main'
|
||||
| 'nav'
|
||||
| 'aside'
|
||||
| 'ul'
|
||||
| 'ol'
|
||||
| 'li'
|
||||
| 'details'
|
||||
| 'summary'
|
||||
| 'dd'
|
||||
| 'dl'
|
||||
| 'dt';
|
||||
|
||||
/** @public */
|
||||
export type Breakpoint = 'initial' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
||||
|
||||
@@ -117,6 +98,26 @@ export interface SpaceProps {
|
||||
py?: Responsive<Space>;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export type TextVariants =
|
||||
| 'title-large'
|
||||
| 'title-medium'
|
||||
| 'title-small'
|
||||
| 'title-x-small'
|
||||
| 'body-large'
|
||||
| 'body-medium'
|
||||
| 'body-small'
|
||||
| 'body-x-small';
|
||||
|
||||
/** @public */
|
||||
export type TextColors = 'primary' | 'secondary';
|
||||
|
||||
/** @public */
|
||||
export type TextColorStatus = 'danger' | 'warning' | 'success';
|
||||
|
||||
/** @public */
|
||||
export type TextWeights = 'regular' | 'bold';
|
||||
|
||||
/** @public */
|
||||
export interface UtilityProps extends SpaceProps {
|
||||
alignItems?: Responsive<AlignItems>;
|
||||
|
||||
Reference in New Issue
Block a user