1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-10-22 11:22:43 +02:00

convert text component to TS (#18329)

* convert text component to TS

* invisible character fix

* storybook fix

* fix types export

* update ButtonBase

* add typeof to objects in TextProps

* fix linting issues

* fix implicit conversion

* lint fix

* add deprecated Text back

* change box ref to any

* fix classnames issue

* account details to use deprecated text reference

* ref update

* make RefObject

* remove RefObject and go back to Ref

* react.ref change to box
This commit is contained in:
Garrett Bear 2023-04-03 10:42:37 -07:00 committed by GitHub
parent 8603a4b067
commit 01057f9824
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 556 additions and 137 deletions

View File

@ -177,7 +177,7 @@ For RTL language support use the `textDirection` prop.
</Canvas>
```jsx
import { ButtonBase, ICON_NAMES } from '../../component-library';
import { ButtonBase, ICON_NAMES, TextDirection } from '../../component-library';
<>
<ButtonBase
@ -189,7 +189,7 @@ import { ButtonBase, ICON_NAMES } from '../../component-library';
<ButtonBase
startIconName={ICON_NAMES.ADD_SQUARE}
endIconName={ICON_NAMES.ARROW_2_RIGHT}
textDirection={TEXT_DIRECTIONS.RIGHT_TO_LEFT}
textDirection={TextDirection.RightToLeft}
>
Button Demo
</ButtonBase>

View File

@ -7,7 +7,7 @@ import {
Size,
} from '../../../helpers/constants/design-system';
import Box from '../../ui/box/box';
import { ICON_NAMES, TEXT_DIRECTIONS } from '..';
import { ICON_NAMES, TextDirection } from '..';
import { BUTTON_BASE_SIZES } from './button-base.constants';
import { ButtonBase } from './button-base';
import README from './README.mdx';
@ -200,7 +200,7 @@ export const Rtl = (args) => (
{...args}
startIconName={ICON_NAMES.ADD_SQUARE}
endIconName={ICON_NAMES.ARROW_2_RIGHT}
textDirection={TEXT_DIRECTIONS.RIGHT_TO_LEFT}
textDirection={TextDirection.RightToLeft}
>
Button Demo
</ButtonBase>

View File

@ -28,7 +28,7 @@ export { Label } from './label';
export { PickerNetwork } from './picker-network';
export { Tag } from './tag';
export { TagUrl } from './tag-url';
export { Text, TEXT_DIRECTIONS, INVISIBLE_CHARACTER } from './text';
export { Text, ValidTag, TextDirection, InvisibleCharacter } from './text';
export { Input, INPUT_TYPES } from './input';
export { TextField, TEXT_FIELD_TYPES, TEXT_FIELD_SIZES } from './text-field';
export { TextFieldSearch } from './text-field-search';

View File

@ -59,7 +59,7 @@ import { TextVariant } from '../../../helpers/constants/design-system';
### Color
Use the `color` prop and the `TextColor` object from `./ui/helpers/constants/design-system.js` to change the color of the `Text` component.
Use the `color` prop and the `TextColor` enum from `./ui/helpers/constants/design-system.js` to change the color of the `Text` component.
<Canvas>
<Story id="components-componentlibrary-text--color-story" />
@ -267,6 +267,8 @@ import { Text } from '../../component-library';
Use the `as` prop to change the root html element of the `Text` component
You can also utilize the `ValidTag` enum from `./text.types` to ensure that you are using a valid html element
<Canvas>
<Story id="components-componentlibrary-text--as" />
</Canvas>
@ -313,22 +315,22 @@ Renders the html:
### Text Direction
Use the `textDirection` prop and the `TEXT_DIRECTIONS` object from `./text.constants.js` to change the text direction of `Text`
Use the `textDirection` prop and the `TextDirection` enum from `./text.types` to change the text direction of `Text`
<Canvas>
<Story id="components-componentlibrary-text--text-direction" />
<Story id="components-componentlibrary-text--text-direction-story" />
</Canvas>
```jsx
import { Text, TEXT_DIRECTIONS } from '../../component-library';
import { Text, TextDirection } from '../../component-library';
<Text textDirection={TEXT_DIRECTIONS.LEFT_TO_RIGHT}>
<Text textDirection={TextDirection.LeftToRight}>
This is left to right (ltr) for English and most languages
</Text>
<Text textDirection={TEXT_DIRECTIONS.RIGHT_TO_LEFT}>
<Text textDirection={TextDirection.RightToLeft}>
This is right to left (rtl) for use with other laguanges such as Arabic. This Enlgish example is incorrect usage.
</Text>
<Text textDirection={TEXT_DIRECTIONS.AUTO}>
<Text textDirection={TextDirection.Auto}>
Let the user agent decide with the auto option
</Text>
```

View File

@ -0,0 +1,56 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Text should render the Text with proper variant class name 1`] = `
<div>
<h1
class="box mm-text mm-text--display-md box--flex-direction-row box--color-text-default"
>
display-md
</h1>
<h2
class="box mm-text mm-text--heading-lg box--flex-direction-row box--color-text-default"
>
heading-lg
</h2>
<h3
class="box mm-text mm-text--heading-md box--flex-direction-row box--color-text-default"
>
heading-md
</h3>
<h4
class="box mm-text mm-text--heading-sm box--flex-direction-row box--color-text-default"
>
heading-sm
</h4>
<p
class="box mm-text mm-text--body-lg-medium box--flex-direction-row box--color-text-default"
>
body-lg-medium
</p>
<p
class="box mm-text mm-text--body-md box--flex-direction-row box--color-text-default"
>
body-md
</p>
<p
class="box mm-text mm-text--body-md-bold box--flex-direction-row box--color-text-default"
>
body-md-bold
</p>
<p
class="box mm-text mm-text--body-sm box--flex-direction-row box--color-text-default"
>
body-sm
</p>
<p
class="box mm-text mm-text--body-sm-bold box--flex-direction-row box--color-text-default"
>
body-sm-bold
</p>
<p
class="box mm-text mm-text--body-xs box--flex-direction-row box--color-text-default"
>
body-xs
</p>
</div>
`;

