UI-14395: typography v2 (#15408)
UI-14395: change Typography v2 to Text UI-14395: upgrade design tokens UI-14395: add classname testing UI-14395: update text colors, update font family name to match token, update text storybook boxprops UI-14395: add text transform docs lint fixfeature/default_network_editable
parent
119a5a4dc4
commit
d25f9cf4da
Binary file not shown.
@ -0,0 +1,302 @@ |
|||||||
|
import { Story, Canvas, ArgsTable } from '@storybook/addon-docs'; |
||||||
|
import ActionableMessage from '../../ui/actionable-message'; |
||||||
|
import { Text } from './text'; |
||||||
|
|
||||||
|
# Text |
||||||
|
|
||||||
|
> This Text (fka Typography) component has breaking changes in variant options and the line heights associated to each variant. |
||||||
|
|
||||||
|
Good typography improves readability, legibility and hierarchy of information. |
||||||
|
|
||||||
|
<Canvas> |
||||||
|
<Story id="ui-components-component-library-text-text-stories-js--default-story" /> |
||||||
|
</Canvas> |
||||||
|
|
||||||
|
## Props |
||||||
|
|
||||||
|
<ArgsTable of={Text} /> |
||||||
|
|
||||||
|
### Variant |
||||||
|
|
||||||
|
Use the `variant` prop and the `TEXT` object from `./ui/helpers/constants/design-system.js` to change the font size of the component. |
||||||
|
|
||||||
|
<Canvas> |
||||||
|
<Story id="ui-components-component-library-text-text-stories-js--variant" /> |
||||||
|
</Canvas> |
||||||
|
|
||||||
|
```jsx |
||||||
|
import { Text } from '../../ui/component-library/text'; |
||||||
|
import { TEXT } from '../../../helpers/constants/design-system'; |
||||||
|
|
||||||
|
<Text variant={TEXT.DISPLAY_MD}>display-md</Text> |
||||||
|
<Text variant={TEXT.HEADING_LG}>heading-lg</Text> |
||||||
|
<Text variant={TEXT.HEADING_MD}>heading-md</Text> |
||||||
|
<Text variant={TEXT.HEADING_SM}>heading-sm</Text> |
||||||
|
<Text variant={TEXT.BODY_MD}>body-md</Text> |
||||||
|
<Text variant={TEXT.BODY_SM}>body-sm</Text> |
||||||
|
<Text variant={TEXT.BODY_XS}>body-xs</Text> |
||||||
|
``` |
||||||
|
|
||||||
|
### Color |
||||||
|
|
||||||
|
Use the `color` prop and the `COLORS` object from `./ui/helpers/constants/design-system.js` to change the color of the `Text` component. |
||||||
|
|
||||||
|
<Canvas> |
||||||
|
<Story id="ui-components-component-library-text-text-stories-js--color" /> |
||||||
|
</Canvas> |
||||||
|
|
||||||
|
```jsx |
||||||
|
import { Text } from '../../ui/component-library/text'; |
||||||
|
import { COLORS } from '../../../helpers/constants/design-system'; |
||||||
|
|
||||||
|
<Text color={COLORS.TEXT_DEFAULT}> |
||||||
|
text-default |
||||||
|
</Text> |
||||||
|
<Text color={COLORS.TEXT_ALTERNATIVE}> |
||||||
|
text-alternative |
||||||
|
</Text> |
||||||
|
<Text color={COLORS.TEXT_MUTED}> |
||||||
|
text-muted |
||||||
|
</Text> |
||||||
|
<Text color={COLORS.OVERLAY_INVERSE} backgroundColor:{COLORS.OVERLAY_DEFAULT}> |
||||||
|
overlay-inverse |
||||||
|
</Text> |
||||||
|
<Text color={COLORS.PRIMARY_DEFAULT}> |
||||||
|
primary-default |
||||||
|
</Text> |
||||||
|
<Text color={COLORS.PRIMARY_INVERSE} backgroundColor:{COLORS.PRIMARY_DEFAULT}> |
||||||
|
primary-inverse |
||||||
|
</Text> |
||||||
|
<Text color={COLORS.ERROR_DEFAULT}> |
||||||
|
error-default |
||||||
|
</Text> |
||||||
|
<Text color={COLORS.ERROR_INVERSE} backgroundColor:{COLORS.ERROR_DEFAULT}> |
||||||
|
error-inverse |
||||||
|
</Text> |
||||||
|
<Text color={COLORS.SUCCESS_DEFAULT}> |
||||||
|
success-default |
||||||
|
</Text> |
||||||
|
<Text color={COLORS.SUCCESS_INVERSE} backgroundColor:{COLORS.SUCCESS_DEFAULT}> |
||||||
|
success-inverse |
||||||
|
</Text> |
||||||
|
<Text color={COLORS.WARNING_INVERSE} backgroundColor:{COLORS.WARNING_DEFAULT}> |
||||||
|
warning-inverse |
||||||
|
</Text> |
||||||
|
<Text color={COLORS.INFO_DEFAULT}> |
||||||
|
info-default |
||||||
|
</Text> |
||||||
|
<Text color={COLORS.INFO_INVERSE} backgroundColor:{COLORS.INFO_DEFAULT}> |
||||||
|
info-inverse |
||||||
|
</Text> |
||||||
|
``` |
||||||
|
|
||||||
|
### Font Weight |
||||||
|
|
||||||
|
Use the `fontWeight` prop and the `FONT_WEIGHT` object from `./ui/helpers/constants/design-system.js` to change the font weight of the `Text` component. There are 3 font weights: |
||||||
|
|
||||||
|
- `FONT_WEIGHT.NORMAL` = `normal` || `400` |
||||||
|
- `FONT_WEIGHT.MEDIUM` = `medium` || `500` |
||||||
|
- `FONT_WEIGHT.BOLD` = `bold` || `700` |
||||||
|
|
||||||
|
<Canvas> |
||||||
|
<Story id="ui-components-component-library-text-text-stories-js--font-weight" /> |
||||||
|
</Canvas> |
||||||
|
|
||||||
|
```jsx |
||||||
|
import { Text } from '../../ui/component-library/text'; |
||||||
|
import { FONT_WEIGHT } from '../../../helpers/constants/design-system'; |
||||||
|
|
||||||
|
<Text fontWeight={FONT_WEIGHT.NORMAL}> |
||||||
|
normal |
||||||
|
</Text> |
||||||
|
<Text fontWeight={FONT_WEIGHT.MEDIUM}> |
||||||
|
medium |
||||||
|
</Text> |
||||||
|
<Text fontWeight={FONT_WEIGHT.BOLD}> |
||||||
|
bold |
||||||
|
</Text> |
||||||
|
``` |
||||||
|
|
||||||
|
### Font Style |
||||||
|
|
||||||
|
Use the `fontStyle` prop and the `FONT_STYLE` object from `./ui/helpers/constants/design-system.js` to change the font style of the `Text` component. There are 2 font styles: |
||||||
|
|
||||||
|
- `FONT_STYLE.NORMAL` |
||||||
|
- `FONT_STYLE.ITALIC` |
||||||
|
|
||||||
|
<Canvas> |
||||||
|
<Story id="ui-components-component-library-text-text-stories-js--font-style" /> |
||||||
|
</Canvas> |
||||||
|
|
||||||
|
```jsx |
||||||
|
import { Text } from '../../ui/component-library/text'; |
||||||
|
import { FONT_STYLE } from '../../../helpers/constants/design-system'; |
||||||
|
|
||||||
|
<Text fontStyle={FONT_STYLE.NORMAL}> |
||||||
|
normal |
||||||
|
</Text> |
||||||
|
<Text fontStyle={FONT_STYLE.ITALIC}> |
||||||
|
bold |
||||||
|
</Text> |
||||||
|
``` |
||||||
|
|
||||||
|
### Text Transform |
||||||
|
|
||||||
|
Use the `textTransform` prop and the `TEXT_TRANSFORM` object from `./ui/helpers/constants/design-system.js` to change the text alignment of the `Text` component |
||||||
|
|
||||||
|
<Canvas> |
||||||
|
<Story id="ui-components-component-library-text-text-stories-js--text-transform" /> |
||||||
|
</Canvas> |
||||||
|
|
||||||
|
```jsx |
||||||
|
import { Text } from '../../ui/component-library/text'; |
||||||
|
import { TEXT_TRANSFORM } from '../../../helpers/constants/design-system'; |
||||||
|
|
||||||
|
<Text textAlign={TEXT_TRANSFORM.UPPERCASE}> |
||||||
|
uppercase |
||||||
|
</Text> |
||||||
|
<Text textAlign={TEXT_TRANSFORM.LOWERCASE}> |
||||||
|
lowercase |
||||||
|
</Text> |
||||||
|
<Text textAlign={TEXT_TRANSFORM.CAPITALIZE}> |
||||||
|
capitalize |
||||||
|
</Text> |
||||||
|
``` |
||||||
|
|
||||||
|
### Text Align |
||||||
|
|
||||||
|
Use the `textAlign` prop and the `TEXT_ALIGN` object from `./ui/helpers/constants/design-system.js` to change the text alignment of the `Text` component |
||||||
|
|
||||||
|
<Canvas> |
||||||
|
<Story id="ui-components-component-library-text-text-stories-js--text-align" /> |
||||||
|
</Canvas> |
||||||
|
|
||||||
|
```jsx |
||||||
|
import { Text } from '../../ui/component-library/text'; |
||||||
|
import { TEXT_ALIGN } from '../../../helpers/constants/design-system'; |
||||||
|
|
||||||
|
<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> |
||||||
|
``` |
||||||
|
|
||||||
|
### Overflow Wrap |
||||||
|
|
||||||
|
Use the `overflowWrap` prop and the `OVERFLOW_WRAP` object from `./ui/helpers/constants/design-system.js` to change the overflow wrap of the `Text` component |
||||||
|
|
||||||
|
<Canvas> |
||||||
|
<Story id="ui-components-component-library-text-text-stories-js--overflow-wrap" /> |
||||||
|
</Canvas> |
||||||
|
|
||||||
|
```jsx |
||||||
|
import { Text } from '../../ui/component-library/text'; |
||||||
|
import { OVERFLOW_WRAP } from '../../../helpers/constants/design-system'; |
||||||
|
|
||||||
|
<div |
||||||
|
style={{ |
||||||
|
width: 250, |
||||||
|
border: '1px solid var(--color-error-default)', |
||||||
|
display: 'block', |
||||||
|
}} |
||||||
|
> |
||||||
|
<Text overflowWrap={OVERFLOW_WRAP.NORMAL}> |
||||||
|
{OVERFLOW_WRAP.NORMAL}: 0x39013f961c378f02c2b82a6e1d31e9812786fd9d |
||||||
|
</Text> |
||||||
|
<Text overflowWrap={OVERFLOW_WRAP.BREAK_WORD}> |
||||||
|
{OVERFLOW_WRAP.BREAK_WORD}: 0x39013f961c378f02c2b82a6e1d31e9812786fd9d |
||||||
|
</Text> |
||||||
|
</div>; |
||||||
|
``` |
||||||
|
|
||||||
|
### Ellipsis |
||||||
|
|
||||||
|
Use the boolean `ellipsis` prop to change the if the `Text` component to have an ellipsis. |
||||||
|
|
||||||
|
<Canvas> |
||||||
|
<Story id="ui-components-component-library-text-text-stories-js--ellipsis" /> |
||||||
|
</Canvas> |
||||||
|
|
||||||
|
```jsx |
||||||
|
import { Text } from '../../ui/component-library/text'; |
||||||
|
|
||||||
|
<div |
||||||
|
style={{ |
||||||
|
width: 250, |
||||||
|
border: '1px solid var(--color-error-default)', |
||||||
|
display: 'block', |
||||||
|
}} |
||||||
|
> |
||||||
|
<Text ellipsis>Ellipsis: 0x39013f961c378f02c2b82a6e1d31e9812786fd9d</Text> |
||||||
|
<Text>No Ellipsis: 0x39013f961c378f02c2b82a6e1d31e9812786fd9d</Text> |
||||||
|
</div>; |
||||||
|
``` |
||||||
|
|
||||||
|
### As |
||||||
|
|
||||||
|
Use the `as` prop to change the root html element of the `Text` component |
||||||
|
|
||||||
|
<Canvas> |
||||||
|
<Story id="ui-components-component-library-text-text-stories-js--as" /> |
||||||
|
</Canvas> |
||||||
|
|
||||||
|
```jsx |
||||||
|
import { Text } from '../../ui/component-library/text'; |
||||||
|
|
||||||
|
<Text as="dd">dd</Text> |
||||||
|
<Text as="div">div</Text> |
||||||
|
<Text as="dt">dt</Text> |
||||||
|
<Text as="em">em</Text> |
||||||
|
<Text as="h1">h1</Text> |
||||||
|
<Text as="h2">h2</Text> |
||||||
|
<Text as="h3">h3</Text> |
||||||
|
<Text as="h4">h4</Text> |
||||||
|
<Text as="h5">h5</Text> |
||||||
|
<Text as="h6">h6</Text> |
||||||
|
<Text as="li">li</Text> |
||||||
|
<Text as="p">p</Text> |
||||||
|
<Text as="span">span</Text> |
||||||
|
<Text as="strong">strong</Text> |
||||||
|
``` |
||||||
|
|
||||||
|
Renders the html: |
||||||
|
|
||||||
|
```html |
||||||
|
<dd>dd</dd> |
||||||
|
<div>div</div> |
||||||
|
<dt>dt</dt> |
||||||
|
<em>em</em> |
||||||
|
<h1>h1</h1> |
||||||
|
<h2>h2</h2> |
||||||
|
<h3>h3</h3> |
||||||
|
<h4>h4</h4> |
||||||
|
<h5>h5</h5> |
||||||
|
<h6>h6</h6> |
||||||
|
<li>li</li> |
||||||
|
<p>p</p> |
||||||
|
<span>span</span> |
||||||
|
<strong>strong</strong> |
||||||
|
``` |
||||||
|
|
||||||
|
### Box Props |
||||||
|
|
||||||
|
Use any valid box props [Box](/?path=/story/ui-components-ui-box-box-stories-js--default-story) component props to the Text component. |
||||||
|
|
||||||
|
### Class Name |
||||||
|
|
||||||
|
Adds an additional class to the `Text` component |
||||||
|
|
||||||
|
### Children |
||||||
|
|
||||||
|
The text content of the `Text` component |
@ -0,0 +1 @@ |
|||||||
|
export { Text } from './text'; |
@ -0,0 +1,145 @@ |
|||||||
|
import React from 'react'; |
||||||
|
import classnames from 'classnames'; |
||||||
|
import PropTypes from 'prop-types'; |
||||||
|
import Box from '../../ui/box'; |
||||||
|
import { |
||||||
|
FONT_WEIGHT, |
||||||
|
FONT_STYLE, |
||||||
|
TEXT, |
||||||
|
TEXT_ALIGN, |
||||||
|
TEXT_TRANSFORM, |
||||||
|
OVERFLOW_WRAP, |
||||||
|
TEXT_COLORS, |
||||||
|
} from '../../../helpers/constants/design-system'; |
||||||
|
|
||||||
|
export const ValidTags = [ |
||||||
|
'dd', |
||||||
|
'div', |
||||||
|
'dt', |
||||||
|
'em', |
||||||
|
'h1', |
||||||
|
'h2', |
||||||
|
'h3', |
||||||
|
'h4', |
||||||
|
'h5', |
||||||
|
'h6', |
||||||
|
'li', |
||||||
|
'p', |
||||||
|
'span', |
||||||
|
'strong', |
||||||
|
'ul', |
||||||
|
'label', |
||||||
|
]; |
||||||
|
|
||||||
|
export const Text = ({ |
||||||
|
variant = TEXT.BODY_MD, |
||||||
|
color = TEXT_COLORS.TEXT_DEFAULT, |
||||||
|
fontWeight, |
||||||
|
fontStyle, |
||||||
|
textTransform, |
||||||
|
textAlign, |
||||||
|
overflowWrap, |
||||||
|
ellipsis, |
||||||
|
as, |
||||||
|
className, |
||||||
|
children, |
||||||
|
...props |
||||||
|
}) => { |
||||||
|
let Tag = as ?? variant; |
||||||
|
let strongTagFontWeight; |
||||||
|
|
||||||
|
if (Tag === 'strong') { |
||||||
|
strongTagFontWeight = FONT_WEIGHT.BOLD; |
||||||
|
} |
||||||
|
|
||||||
|
const computedClassName = classnames( |
||||||
|
'text', |
||||||
|
className, |
||||||
|
`text--${variant}`, |
||||||
|
(strongTagFontWeight || fontWeight) && |
||||||
|
`text--font-weight-${strongTagFontWeight || fontWeight}`, |
||||||
|
{ |
||||||
|
[`text--font-style-${fontStyle}`]: Boolean(fontStyle), |
||||||
|
[`text--ellipsis`]: Boolean(ellipsis), |
||||||
|
[`text--text-transform-${textTransform}`]: Boolean(textTransform), |
||||||
|
[`text--text-align-${textAlign}`]: Boolean(textAlign), |
||||||
|
[`text--color-${color}`]: Boolean(color), |
||||||
|
[`text--overflow-wrap-${overflowWrap}`]: Boolean(overflowWrap), |
||||||
|
}, |
||||||
|
); |
||||||
|
|
||||||
|
// // Set a default tag based on variant
|
||||||
|
const splitTag = Tag.split('-')[0]; |
||||||
|
if (splitTag === 'body') { |
||||||
|
Tag = 'p'; |
||||||
|
} else if (splitTag === 'heading') { |
||||||
|
Tag = 'h2'; |
||||||
|
} else if (splitTag === 'display') { |
||||||
|
Tag = 'h1'; |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<Box {...props} className={classnames(computedClassName)} as={Tag}> |
||||||
|
{children} |
||||||
|
</Box> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
Text.propTypes = { |
||||||
|
/** |
||||||
|
* The variation of font styles including sizes and weights of the Text component (display, heading, body) |
||||||
|
*/ |
||||||
|
variant: PropTypes.oneOf(Object.values(TEXT)), |
||||||
|
/** |
||||||
|
* The color of the Text component Should use the COLOR object from |
||||||
|
* ./ui/helpers/constants/design-system.js |
||||||
|
*/ |
||||||
|
color: PropTypes.oneOf(Object.values(TEXT_COLORS)), |
||||||
|
/** |
||||||
|
* The font-weight of the Text component. Should use the FONT_WEIGHT object from |
||||||
|
* ./ui/helpers/constants/design-system.js |
||||||
|
*/ |
||||||
|
fontWeight: PropTypes.oneOf(Object.values(FONT_WEIGHT)), |
||||||
|
/** |
||||||
|
* The font-style of the Text component. Should use the FONT_STYLE object from |
||||||
|
* ./ui/helpers/constants/design-system.js |
||||||
|
*/ |
||||||
|
fontStyle: PropTypes.oneOf(Object.values(FONT_STYLE)), |
||||||
|
/** |
||||||
|
* The textTransform of the Text component. Should use the TEXT_TRANSFORM object from |
||||||
|
* ./ui/helpers/constants/design-system.js |
||||||
|
*/ |
||||||
|
textTransform: PropTypes.oneOf(Object.values(TEXT_TRANSFORM)), |
||||||
|
/** |
||||||
|
* The text-align of the Text component. Should use the TEXT_ALIGN object from |
||||||
|
* ./ui/helpers/constants/design-system.js |
||||||
|
*/ |
||||||
|
textAlign: PropTypes.oneOf(Object.values(TEXT_ALIGN)), |
||||||
|
/** |
||||||
|
* The overflow-wrap of the Text component. Should use the OVERFLOW_WRAP object from |
||||||
|
* ./ui/helpers/constants/design-system.js |
||||||
|
*/ |
||||||
|
overflowWrap: PropTypes.oneOf(Object.values(OVERFLOW_WRAP)), |
||||||
|
/** |
||||||
|
* Used for long strings that can be cut off... |
||||||
|
*/ |
||||||
|
ellipsis: PropTypes.bool, |
||||||
|
/** |
||||||
|
* Changes the root html element tag of the Text component. |
||||||
|
*/ |
||||||
|
as: PropTypes.oneOf(ValidTags), |
||||||
|
/** |
||||||
|
* Additional className to assign the Text component |
||||||
|
*/ |
||||||
|
className: PropTypes.string, |
||||||
|
/** |
||||||
|
* The text content of the Text component |
||||||
|
*/ |
||||||
|
children: PropTypes.node.isRequired, |
||||||
|
/** |
||||||
|
* Text component accepts all Box component props |
||||||
|
*/ |
||||||
|
...Box.propTypes, |
||||||
|
}; |
||||||
|
|
||||||
|
export default Text; |
@ -0,0 +1,104 @@ |
|||||||
|
@use "design-system"; |
||||||
|
@use "sass:map"; |
||||||
|
|
||||||
|
$text-variants: ( |
||||||
|
display: ("md"), |
||||||
|
heading: ( "sm", "md", "lg"), |
||||||
|
body: ("xs", "sm", "sm-bold", "md", "md-bold", "lg-medium"), |
||||||
|
); |
||||||
|
|
||||||
|
// Variable output mixin |
||||||
|
// screen size, type, size |
||||||
|
|
||||||
|
@mixin textVariables($type, $size) { |
||||||
|
font-family: var(--typography-s-#{$type}-#{$size}-font-family); |
||||||
|
font-weight: var(--typography-s-#{$type}-#{$size}-font-weight); |
||||||
|
font-size: var(--typography-s-#{$type}-#{$size}-font-size); |
||||||
|
line-height: var(--typography-s-#{$type}-#{$size}-line-height); |
||||||
|
letter-spacing: var(--typography-s-#{$type}-#{$size}-letter-spacing); |
||||||
|
|
||||||
|
@include screen-md-min { |
||||||
|
font-family: var(--typography-l-#{$type}-#{$size}-font-family); |
||||||
|
font-weight: var(--typography-l-#{$type}-#{$size}-font-weight); |
||||||
|
font-size: var(--typography-l-#{$type}-#{$size}-font-size); |
||||||
|
line-height: var(--typography-l-#{$type}-#{$size}-line-height); |
||||||
|
letter-spacing: var(--typography-l-#{$type}-#{$size}-letter-spacing); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.text { |
||||||
|
// Set default styles |
||||||
|
color: var(--color-text-default); |
||||||
|
font-family: var(----font-family-sans); |
||||||
|
|
||||||
|
@each $type, $size-options in $text-variants { |
||||||
|
&--#{$type} { |
||||||
|
// Sets a default |
||||||
|
@include textVariables($type, "md"); |
||||||
|
// Generates all the size options |
||||||
|
@each $size in $size-options { |
||||||
|
&-#{$size} { |
||||||
|
@include textVariables($type, $size); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@each $variant, $color in $color-map { |
||||||
|
&--color-#{$variant} { |
||||||
|
color: var($color); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@each $weight in $font-weight { |
||||||
|
&--font-weight-#{$weight} { |
||||||
|
@if $weight == "medium" { |
||||||
|
font-weight: var(--font-weight-medium); |
||||||
|
} |
||||||
|
|
||||||
|
@else { |
||||||
|
font-weight: $weight; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@each $style in $font-style { |
||||||
|
&--font-style-#{$style} { |
||||||
|
font-style: $style; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@each $alignment in $text-align { |
||||||
|
&--text-align-#{$alignment} { |
||||||
|
text-align: $alignment; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@each $overflow in $overflow-wrap { |
||||||
|
&--overflow-wrap-#{$overflow} { |
||||||
|
overflow-wrap: $overflow; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&--ellipsis { |
||||||
|
text-overflow: ellipsis; |
||||||
|
white-space: nowrap; |
||||||
|
overflow: hidden; |
||||||
|
} |
||||||
|
|
||||||
|
&--text-transform-uppercase { |
||||||
|
text-transform: uppercase; |
||||||
|
} |
||||||
|
|
||||||
|
&--text-transform-lowercase { |
||||||
|
text-transform: lowercase; |
||||||
|
} |
||||||
|
|
||||||
|
&--text-transform-capitalize { |
||||||
|
text-transform: capitalize; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
@ -0,0 +1,270 @@ |
|||||||
|
import React from 'react'; |
||||||
|
import { |
||||||
|
COLORS, |
||||||
|
DISPLAY, |
||||||
|
BACKGROUND_COLORS, |
||||||
|
BORDER_COLORS, |
||||||
|
FONT_WEIGHT, |
||||||
|
FONT_STYLE, |
||||||
|
TEXT_COLORS, |
||||||
|
TEXT_ALIGN, |
||||||
|
TEXT, |
||||||
|
OVERFLOW_WRAP, |
||||||
|
TEXT_TRANSFORM, |
||||||
|
FRACTIONS, |
||||||
|
} from '../../../helpers/constants/design-system'; |
||||||
|
|
||||||
|
import Box from '../../ui/box'; |
||||||
|
import { ValidTags, Text } from './text'; |
||||||
|
|
||||||
|
import README from './README.mdx'; |
||||||
|
|
||||||
|
const sizeKnobOptions = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; |
||||||
|
const marginSizeKnobOptions = [...sizeKnobOptions, 'auto']; |
||||||
|
|
||||||
|
export default { |
||||||
|
title: 'Components/ComponentLibrary/Text', |
||||||
|
id: __filename, |
||||||
|
parameters: { |
||||||
|
docs: { |
||||||
|
page: README, |
||||||
|
}, |
||||||
|
}, |
||||||
|
argTypes: { |
||||||
|
variant: { |
||||||
|
control: { type: 'select' }, |
||||||
|
options: Object.values(TEXT), |
||||||
|
}, |
||||||
|
color: { |
||||||
|
control: { type: 'select' }, |
||||||
|
options: Object.values(TEXT_COLORS), |
||||||
|
}, |
||||||
|
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, |
||||||
|
}, |
||||||
|
className: { |
||||||
|
control: { type: 'text' }, |
||||||
|
}, |
||||||
|
children: { |
||||||
|
control: { type: 'text' }, |
||||||
|
}, |
||||||
|
display: { |
||||||
|
options: Object.values(DISPLAY), |
||||||
|
control: 'select', |
||||||
|
table: { category: 'box props' }, |
||||||
|
}, |
||||||
|
backgroundColor: { |
||||||
|
options: Object.values(BACKGROUND_COLORS), |
||||||
|
control: 'select', |
||||||
|
table: { category: 'box props' }, |
||||||
|
}, |
||||||
|
borderColor: { |
||||||
|
options: Object.values(BORDER_COLORS), |
||||||
|
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' }, |
||||||
|
}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
|
||||||
|
function renderBackgroundColor(color) { |
||||||
|
let bgColor; |
||||||
|
switch (color) { |
||||||
|
case COLORS.OVERLAY_INVERSE: |
||||||
|
bgColor = COLORS.OVERLAY_DEFAULT; |
||||||
|
break; |
||||||
|
case COLORS.PRIMARY_INVERSE: |
||||||
|
bgColor = COLORS.PRIMARY_DEFAULT; |
||||||
|
break; |
||||||
|
case COLORS.ERROR_INVERSE: |
||||||
|
bgColor = COLORS.ERROR_DEFAULT; |
||||||
|
break; |
||||||
|
case COLORS.WARNING_INVERSE: |
||||||
|
bgColor = COLORS.WARNING_DEFAULT; |
||||||
|
break; |
||||||
|
case COLORS.SUCCESS_INVERSE: |
||||||
|
bgColor = COLORS.SUCCESS_DEFAULT; |
||||||
|
break; |
||||||
|
case COLORS.INFO_INVERSE: |
||||||
|
bgColor = COLORS.INFO_DEFAULT; |
||||||
|
break; |
||||||
|
default: |
||||||
|
bgColor = null; |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
return bgColor; |
||||||
|
} |
||||||
|
|
||||||
|
export const DefaultStory = (args) => <Text {...args}>{args.children}</Text>; |
||||||
|
|
||||||
|
DefaultStory.storyName = 'Default'; |
||||||
|
|
||||||
|
DefaultStory.args = { |
||||||
|
children: 'The quick orange fox jumped over the lazy dog.', |
||||||
|
}; |
||||||
|
|
||||||
|
export const Variant = (args) => ( |
||||||
|
<> |
||||||
|
{Object.values(TEXT).map((variant) => ( |
||||||
|
<Text {...args} variant={variant} key={variant}> |
||||||
|
{args.children || variant} |
||||||
|
</Text> |
||||||
|
))} |
||||||
|
</> |
||||||
|
); |
||||||
|
|
||||||
|
export const Color = (args) => { |
||||||
|
// Index of last valid color in TEXT_COLORS array
|
||||||
|
return ( |
||||||
|
<> |
||||||
|
{Object.values(TEXT_COLORS).map((color) => { |
||||||
|
return ( |
||||||
|
<Text |
||||||
|
{...args} |
||||||
|
backgroundColor={renderBackgroundColor(color)} |
||||||
|
color={color} |
||||||
|
key={color} |
||||||
|
> |
||||||
|
{color} |
||||||
|
</Text> |
||||||
|
); |
||||||
|
})} |
||||||
|
</> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
export const FontWeight = (args) => ( |
||||||
|
<> |
||||||
|
{Object.values(FONT_WEIGHT).map((weight) => ( |
||||||
|
<Text {...args} fontWeight={weight} key={weight}> |
||||||
|
{weight} |
||||||
|
</Text> |
||||||
|
))} |
||||||
|
</> |
||||||
|
); |
||||||
|
|
||||||
|
export const FontStyle = (args) => ( |
||||||
|
<> |
||||||
|
{Object.values(FONT_STYLE).map((style) => ( |
||||||
|
<Text {...args} fontStyle={style} key={style}> |
||||||
|
{style} |
||||||
|
</Text> |
||||||
|
))} |
||||||
|
</> |
||||||
|
); |
||||||
|
|
||||||
|
export const TextTransform = (args) => ( |
||||||
|
<> |
||||||
|
{Object.values(TEXT_TRANSFORM).map((transform) => ( |
||||||
|
<Text {...args} textTransform={transform} key={transform}> |
||||||
|
{transform} |
||||||
|
</Text> |
||||||
|
))} |
||||||
|
</> |
||||||
|
); |
||||||
|
|
||||||
|
export const TextAlign = (args) => ( |
||||||
|
<> |
||||||
|
{Object.values(TEXT_ALIGN).map((align) => ( |
||||||
|
<Text {...args} textAlign={align} key={align}> |
||||||
|
{align} |
||||||
|
</Text> |
||||||
|
))} |
||||||
|
</> |
||||||
|
); |
||||||
|
|
||||||
|
export const OverflowWrap = (args) => ( |
||||||
|
<Box |
||||||
|
borderColor={COLORS.WARNING_DEFAULT} |
||||||
|
display={DISPLAY.BLOCK} |
||||||
|
width={FRACTIONS.ONE_THIRD} |
||||||
|
> |
||||||
|
<Text {...args} overflowWrap={OVERFLOW_WRAP.NORMAL}> |
||||||
|
{OVERFLOW_WRAP.NORMAL}: 0x39013f961c378f02c2b82a6e1d31e9812786fd9d |
||||||
|
</Text> |
||||||
|
<Text {...args} overflowWrap={OVERFLOW_WRAP.BREAK_WORD}> |
||||||
|
{OVERFLOW_WRAP.BREAK_WORD}: 0x39013f961c378f02c2b82a6e1d31e9812786fd9d |
||||||
|
</Text> |
||||||
|
</Box> |
||||||
|
); |
||||||
|
|
||||||
|
export const Ellipsis = (args) => ( |
||||||
|
<Box |
||||||
|
borderColor={COLORS.PRIMARY_DEFAULT} |
||||||
|
display={DISPLAY.BLOCK} |
||||||
|
width={FRACTIONS.ONE_THIRD} |
||||||
|
> |
||||||
|
<Text {...args} ellipsis> |
||||||
|
Ellipsis: 0x39013f961c378f02c2b82a6e1d31e9812786fd9d |
||||||
|
</Text> |
||||||
|
<Text {...args}> |
||||||
|
No Ellipsis: 0x39013f961c378f02c2b82a6e1d31e9812786fd9d |
||||||
|
</Text> |
||||||
|
</Box> |
||||||
|
); |
||||||
|
|
||||||
|
export const As = (args) => ( |
||||||
|
<> |
||||||
|
{Object.values(ValidTags).map((tag) => ( |
||||||
|
<div key={tag}> |
||||||
|
<Text {...args} as={tag}> |
||||||
|
{tag} |
||||||
|
</Text> |
||||||
|
</div> |
||||||
|
))} |
||||||
|
</> |
||||||
|
); |
@ -0,0 +1,221 @@ |
|||||||
|
import * as React from 'react'; |
||||||
|
import { render } from '@testing-library/react'; |
||||||
|
import { |
||||||
|
COLORS, |
||||||
|
FONT_STYLE, |
||||||
|
FONT_WEIGHT, |
||||||
|
OVERFLOW_WRAP, |
||||||
|
TEXT, |
||||||
|
TEXT_ALIGN, |
||||||
|
TEXT_TRANSFORM, |
||||||
|
} from '../../../helpers/constants/design-system'; |
||||||
|
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="p">p</Text> |
||||||
|
<Text as="h1">h1</Text> |
||||||
|
<Text as="h2">h2</Text> |
||||||
|
<Text as="h3">h3</Text> |
||||||
|
<Text as="h4">h4</Text> |
||||||
|
<Text as="h5">h5</Text> |
||||||
|
<Text as="h6">h6</Text> |
||||||
|
<Text as="span">span</Text> |
||||||
|
<Text as="strong">strong</Text> |
||||||
|
<Text as="em">em</Text> |
||||||
|
<Text as="li">li</Text> |
||||||
|
<Text as="div">div</Text> |
||||||
|
<Text as="dt">dt</Text> |
||||||
|
<Text as="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 } = render( |
||||||
|
<> |
||||||
|
<Text variant={TEXT.DISPLAY_MD}>display-md</Text> |
||||||
|
<Text variant={TEXT.HEADING_LG}>heading-lg</Text> |
||||||
|
<Text variant={TEXT.HEADING_MD}>heading-md</Text> |
||||||
|
<Text variant={TEXT.HEADING_SM}>heading-sm</Text> |
||||||
|
<Text variant={TEXT.BODY_LG}>body-lg-medium</Text> |
||||||
|
<Text variant={TEXT.BODY_MD}>body-md</Text> |
||||||
|
<Text variant={TEXT.BODY_SM}>body-sm</Text> |
||||||
|
<Text variant={TEXT.BODY_XS}>body-xs</Text> |
||||||
|
</>, |
||||||
|
); |
||||||
|
|
||||||
|
expect(getByText('display-md')).toHaveClass('text--display-md'); |
||||||
|
expect(getByText('heading-lg')).toHaveClass('text--heading-lg'); |
||||||
|
expect(getByText('heading-md')).toHaveClass('text--heading-md'); |
||||||
|
expect(getByText('heading-sm')).toHaveClass('text--heading-sm'); |
||||||
|
expect(getByText('body-lg-medium')).toHaveClass('text--body-lg-medium'); |
||||||
|
expect(getByText('body-md')).toHaveClass('text--body-md'); |
||||||
|
expect(getByText('body-sm')).toHaveClass('text--body-sm'); |
||||||
|
expect(getByText('body-xs')).toHaveClass('text--body-xs'); |
||||||
|
}); |
||||||
|
|
||||||
|
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('text--font-weight-bold'); |
||||||
|
expect(getByText('medium')).toHaveClass('text--font-weight-medium'); |
||||||
|
expect(getByText('normal')).toHaveClass('text--font-weight-normal'); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should render the Text with proper text color class name', () => { |
||||||
|
const { getByText } = render( |
||||||
|
<> |
||||||
|
<Text color={COLORS.TEXT_DEFAULT}>text-default</Text> |
||||||
|
<Text color={COLORS.TEXT_ALTERNATIVE}>text-alternative</Text> |
||||||
|
<Text color={COLORS.TEXT_MUTED}>text-muted</Text> |
||||||
|
<Text color={COLORS.OVERLAY_INVERSE}>overlay-inverse</Text> |
||||||
|
<Text color={COLORS.PRIMARY_DEFAULT}>primary-default</Text> |
||||||
|
<Text color={COLORS.PRIMARY_INVERSE}>primary-inverse</Text> |
||||||
|
<Text color={COLORS.ERROR_DEFAULT}>error-default</Text> |
||||||
|
<Text color={COLORS.ERROR_INVERSE}>error-inverse</Text> |
||||||
|
<Text color={COLORS.SUCCESS_DEFAULT}>success-default</Text> |
||||||
|
<Text color={COLORS.SUCCESS_INVERSE}>success-inverse</Text> |
||||||
|
<Text color={COLORS.WARNING_INVERSE}>warning-inverse</Text> |
||||||
|
<Text color={COLORS.INFO_DEFAULT}>info-default</Text> |
||||||
|
<Text color={COLORS.INFO_INVERSE}>info-inverse</Text> |
||||||
|
</>, |
||||||
|
); |
||||||
|
expect(getByText('text-default')).toHaveClass('text--color-text-default'); |
||||||
|
expect(getByText('text-alternative')).toHaveClass( |
||||||
|
'text--color-text-alternative', |
||||||
|
); |
||||||
|
expect(getByText('text-muted')).toHaveClass('text--color-text-muted'); |
||||||
|
expect(getByText('overlay-inverse')).toHaveClass( |
||||||
|
'text--color-overlay-inverse', |
||||||
|
); |
||||||
|
expect(getByText('primary-default')).toHaveClass( |
||||||
|
'text--color-primary-default', |
||||||
|
); |
||||||
|
expect(getByText('primary-inverse')).toHaveClass( |
||||||
|
'text--color-primary-inverse', |
||||||
|
); |
||||||
|
expect(getByText('error-default')).toHaveClass('text--color-error-default'); |
||||||
|
expect(getByText('error-inverse')).toHaveClass('text--color-error-inverse'); |
||||||
|
expect(getByText('success-default')).toHaveClass( |
||||||
|
'text--color-success-default', |
||||||
|
); |
||||||
|
expect(getByText('success-inverse')).toHaveClass( |
||||||
|
'text--color-success-inverse', |
||||||
|
); |
||||||
|
expect(getByText('warning-inverse')).toHaveClass( |
||||||
|
'text--color-warning-inverse', |
||||||
|
); |
||||||
|
expect(getByText('info-default')).toHaveClass('text--color-info-default'); |
||||||
|
expect(getByText('info-inverse')).toHaveClass('text--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('text--font-style-italic'); |
||||||
|
expect(getByText('normal')).toHaveClass('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('text--text-align-left'); |
||||||
|
expect(getByText('center')).toHaveClass('text--text-align-center'); |
||||||
|
expect(getByText('right')).toHaveClass('text--text-align-right'); |
||||||
|
expect(getByText('justify')).toHaveClass('text--text-align-justify'); |
||||||
|
expect(getByText('end')).toHaveClass('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( |
||||||
|
'text--overflow-wrap-break-word', |
||||||
|
); |
||||||
|
expect(getByText('normal')).toHaveClass('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('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( |
||||||
|
'text--text-transform-uppercase', |
||||||
|
); |
||||||
|
expect(getByText('lowercase')).toHaveClass( |
||||||
|
'text--text-transform-lowercase', |
||||||
|
); |
||||||
|
expect(getByText('capitalize')).toHaveClass( |
||||||
|
'text--text-transform-capitalize', |
||||||
|
); |
||||||
|
}); |
||||||
|
}); |
Loading…
Reference in new issue