Improve the way we treat custom render on Text and Heading
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/canon': minor
|
||||
---
|
||||
|
||||
We are modifying the way we treat custom render using 'useRender()' under the hood from BaseUI.
|
||||
@@ -447,6 +447,26 @@
|
||||
font-weight: var(--canon-font-weight-bold);
|
||||
}
|
||||
|
||||
.canon-Heading[data-color="primary"] {
|
||||
color: var(--canon-fg-primary);
|
||||
}
|
||||
|
||||
.canon-Heading[data-color="secondary"] {
|
||||
color: var(--canon-fg-secondary);
|
||||
}
|
||||
|
||||
.canon-Heading[data-color="danger"] {
|
||||
color: var(--canon-fg-danger);
|
||||
}
|
||||
|
||||
.canon-Heading[data-color="warning"] {
|
||||
color: var(--canon-fg-warning);
|
||||
}
|
||||
|
||||
.canon-Heading[data-color="success"] {
|
||||
color: var(--canon-fg-success);
|
||||
}
|
||||
|
||||
.canon-Heading[data-truncate] {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
||||
@@ -36,6 +36,26 @@
|
||||
font-weight: var(--canon-font-weight-bold);
|
||||
}
|
||||
|
||||
.canon-Heading[data-color="primary"] {
|
||||
color: var(--canon-fg-primary);
|
||||
}
|
||||
|
||||
.canon-Heading[data-color="secondary"] {
|
||||
color: var(--canon-fg-secondary);
|
||||
}
|
||||
|
||||
.canon-Heading[data-color="danger"] {
|
||||
color: var(--canon-fg-danger);
|
||||
}
|
||||
|
||||
.canon-Heading[data-color="warning"] {
|
||||
color: var(--canon-fg-warning);
|
||||
}
|
||||
|
||||
.canon-Heading[data-color="success"] {
|
||||
color: var(--canon-fg-success);
|
||||
}
|
||||
|
||||
.canon-Heading[data-truncate] {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
||||
@@ -9671,6 +9671,26 @@
|
||||
font-weight: var(--canon-font-weight-bold);
|
||||
}
|
||||
|
||||
.canon-Heading[data-color="primary"] {
|
||||
color: var(--canon-fg-primary);
|
||||
}
|
||||
|
||||
.canon-Heading[data-color="secondary"] {
|
||||
color: var(--canon-fg-secondary);
|
||||
}
|
||||
|
||||
.canon-Heading[data-color="danger"] {
|
||||
color: var(--canon-fg-danger);
|
||||
}
|
||||
|
||||
.canon-Heading[data-color="warning"] {
|
||||
color: var(--canon-fg-warning);
|
||||
}
|
||||
|
||||
.canon-Heading[data-color="success"] {
|
||||
color: var(--canon-fg-success);
|
||||
}
|
||||
|
||||
.canon-Heading[data-truncate] {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
||||
@@ -613,18 +613,28 @@ export interface GridProps extends SpaceProps {
|
||||
|
||||
// @public (undocumented)
|
||||
export const Heading: ForwardRefExoticComponent<
|
||||
HeadingProps & RefAttributes<HTMLHeadingElement>
|
||||
Omit<HeadingProps, 'ref'> & RefAttributes<HTMLHeadingElement>
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface HeadingProps {
|
||||
// (undocumented)
|
||||
as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
|
||||
// (undocumented)
|
||||
children: React.ReactNode;
|
||||
export interface HeadingProps
|
||||
extends Omit<useRender.ComponentProps<'h1'>, 'color'> {
|
||||
// (undocumented)
|
||||
className?: string;
|
||||
// (undocumented)
|
||||
color?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| 'danger'
|
||||
| 'warning'
|
||||
| 'success'
|
||||
| Partial<
|
||||
Record<
|
||||
Breakpoint,
|
||||
'primary' | 'secondary' | 'danger' | 'warning' | 'success'
|
||||
>
|
||||
>;
|
||||
// (undocumented)
|
||||
style?: React.CSSProperties;
|
||||
// (undocumented)
|
||||
truncate?: boolean;
|
||||
@@ -1208,7 +1218,7 @@ export interface TableCellTextProps
|
||||
|
||||
// @public (undocumented)
|
||||
const Text_2: ForwardRefExoticComponent<
|
||||
TextProps & RefAttributes<HTMLParagraphElement>
|
||||
Omit<TextProps, 'ref'> & RefAttributes<HTMLParagraphElement>
|
||||
>;
|
||||
export { Text_2 as Text };
|
||||
|
||||
@@ -1231,9 +1241,8 @@ export interface TextFieldProps
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface TextProps {
|
||||
// (undocumented)
|
||||
children: ReactNode;
|
||||
export interface TextProps
|
||||
extends Omit<useRender.ComponentProps<'p'>, 'color'> {
|
||||
// (undocumented)
|
||||
className?: string;
|
||||
// (undocumented)
|
||||
|
||||
@@ -50,6 +50,21 @@ export const AllVariants: Story = {
|
||||
),
|
||||
};
|
||||
|
||||
export const AllColors: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
},
|
||||
render: args => (
|
||||
<Flex gap="4" direction="column">
|
||||
<Heading color="primary" {...args} />
|
||||
<Heading color="secondary" {...args} />
|
||||
<Heading color="danger" {...args} />
|
||||
<Heading color="warning" {...args} />
|
||||
<Heading color="success" {...args} />
|
||||
</Flex>
|
||||
),
|
||||
};
|
||||
|
||||
export const Truncate: Story = {
|
||||
args: {
|
||||
...Title1.args,
|
||||
@@ -67,13 +82,6 @@ export const Responsive: Story = {
|
||||
},
|
||||
};
|
||||
|
||||
export const CustomTag: Story = {
|
||||
args: {
|
||||
variant: 'title5',
|
||||
as: 'h2',
|
||||
},
|
||||
};
|
||||
|
||||
export const WrappedInLink: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
@@ -87,6 +95,13 @@ export const WrappedInLink: Story = {
|
||||
],
|
||||
};
|
||||
|
||||
export const CustomRender: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
render: <h4 />,
|
||||
},
|
||||
};
|
||||
|
||||
export const Playground: Story = {
|
||||
render: () => (
|
||||
<Flex direction="column" gap="4">
|
||||
|
||||
@@ -14,46 +14,41 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { forwardRef } from 'react';
|
||||
import { forwardRef, useRef } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import { useResponsiveValue } from '../../hooks/useResponsiveValue';
|
||||
|
||||
import { useRender } from '@base-ui-components/react/use-render';
|
||||
import type { HeadingProps } from './types';
|
||||
|
||||
/** @public */
|
||||
export const Heading = forwardRef<HTMLHeadingElement, HeadingProps>(
|
||||
(props, ref) => {
|
||||
const {
|
||||
children,
|
||||
variant = 'title1',
|
||||
as = 'h1',
|
||||
color = 'primary',
|
||||
truncate,
|
||||
className,
|
||||
render = <h1 />,
|
||||
...restProps
|
||||
} = props;
|
||||
|
||||
// Get the responsive value for the variant
|
||||
const responsiveVariant = useResponsiveValue(variant);
|
||||
const responsiveColor = useResponsiveValue(color);
|
||||
const internalRef = useRef<HTMLElement | null>(null);
|
||||
|
||||
// Determine the component to render based on the variant
|
||||
let Component = as;
|
||||
if (variant === 'title2') Component = 'h2';
|
||||
if (variant === 'title3') Component = 'h3';
|
||||
if (variant === 'title4') Component = 'h4';
|
||||
if (variant === 'title5') Component = 'h5';
|
||||
if (as) Component = as;
|
||||
const { renderElement } = useRender({
|
||||
render,
|
||||
props: {
|
||||
className: clsx('canon-Heading', className),
|
||||
['data-variant']: responsiveVariant,
|
||||
['data-color']: responsiveColor,
|
||||
['data-truncate']: truncate,
|
||||
...restProps,
|
||||
},
|
||||
refs: [ref, internalRef],
|
||||
});
|
||||
|
||||
return (
|
||||
<Component
|
||||
ref={ref}
|
||||
className={clsx('canon-Heading', className)}
|
||||
data-variant={responsiveVariant}
|
||||
data-truncate={truncate}
|
||||
{...restProps}
|
||||
>
|
||||
{children}
|
||||
</Component>
|
||||
);
|
||||
return renderElement();
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -52,6 +52,26 @@
|
||||
font-weight: var(--canon-font-weight-bold);
|
||||
}
|
||||
|
||||
.canon-Heading[data-color='primary'] {
|
||||
color: var(--canon-fg-primary);
|
||||
}
|
||||
|
||||
.canon-Heading[data-color='secondary'] {
|
||||
color: var(--canon-fg-secondary);
|
||||
}
|
||||
|
||||
.canon-Heading[data-color='danger'] {
|
||||
color: var(--canon-fg-danger);
|
||||
}
|
||||
|
||||
.canon-Heading[data-color='warning'] {
|
||||
color: var(--canon-fg-warning);
|
||||
}
|
||||
|
||||
.canon-Heading[data-color='success'] {
|
||||
color: var(--canon-fg-success);
|
||||
}
|
||||
|
||||
.canon-Heading[data-truncate] {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
@@ -15,10 +15,11 @@
|
||||
*/
|
||||
|
||||
import { Breakpoint } from '../../types';
|
||||
import type { useRender } from '@base-ui-components/react/use-render';
|
||||
|
||||
/** @public */
|
||||
export interface HeadingProps {
|
||||
children: React.ReactNode;
|
||||
export interface HeadingProps
|
||||
extends Omit<useRender.ComponentProps<'h1'>, 'color'> {
|
||||
variant?:
|
||||
| 'display'
|
||||
| 'title1'
|
||||
@@ -32,7 +33,18 @@ export interface HeadingProps {
|
||||
'display' | 'title1' | 'title2' | 'title3' | 'title4' | 'title5'
|
||||
>
|
||||
>;
|
||||
as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
|
||||
color?:
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| 'danger'
|
||||
| 'warning'
|
||||
| 'success'
|
||||
| Partial<
|
||||
Record<
|
||||
Breakpoint,
|
||||
'primary' | 'secondary' | 'danger' | 'warning' | 'success'
|
||||
>
|
||||
>;
|
||||
truncate?: boolean;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
|
||||
@@ -108,6 +108,13 @@ export const WrappedInLink: Story = {
|
||||
],
|
||||
};
|
||||
|
||||
export const CustomRender: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
render: <span />,
|
||||
},
|
||||
};
|
||||
|
||||
export const Playground: Story = {
|
||||
render: () => (
|
||||
<Flex gap="4" direction="column">
|
||||
|
||||
@@ -14,8 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { forwardRef } from 'react';
|
||||
import { forwardRef, useRef } from 'react';
|
||||
import { useResponsiveValue } from '../../hooks/useResponsiveValue';
|
||||
import { useRender } from '@base-ui-components/react/use-render';
|
||||
import clsx from 'clsx';
|
||||
|
||||
import type { TextProps } from './types';
|
||||
@@ -24,13 +25,12 @@ import type { TextProps } from './types';
|
||||
export const Text = forwardRef<HTMLParagraphElement, TextProps>(
|
||||
(props, ref) => {
|
||||
const {
|
||||
children,
|
||||
variant = 'body',
|
||||
weight = 'regular',
|
||||
color = 'primary',
|
||||
style,
|
||||
className,
|
||||
truncate,
|
||||
render = <p />,
|
||||
...restProps
|
||||
} = props;
|
||||
|
||||
@@ -38,21 +38,22 @@ export const Text = forwardRef<HTMLParagraphElement, TextProps>(
|
||||
const responsiveVariant = useResponsiveValue(variant);
|
||||
const responsiveWeight = useResponsiveValue(weight);
|
||||
const responsiveColor = useResponsiveValue(color);
|
||||
const internalRef = useRef<HTMLElement | null>(null);
|
||||
|
||||
return (
|
||||
<p
|
||||
ref={ref}
|
||||
className={clsx('canon-Text', className)}
|
||||
data-variant={responsiveVariant}
|
||||
data-weight={responsiveWeight}
|
||||
data-color={responsiveColor}
|
||||
data-truncate={truncate}
|
||||
style={style}
|
||||
{...restProps}
|
||||
>
|
||||
{children}
|
||||
</p>
|
||||
);
|
||||
const { renderElement } = useRender({
|
||||
render,
|
||||
props: {
|
||||
className: clsx('canon-Text', className),
|
||||
['data-variant']: responsiveVariant,
|
||||
['data-weight']: responsiveWeight,
|
||||
['data-color']: responsiveColor,
|
||||
['data-truncate']: truncate,
|
||||
...restProps,
|
||||
},
|
||||
refs: [ref, internalRef],
|
||||
});
|
||||
|
||||
return renderElement();
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -14,12 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { CSSProperties, ReactNode } from 'react';
|
||||
import type { CSSProperties } from 'react';
|
||||
import type { Breakpoint } from '../../types';
|
||||
import type { useRender } from '@base-ui-components/react/use-render';
|
||||
|
||||
/** @public */
|
||||
export interface TextProps {
|
||||
children: ReactNode;
|
||||
export interface TextProps
|
||||
extends Omit<useRender.ComponentProps<'p'>, 'color'> {
|
||||
variant?:
|
||||
| 'subtitle'
|
||||
| 'body'
|
||||
|
||||
Reference in New Issue
Block a user