View File

@ -1,7 +1,7 @@
import React from 'react';
import classnames from 'classnames';
import PropTypes from 'prop-types';
import Box from '../../ui/box';
import Box from '../../../ui/box';
import {
FONT_WEIGHT,
FONT_STYLE,
@ -10,7 +10,7 @@ import {
TEXT_TRANSFORM,
OVERFLOW_WRAP,
TextColor,
} from '../../../helpers/constants/design-system';
} from '../../../../helpers/constants/design-system';
import { TEXT_DIRECTIONS } from './text.constants';
export const ValidTags = [

View File

@ -9,7 +9,7 @@ import {
TEXT_TRANSFORM,
TextVariant,
Color,
} from '../../../helpers/constants/design-system';
} from '../../../../helpers/constants/design-system';
import { Text, TEXT_DIRECTIONS } from '.';
describe('Text', () => {

View File

@ -0,0 +1,3 @@
export { Text } from './text';
export { ValidTag, TextDirection, InvisibleCharacter } from './text.types';
export type { TextProps } from './text.types';

View File

@ -1,4 +1,5 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import {
DISPLAY,
BackgroundColor,
@ -16,115 +17,20 @@ import {
} from '../../../helpers/constants/design-system';
import Box from '../../ui/box';
import { ValidTags, Text } from './text';
import { TEXT_DIRECTIONS } from './text.constants';
import README from './README.mdx';
const sizeKnobOptions = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
const marginSizeKnobOptions = [...sizeKnobOptions, 'auto'];
import { Text } from './text';
import { ValidTag, TextDirection } from './text.types';
export default {
title: 'Components/ComponentLibrary/Text',
component: Text,
parameters: {
docs: {
page: README,
},
},
argTypes: {
variant: {
control: { type: 'select' },
options: Object.values(TextVariant),
},
color: {
control: { type: 'select' },
options: Object.values(TextColor),
},
fontWeight: {
control: { type: 'select' },
options: Object.values(FONT_WEIGHT),
},
fontStyle: {
control: { type: 'select' },
options: Object.values(FONT_STYLE),
},
textTransform: {
control: { type: 'select' },
options: Object.values(TEXT_TRANSFORM),
},
align: {
control: { type: 'select' },
options: Object.values(TEXT_ALIGN),
},
overflowWrap: {
control: { type: 'select' },
options: Object.values(OVERFLOW_WRAP),
},
ellipsis: {
control: { type: 'boolean' },
},
as: {
control: { type: 'select' },
options: ValidTags,
},
textDirection: {
control: { type: 'select' },
options: Object.values(TEXT_DIRECTIONS),
},
className: {
control: { type: 'text' },
},
children: {
control: { type: 'text' },
},
display: {
options: Object.values(DISPLAY),
control: 'select',
table: { category: 'box props' },
},
backgroundColor: {
options: Object.values(BackgroundColor),
control: 'select',
table: { category: 'box props' },
},
borderColor: {
options: Object.values(BorderColor),
control: 'select',
table: { category: 'box props' },
},
padding: {
options: sizeKnobOptions,
control: 'select',
table: { category: 'box props' },
},
margin: {
options: marginSizeKnobOptions,
control: 'select',
table: { category: 'box props' },
},
marginTop: {
options: marginSizeKnobOptions,
control: 'select',
table: { category: 'box props' },
},
marginRight: {
options: marginSizeKnobOptions,
control: 'select',
table: { category: 'box props' },
},
marginBottom: {
options: marginSizeKnobOptions,
control: 'select',
table: { category: 'box props' },
},
marginLeft: {
options: marginSizeKnobOptions,
control: 'select',
table: { category: 'box props' },
},
},
};
} as ComponentMeta<typeof Text>;
function renderBackgroundColor(color) {
let bgColor;
@ -164,14 +70,18 @@ function renderBackgroundColor(color) {
return bgColor;
}
export const DefaultStory = (args) => <Text {...args}>{args.children}</Text>;
const Template: ComponentStory<typeof Text> = (args) => (
<Text {...args}>{args.children}</Text>
);
DefaultStory.storyName = 'Default';
export const DefaultStory = Template.bind({});
DefaultStory.args = {
children: 'The quick orange fox jumped over the lazy dog.',
};
DefaultStory.storyName = 'Default';
export const Variant = (args) => (
<>
{Object.values(TextVariant).map((variant) => (
@ -182,7 +92,7 @@ export const Variant = (args) => (
</>
);
export const ColorStory = (args) => {
export const ColorStory: ComponentStory<typeof Text> = (args) => {
// Index of last valid color in TextColor array
return (
<>
@ -203,7 +113,7 @@ export const ColorStory = (args) => {
};
ColorStory.storyName = 'Color';
export const FontWeight = (args) => (
export const FontWeight: ComponentStory<typeof Text> = (args) => (
<>
{Object.values(FONT_WEIGHT).map((weight) => (
<Text {...args} fontWeight={weight} key={weight}>
@ -213,7 +123,7 @@ export const FontWeight = (args) => (
</>
);
export const FontStyle = (args) => (
export const FontStyle: ComponentStory<typeof Text> = (args) => (
<>
{Object.values(FONT_STYLE).map((style) => (
<Text {...args} fontStyle={style} key={style}>
@ -223,7 +133,7 @@ export const FontStyle = (args) => (
</>
);
export const TextTransform = (args) => (
export const TextTransform: ComponentStory<typeof Text> = (args) => (
<>
{Object.values(TEXT_TRANSFORM).map((transform) => (
<Text {...args} textTransform={transform} key={transform}>
@ -233,7 +143,7 @@ export const TextTransform = (args) => (
</>
);
export const TextAlign = (args) => (
export const TextAlign: ComponentStory<typeof Text> = (args) => (
<>
{Object.values(TEXT_ALIGN).map((align) => (
<Text {...args} textAlign={align} key={align}>
@ -243,11 +153,11 @@ export const TextAlign = (args) => (
</>
);
export const OverflowWrap = (args) => (
export const OverflowWrap: ComponentStory<typeof Text> = (args) => (
<Box
borderColor={BorderColor.warningDefault}
display={DISPLAY.BLOCK}
width={FRACTIONS.ONE_THIRD}
style={{ width: 200 }}
>
<Text {...args} overflowWrap={OVERFLOW_WRAP.NORMAL}>
{OVERFLOW_WRAP.NORMAL}: 0x39013f961c378f02c2b82a6e1d31e9812786fd9d
@ -258,7 +168,7 @@ export const OverflowWrap = (args) => (
</Box>
);
export const Ellipsis = (args) => (
export const Ellipsis: ComponentStory<typeof Text> = (args) => (
<Box
borderColor={BorderColor.primaryDefault}
display={DISPLAY.BLOCK}
@ -273,16 +183,23 @@ export const Ellipsis = (args) => (
</Box>
);
export const As = (args) => (
export const As: ComponentStory<typeof Text> = (args) => (
<>
{ValidTags.map((tag) => {
if (tag === 'input') {
return <Text key={tag} {...args} as={tag} placeholder={tag} />;
{Object.keys(ValidTag).map((tag) => {
if (ValidTag[tag] === ValidTag.Input) {
return (
<Text
key={ValidTag[tag]}
{...args}
as={ValidTag[tag]}
placeholder={ValidTag[tag]}
/>
);
}
return (
<div key={tag}>
<Text {...args} as={tag}>
{tag}
<div key={ValidTag[tag]}>
<Text {...args} as={ValidTag[tag]}>
{ValidTag[tag]}
</Text>
</div>
);
@ -290,21 +207,21 @@ export const As = (args) => (
</>
);
export const TextDirection = (args) => (
export const TextDirectionStory: ComponentStory<typeof Text> = (args) => (
<Box
style={{ maxWidth: 300 }}
display={DISPLAY.FLEX}
flexDirection={FLEX_DIRECTION.COLUMN}
gap={4}
>
<Text {...args} textDirection={TEXT_DIRECTIONS.LEFT_TO_RIGHT}>
<Text {...args} textDirection={TextDirection.LeftToRight}>
This is left to right (ltr) for English and most languages
</Text>
<Text {...args} textDirection={TEXT_DIRECTIONS.RIGHT_TO_LEFT}>
<Text {...args} textDirection={TextDirection.RightToLeft}>
This is right to left (rtl) for use with other laguanges such as Arabic.
This Enlgish example is incorrect usage.
</Text>
<Text {...args} textDirection={TEXT_DIRECTIONS.AUTO}>
<Text {...args} textDirection={TextDirection.Auto}>
Let the user agent decide with the auto option
</Text>
</Box>

View File

@ -0,0 +1,243 @@
import * as React from 'react';
import { render } from '@testing-library/react';
import {
FONT_STYLE,
FONT_WEIGHT,
OVERFLOW_WRAP,
TEXT_ALIGN,
TextColor,
TEXT_TRANSFORM,
TextVariant,
Color,
} from '../../../helpers/constants/design-system';
import { TextDirection, ValidTag } from './text.types';
import { Text } from '.';
describe('Text', () => {
it('should render the Text without crashing', () => {
const { getByText } = render(<Text>Test type</Text>);
expect(getByText('Test type')).toBeDefined();
});
it('should render the Text with correct html elements', () => {
const { getByText, container } = render(
<>
<Text as={ValidTag.P}>p</Text>
<Text as={ValidTag.H1}>h1</Text>
<Text as={ValidTag.H2}>h2</Text>
<Text as={ValidTag.H3}>h3</Text>
<Text as={ValidTag.H4}>h4</Text>
<Text as={ValidTag.H5}>h5</Text>
<Text as={ValidTag.H6}>h6</Text>
<Text as={ValidTag.Span}>span</Text>
<Text as={ValidTag.Strong}>strong</Text>
<Text as={ValidTag.Em}>em</Text>
<Text as={ValidTag.Li}>li</Text>
<Text as={ValidTag.Div}>div</Text>
<Text as={ValidTag.Dt}>dt</Text>
<Text as={ValidTag.Dd}>dd</Text>
</>,
);
expect(container.querySelector('p')).toBeDefined();
expect(getByText('p')).toBeDefined();
expect(container.querySelector('h1')).toBeDefined();
expect(getByText('h1')).toBeDefined();
expect(container.querySelector('h2')).toBeDefined();
expect(getByText('h2')).toBeDefined();
expect(container.querySelector('h3')).toBeDefined();
expect(getByText('h3')).toBeDefined();
expect(container.querySelector('h4')).toBeDefined();
expect(getByText('h4')).toBeDefined();
expect(container.querySelector('h5')).toBeDefined();
expect(getByText('h5')).toBeDefined();
expect(container.querySelector('h6')).toBeDefined();
expect(getByText('h6')).toBeDefined();
expect(container.querySelector('span')).toBeDefined();
expect(getByText('span')).toBeDefined();
expect(container.querySelector('strong')).toBeDefined();
expect(getByText('strong')).toBeDefined();
expect(container.querySelector('em')).toBeDefined();
expect(getByText('em')).toBeDefined();
expect(container.querySelector('li')).toBeDefined();
expect(getByText('li')).toBeDefined();
expect(container.querySelector('div')).toBeDefined();
expect(getByText('div')).toBeDefined();
expect(container.querySelector('dt')).toBeDefined();
expect(getByText('dt')).toBeDefined();
expect(container.querySelector('dd')).toBeDefined();
expect(getByText('dd')).toBeDefined();
});
it('should render the Text with proper variant class name', () => {
const { getByText, container } = render(
<>
<Text variant={TextVariant.displayMd}>display-md</Text>
<Text variant={TextVariant.headingLg}>heading-lg</Text>
<Text variant={TextVariant.headingMd}>heading-md</Text>
<Text variant={TextVariant.headingSm}>heading-sm</Text>
<Text variant={TextVariant.bodyLgMedium}>body-lg-medium</Text>
<Text variant={TextVariant.bodyMd}>body-md</Text>
<Text variant={TextVariant.bodyMdBold}>body-md-bold</Text>
<Text variant={TextVariant.bodySm}>body-sm</Text>
<Text variant={TextVariant.bodySmBold}>body-sm-bold</Text>
<Text variant={TextVariant.bodyXs}>body-xs</Text>
</>,
);
expect(getByText('display-md')).toHaveClass('mm-text--display-md');
expect(getByText('heading-lg')).toHaveClass('mm-text--heading-lg');
expect(getByText('heading-md')).toHaveClass('mm-text--heading-md');
expect(getByText('heading-sm')).toHaveClass('mm-text--heading-sm');
expect(getByText('body-lg-medium')).toHaveClass('mm-text--body-lg-medium');
expect(getByText('body-md')).toHaveClass('mm-text--body-md');
expect(getByText('body-md-bold')).toHaveClass('mm-text--body-md-bold');
expect(getByText('body-sm')).toHaveClass('mm-text--body-sm');
expect(getByText('body-sm-bold')).toHaveClass('mm-text--body-sm-bold');
expect(getByText('body-xs')).toHaveClass('mm-text--body-xs');
expect(container).toMatchSnapshot();
});
it('should render the Text with proper font weight class name', () => {
const { getByText } = render(
<>
<Text fontWeight={FONT_WEIGHT.BOLD}>bold</Text>
<Text fontWeight={FONT_WEIGHT.MEDIUM}>medium</Text>
<Text fontWeight={FONT_WEIGHT.NORMAL}>normal</Text>
</>,
);
expect(getByText('bold')).toHaveClass('mm-text--font-weight-bold');
expect(getByText('medium')).toHaveClass('mm-text--font-weight-medium');
expect(getByText('normal')).toHaveClass('mm-text--font-weight-normal');
});
it('should render the Text with proper text color class name', () => {
const { getByText } = render(
<>
<Text color={TextColor.textDefault}>text-default</Text>
<Text color={TextColor.textAlternative}>text-alternative</Text>
<Text color={TextColor.textMuted}>text-muted</Text>
<Text color={Color.overlayInverse}>overlay-inverse</Text>
<Text color={TextColor.primaryDefault}>primary-default</Text>
<Text color={TextColor.primaryInverse}>primary-inverse</Text>
<Text color={TextColor.errorDefault}>error-default</Text>
<Text color={TextColor.errorInverse}>error-inverse</Text>
<Text color={TextColor.successDefault}>success-default</Text>
<Text color={TextColor.successInverse}>success-inverse</Text>
<Text color={TextColor.warningInverse}>warning-inverse</Text>
<Text color={TextColor.infoDefault}>info-default</Text>
<Text color={TextColor.infoInverse}>info-inverse</Text>
</>,
);
expect(getByText('text-default')).toHaveClass('box--color-text-default');
expect(getByText('text-alternative')).toHaveClass(
'box--color-text-alternative',
);
expect(getByText('text-muted')).toHaveClass('box--color-text-muted');
expect(getByText('primary-default')).toHaveClass(
'box--color-primary-default',
);
expect(getByText('primary-inverse')).toHaveClass(
'box--color-primary-inverse',
);
expect(getByText('error-default')).toHaveClass('box--color-error-default');
expect(getByText('error-inverse')).toHaveClass('box--color-error-inverse');
expect(getByText('success-default')).toHaveClass(
'box--color-success-default',
);
expect(getByText('success-inverse')).toHaveClass(
'box--color-success-inverse',
);
expect(getByText('warning-inverse')).toHaveClass(
'box--color-warning-inverse',
);
expect(getByText('info-default')).toHaveClass('box--color-info-default');
expect(getByText('info-inverse')).toHaveClass('box--color-info-inverse');
});
it('should render the Text with proper font style class name', () => {
const { getByText } = render(
<>
<Text fontStyle={FONT_STYLE.ITALIC}>italic</Text>
<Text fontStyle={FONT_STYLE.NORMAL}>normal</Text>
</>,
);
expect(getByText('italic')).toHaveClass('mm-text--font-style-italic');
expect(getByText('normal')).toHaveClass('mm-text--font-style-normal');
});
it('should render the Text with proper text align class name', () => {
const { getByText } = render(
<>
<Text textAlign={TEXT_ALIGN.LEFT}>left</Text>
<Text textAlign={TEXT_ALIGN.CENTER}>center</Text>
<Text textAlign={TEXT_ALIGN.RIGHT}>right</Text>
<Text textAlign={TEXT_ALIGN.JUSTIFY}>justify</Text>
<Text textAlign={TEXT_ALIGN.END}>end</Text>
</>,
);
expect(getByText('left')).toHaveClass('mm-text--text-align-left');
expect(getByText('center')).toHaveClass('mm-text--text-align-center');
expect(getByText('right')).toHaveClass('mm-text--text-align-right');
expect(getByText('justify')).toHaveClass('mm-text--text-align-justify');
expect(getByText('end')).toHaveClass('mm-text--text-align-end');
});
it('should render the Text with proper overflow wrap class name', () => {
const { getByText } = render(
<>
<Text overflowWrap={OVERFLOW_WRAP.BREAK_WORD}>break-word</Text>
<Text overflowWrap={OVERFLOW_WRAP.NORMAL}>normal</Text>
</>,
);
expect(getByText('break-word')).toHaveClass(
'mm-text--overflow-wrap-break-word',
);
expect(getByText('normal')).toHaveClass('mm-text--overflow-wrap-normal');
});
it('should render the Text with proper ellipsis class name', () => {
const { getByText } = render(
<>
<Text ellipsis>ellipsis</Text>
</>,
);
expect(getByText('ellipsis')).toHaveClass('mm-text--ellipsis');
});
it('should render the Text with proper text transform class name', () => {
const { getByText } = render(
<>
<Text textTransform={TEXT_TRANSFORM.UPPERCASE}>uppercase</Text>
<Text textTransform={TEXT_TRANSFORM.LOWERCASE}>lowercase</Text>
<Text textTransform={TEXT_TRANSFORM.CAPITALIZE}>capitalize</Text>
</>,
);
expect(getByText('uppercase')).toHaveClass(
'mm-text--text-transform-uppercase',
);
expect(getByText('lowercase')).toHaveClass(
'mm-text--text-transform-lowercase',
);
expect(getByText('capitalize')).toHaveClass(
'mm-text--text-transform-capitalize',
);
});
it('should accept a ref prop that is passed down to the html element', () => {
const mockRef = jest.fn();
render(<Text ref={mockRef} />);
expect(mockRef).toHaveBeenCalledTimes(1);
});
it('should render the Text with proper direction', () => {
const { getByText } = render(
<>
<Text textDirection={TextDirection.Auto}>auto</Text>
<Text textDirection={TextDirection.LeftToRight}>ltr</Text>
<Text textDirection={TextDirection.RightToLeft}>rtl</Text>
</>,
);
expect(getByText('auto')).toHaveAttribute('dir', 'auto');
expect(getByText('ltr')).toHaveAttribute('dir', 'ltr');
expect(getByText('rtl')).toHaveAttribute('dir', 'rtl');
});
});

View File

@ -0,0 +1,84 @@
import React, { forwardRef, Ref } from 'react';
import classnames from 'classnames';
import Box from '../../ui/box';
import {
FONT_WEIGHT,
TextVariant,
TextColor,
} from '../../../helpers/constants/design-system';
import { TextProps, ValidTag } from './text.types';
const getTextElementDefault = (variant: TextVariant) => {
switch (variant) {
case TextVariant.displayMd:
return ValidTag.H1;
case TextVariant.headingLg:
return ValidTag.H2;
case TextVariant.headingMd:
return ValidTag.H3;
case TextVariant.headingSm:
return ValidTag.H4;
case TextVariant.inherit:
return ValidTag.Span;
// TextVariant.bodyLgMedium, TextVariant.bodyMd, TextVariant.bodyMdBold, TextVariant.bodySm, TextVariant.bodySmBold, TextVariant.bodyXs use default 'p' tag
default:
return ValidTag.P;
}
};
export const Text = forwardRef(function Text(
{
variant = TextVariant.bodyMd,
color = TextColor.textDefault,
fontWeight,
fontStyle,
textTransform,
textAlign,
textDirection,
overflowWrap,
ellipsis,
as,
className = '',
children,
...props
}: TextProps,
ref: Ref<HTMLElement>,
) {
// Check if as is set otherwise set a default tag based on variant
const Tag = as ?? getTextElementDefault(variant);
let strongTagFontWeight;
if (Tag === 'strong') {
strongTagFontWeight = FONT_WEIGHT.BOLD;
}
const computedClassName = classnames(
'mm-text',
className,
`mm-text--${variant}`,
{
[`mm-text--font-weight-${strongTagFontWeight || fontWeight}`]: Boolean(
strongTagFontWeight || fontWeight,
),
[`mm-text--font-style-${String(fontStyle)}`]: Boolean(fontStyle),
[`mm-text--ellipsis`]: Boolean(ellipsis),
[`mm-text--text-transform-${String(textTransform)}`]:
Boolean(textTransform),
[`mm-text--text-align-${String(textAlign)}`]: Boolean(textAlign),
[`mm-text--overflow-wrap-${String(overflowWrap)}`]: Boolean(overflowWrap),
},
);
return (
<Box
className={classnames(computedClassName)}
as={Tag}
dir={textDirection}
color={color}
ref={ref}
{...props}
>
{children}
</Box>
);
});

View File

@ -0,0 +1,114 @@
import React from 'react';
import type { BoxProps } from '../../ui/box/box.d';
import {
FONT_WEIGHT,
FONT_STYLE,
TextVariant,
TEXT_ALIGN,
TEXT_TRANSFORM,
OVERFLOW_WRAP,
TextColor,
Color,
} from '../../../helpers/constants/design-system';
export enum TextDirection {
LeftToRight = 'ltr',
RightToLeft = 'rtl',
Auto = 'auto',
}
/**
* The InvisibleCharacter is a very useful tool if you want to make sure a line of text
* takes up vertical space even if it's empty.
*/
export const InvisibleCharacter = '\u200B';
export enum ValidTag {
Dd = 'dd',
Div = 'div',
Dt = 'dt',
Em = 'em',
H1 = 'h1',
H2 = 'h2',
H3 = 'h3',
H4 = 'h4',
H5 = 'h5',
H6 = 'h6',
Li = 'li',
P = 'p',
Span = 'span',
Strong = 'strong',
Ul = 'ul',
Label = 'label',
Input = 'input',
}
export interface TextProps extends BoxProps {
/**
* The text content of the Text component
*/
children: React.ReactNode;
/**
* The variation of font styles including sizes and weights of the Text component
* Possible values:
* `displayMd` large screen: 48px / small screen: 32px,
* `headingLg` large screen: 32px / small screen: 24px,
* `headingMd` large screen: 24px / small screen: 18px,
* `headingSm` large screen: 18px / small screen: 16px,
* `bodyLgMedium` large screen: 18px / small screen: 16px,
* `bodyMd` large screen: 16px / small screen: 14px,
* `bodyMdBold` large screen: 16px / small screen: 14px,
* `bodySm` large screen: 14px / small screen: 12px,
* `bodySmBold` large screen: 14px / small screen: 12px,
* `bodyXs` large screen: 12px / small screen: 10px,
* `inherit`
*/
variant?: TextVariant;
/**
* The color of the Text component Should use the COLOR object from
* ./ui/helpers/constants/design-system.js
*/
color?: TextColor | Color;
/**
* The font-weight of the Text component. Should use the FONT_WEIGHT object from
* ./ui/helpers/constants/design-system.js
*/
fontWeight?: keyof typeof FONT_WEIGHT;
/**
* The font-style of the Text component. Should use the FONT_STYLE object from
* ./ui/helpers/constants/design-system.js
*/
fontStyle?: keyof typeof FONT_STYLE;
/**
* The textTransform of the Text component. Should use the TEXT_TRANSFORM object from
* ./ui/helpers/constants/design-system.js
*/
textTransform?: keyof typeof TEXT_TRANSFORM;
/**
* The text-align of the Text component. Should use the TEXT_ALIGN object from
* ./ui/helpers/constants/design-system.js
*/
textAlign?: keyof typeof TEXT_ALIGN;
/**
* Change the dir (direction) global attribute of text to support the direction a language is written
* Possible values: `LEFT_TO_RIGHT` (default), `RIGHT_TO_LEFT`, `AUTO` (user agent decides)
*/
textDirection?: TextDirection;
/**
* The overflow-wrap of the Text component. Should use the OVERFLOW_WRAP object from
* ./ui/helpers/constants/design-system.js
*/
overflowWrap?: keyof typeof OVERFLOW_WRAP;
/**
* Used for long strings that can be cut off...
*/
ellipsis?: boolean;
/**
* Changes the root html element tag of the Text component.
*/
as?: ValidTag;
/**
* Additional className to assign the Text component
*/
className?: string;
}

View File

@ -337,7 +337,7 @@ export interface BoxProps extends React.HTMLAttributes<HTMLElement> {
/**
* The ref of the Box component.
*/
ref?: React.RefObject<HTMLElement>;
ref?: React.Ref<HTMLElement>;
}
declare const Box: React.FC<BoxProps>;

View File

@ -1,4 +1,4 @@
import { INVISIBLE_CHARACTER } from '../../components/component-library';
import { INVISIBLE_CHARACTER } from '../../components/component-library/text/deprecated';
export function getAccountNameErrorMessage(
accounts,