Add responsive props to Box component (#15106)

* Adding responsive props to Box component

* Updating margin array prop instances

* Updating padding array prop instances

* Updates to docs, tests and margin, padding instances

* Optimizing class name object

* Simplifying single value logic

* replacing for loop with switch statement

* Memoizing generateClassNames function
feature/default_network_editable
George Marshall 2 years ago committed by GitHub
parent 98fc0060f3
commit 05a20bb721
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 17
      ui/components/app/add-network/add-network.js
  2. 4
      ui/components/app/advanced-gas-fee-popover/advanced-gas-fee-defaults/advanced-gas-fee-defaults.js
  3. 4
      ui/components/app/advanced-gas-fee-popover/advanced-gas-fee-gas-limit/advanced-gas-fee-gas-limit.js
  4. 2
      ui/components/app/advanced-gas-fee-popover/advanced-gas-fee-inputs/base-fee-input/base-fee-input.js
  5. 7
      ui/components/app/advanced-gas-fee-popover/advanced-gas-fee-inputs/priority-fee-input/priority-fee-input.js
  6. 3
      ui/components/app/cancel-speedup-popover/cancel-speedup-popover.js
  7. 11
      ui/components/app/collectibles-items/collectibles-items.js
  8. 4
      ui/components/app/confirm-page-container/enableEIP1559V2-notice/enableEIP1559V2-notice.js
  9. 3
      ui/components/app/detected-token/detected-token-address/detected-token-address.js
  10. 5
      ui/components/app/detected-token/detected-token-ignored-popover/detected-token-ignored-popover.js
  11. 3
      ui/components/app/edit-gas-fee-popover/network-statistics/network-statistics.js
  12. 9
      ui/components/app/recovery-phrase-reminder/recovery-phrase-reminder.js
  13. 4
      ui/components/app/transaction-detail-item/transaction-detail-item.component.js
  14. 207
      ui/components/ui/box/README.mdx
  15. 358
      ui/components/ui/box/box.js
  16. 253
      ui/components/ui/box/box.scss
  17. 139
      ui/components/ui/box/box.stories.js
  18. 732
      ui/components/ui/box/box.test.js
  19. 7
      ui/components/ui/box/index.js
  20. 6
      ui/components/ui/callout/callout.stories.js
  21. 2
      ui/components/ui/textarea/textarea.js
  22. 28
      ui/components/ui/typography/typography.js
  23. 4
      ui/css/design-system/attributes.scss
  24. 6
      ui/css/design-system/breakpoints.scss
  25. 4
      ui/helpers/constants/design-system.js
  26. 6
      ui/pages/confirm-transaction-base/transaction-alerts/transaction-alerts.js
  27. 5
      ui/pages/confirmation/confirmation.js
  28. 7
      ui/pages/home/home.component.js
  29. 8
      ui/pages/keychains/restore-vault.js
  30. 8
      ui/pages/settings/settings-tab/settings-tab.component.js
  31. 4
      ui/pages/swaps/import-token/import-token.js
  32. 33
      ui/pages/token-details/token-details-page.js

@ -82,7 +82,9 @@ const AddNetwork = () => {
className="add-network__edge-case-box"
borderRadius={SIZES.MD}
padding={4}
margin={[4, 6, 0, 6]}
marginTop={4}
marginRight={6}
marginLeft={6}
display={DISPLAY.FLEX}
flexDirection={FLEX_DIRECTION.ROW}
backgroundColor={COLORS.BACKGROUND_ALTERNATIVE}
@ -147,24 +149,23 @@ const AddNetwork = () => {
</Box>
)}
<Box
margin={
getEnvironmentType() === ENVIRONMENT_TYPE_POPUP
? [0, 0, 1, 0]
: [4, 0, 1, 0]
}
marginTop={getEnvironmentType() === ENVIRONMENT_TYPE_POPUP ? 0 : 4}
marginBottom={1}
className="add-network__main-container"
>
<Typography
variant={TYPOGRAPHY.H6}
color={COLORS.TEXT_ALTERNATIVE}
margin={[4, 0, 0, 0]}
margin={0}
marginTop={4}
>
{t('addFromAListOfPopularNetworks')}
</Typography>
<Typography
variant={TYPOGRAPHY.H7}
color={COLORS.TEXT_MUTED}
margin={[4, 0, 3, 0]}
marginTop={4}
marginBottom={3}
>
{t('popularCustomNetworks')}
</Typography>

@ -78,7 +78,9 @@ const AdvancedGasFeeDefaults = () => {
<Box
display={DISPLAY.FLEX}
flexDirection={FLEX_DIRECTION.ROW}
margin={[4, 2, 0, 2]}
marginTop={4}
marginLeft={2}
marginRight={2}
className="advanced-gas-fee-defaults"
>
<label className="advanced-gas-fee-defaults__label">

@ -65,7 +65,9 @@ const AdvancedGasFeeGasLimit = () => {
tag={TYPOGRAPHY.Paragraph}
variant={TYPOGRAPHY.H7}
className="advanced-gas-fee-gas-limit"
margin={[4, 2, 0, 2]}
marginTop={4}
marginLeft={2}
marginRight={2}
>
<strong>{t('gasLimitV2')}</strong>
<span>{gasLimit}</span>

@ -115,7 +115,7 @@ const BaseFeeInput = () => {
]);
return (
<Box className="base-fee-input" margin={[0, 2]}>
<Box className="base-fee-input" marginLeft={2} marginRight={2}>
<FormField
dataTestId="base-fee-input"
error={baseFeeError ? t(baseFeeError) : ''}

@ -103,7 +103,12 @@ const PriorityFeeInput = () => {
]);
return (
<Box margin={[4, 2, 0, 2]} className="priority-fee-input">
<Box
marginTop={4}
marginLeft={2}
marginRight={2}
className="priority-fee-input"
>
<FormField
dataTestId="priority-fee-input"
error={priorityFeeError ? t(priorityFeeError) : ''}

@ -103,7 +103,8 @@ const CancelSpeedupPopover = () => {
<Typography
boxProps={{ alignItems: ALIGN_ITEMS.CENTER, display: DISPLAY.FLEX }}
variant={TYPOGRAPHY.H6}
margin={[0, 0, 2, 0]}
marginTop={0}
marginBottom={2}
>
{t('cancelSpeedUpLabel', [
<strong key="cancelSpeedupReplace">{t('replace')}</strong>,

@ -165,7 +165,8 @@ export default function CollectiblesItems({
<Typography
color={COLORS.TEXT_DEFAULT}
variant={TYPOGRAPHY.H5}
margin={[0, 0, 0, 2]}
marginTop={0}
marginBottom={2}
>
{`${collectionName ?? t('unknownCollection')} (${
collectibles.length
@ -239,7 +240,13 @@ export default function CollectiblesItems({
return (
<div className="collectibles-items">
<Box padding={[6, 4]} flexDirection={FLEX_DIRECTION.COLUMN}>
<Box
paddingTop={6}
paddingBottom={6}
paddingLeft={4}
paddingRight={4}
flexDirection={FLEX_DIRECTION.COLUMN}
>
<>
{collectionsKeys.map((key) => {
const {

@ -34,7 +34,9 @@ export default function EnableEIP1559V2Notice({ isFirstAlert }) {
return (
<Box
margin={[0, 4, 4, 4]}
marginRight={4}
marginBottom={4}
marginLeft={4}
marginTop={isFirstAlert ? 4 : 0}
className="enableEIP1559V2-notice"
>

@ -29,7 +29,8 @@ const DetectedTokenAddress = ({ tokenAddress }) => {
<Typography
variant={TYPOGRAPHY.H7}
color={COLORS.PRIMARY_DEFAULT}
margin={[1, 2]}
marginLeft={2}
marginRight={2}
>
{shortenAddress(tokenAddress)}
</Typography>

@ -41,7 +41,10 @@ const DetectedTokenIgnoredPopover = ({
<Typography
variant={TYPOGRAPHY.H6}
tag={TYPOGRAPHY.H6}
margin={[0, 5, 7, 5]}
marginTop={0}
marginRight={5}
marginBottom={7}
marginLeft={5}
>
{t('ignoreTokenWarning')}
</Typography>

@ -32,7 +32,8 @@ const NetworkStatistics = () => {
<Typography
color={COLORS.TEXT_ALTERNATIVE}
fontWeight={FONT_WEIGHT.BOLD}
margin={[3, 0]}
marginTop={3}
marginBottom={3}
variant={TYPOGRAPHY.H8}
>
{t('networkStatus')}

@ -29,7 +29,12 @@ export default function RecoveryPhraseReminder({ onConfirm, hasBackedUp }) {
return (
<Popover centerTitle title={t('recoveryPhraseReminderTitle')}>
<Box padding={[0, 4, 6, 4]} className="recovery-phrase-reminder">
<Box
paddingRight={4}
paddingBottom={6}
paddingLeft={4}
className="recovery-phrase-reminder"
>
<Typography
color={COLORS.TEXT_DEFAULT}
align={TEXT_ALIGN.CENTER}
@ -38,7 +43,7 @@ export default function RecoveryPhraseReminder({ onConfirm, hasBackedUp }) {
>
{t('recoveryPhraseReminderSubText')}
</Typography>
<Box margin={[4, 0, 8, 0]}>
<Box marginTop={4} marginBottom={8}>
<ul className="recovery-phrase-reminder__list">
<li>
<Typography

@ -52,7 +52,9 @@ export default function TransactionDetailItem({
color={COLORS.TEXT_DEFAULT}
fontWeight={boldHeadings ? FONT_WEIGHT.BOLD : FONT_WEIGHT.NORMAL}
variant={TYPOGRAPHY.H6}
margin={[1, 0, 1, 1]}
marginTop={1}
marginBottom={1}
marginLeft={1}
boxProps={{ textAlign: TEXT_ALIGN.RIGHT }}
>
{detailTotal}

@ -14,42 +14,127 @@ Box is a utility component that can be used for layout or as a base for other UI
## Component API
| Name | Description | Default |
| --------------- | ----------------------------------- | ------------------ |
| children | node func | - |
| flexDirection | Object.values(FLEX_DIRECTION) | FLEX_DIRECTION.ROW |
| flexWrap | Object.values(FLEX_WRAP) | - |
| gap | 1,2,4,6,8 | - |
| margin | 1,2,4,6,8 or array of numbers [1,2] | - |
| marginTop | 1,2,4,6,8 | - |
| marginBottom | 1,2,4,6,8 | - |
| marginRight | 1,2,4,6,8 | - |
| marginLeft | 1,2,4,6,8 | - |
| padding | 1,2,4,6,8 or array of numbers [1,2] | - |
| paddingTop | 1,2,4,6,8 | - |
| paddingBottom | 1,2,4,6,8 | - |
| paddingRight | 1,2,4,6,8 | - |
| paddingLeft | 1,2,4,6,8 | - |
| borderColor | Object.values(COLORS) | - |
| borderWidth | number | - |
| borderRadius | Object.values(SIZES) | - |
| borderStyle | Object.values(BORDER_STYLE) | - |
| alignItems | Object.values(ALIGN_ITEMS) | - |
| justifyContent | Object.values(JUSTIFY_CONTENT) | - |
| textAlign | Object.values(TEXT_ALIGN) | - |
| display | Object.values(DISPLAY) | - |
| width | Object.values(BLOCK_SIZES) | - |
| height | Object.values(BLOCK_SIZES) | - |
| backgroundColor | Object.values(COLORS) | - |
| className | string | |
| Name | Description | Default |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
| children | The children of the Box component. If `function` type will render the child as the Box node instead of a child of the Box | - |
| className | Additional className of the Box component | - |
| margin | 0, 1, 2, 4, 6, 8, 9, 10, 12, 'auto' or array of values [1, 2, 'auto'] | - |
| marginTop | 0, 1, 2, 4, 6, 8, 9, 10, 12, 'auto' or array of values [1, 2, 'auto'] | - |
| marginBottom | 0, 1, 2, 4, 6, 8, 9, 10, 12, 'auto' or array of values [1, 2, 'auto'] | - |
| marginRight | 0, 1, 2, 4, 6, 8, 9, 10, 12, 'auto' or array of values [1, 2, 'auto'] | - |
| marginLeft | 0, 1, 2, 4, 6, 8, 9, 10, 12, 'auto' or array of values [1, 2, 'auto'] | - |
| padding | 0, 1, 2, 4, 6, 8, 9, 10, 12 or array of numbers [1, 2] | - |
| paddingTop | 0, 1, 2, 4, 6, 8, 9, 10, 12 or array of numbers [1, 2] | - |
| paddingBottom | 0, 1, 2, 4, 6, 8, 9, 10, 12 or array of numbers [1, 2] | - |
| paddingRight | 0, 1, 2, 4, 6, 8, 9, 10, 12 or array of numbers [1, 2] | - |
| paddingLeft | 0, 1, 2, 4, 6, 8, 9, 10, 12 or array of numbers [1, 2] | - |
| display | [DISPLAY](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L125-L133) values or array of [DISPLAY](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L125-L133) values | - |
| flexDirection | [FLEX_DIRECTION](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L112-L117) values or array of [FLEX_DIRECTION](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L112-L117) values | FLEX_DIRECTION.ROW |
| flexWrap | [FLEX_WRAP](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L119-L123) values or array of [FLEX_WRAP](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L119-L123) values | - |
| alignItems | [ALIGN_ITEMS](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L95-L101) values or array of [ALIGN_ITEMS](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L95-L101) values | - |
| justifyContent | [JUSTIFY_CONTENT](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L103-L110) values or array of [JUSTIFY_CONTENT](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L103-L110) values | - |
| gap | 0, 1, 2, 4, 6, 8, 9, 10, 12 or array of numbers [1, 2] | - |
| textAlign | [TEXT_ALIGN](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L172-L178) values or array of [TEXT_ALIGN](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L172-L178) values | - |
| width | [BLOCK_SIZES](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L164-L170) values or array of [BLOCK_SIZES](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L164-L170) values | - |
| height | [BLOCK_SIZES](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L164-L170) values or array of [BLOCK_SIZES](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L164-L170) values | - |
| backgroundColor | COLORS values or array of COLORS values | - |
| borderColor | COLORS values or array of COLOR values | - |
| borderWidth | 0, 1, 2, 4, 6, 8, 9, 10, 12 or array of numbers [1, 2] | - |
| borderRadius | [SIZES](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L74-L81) values or array of [SIZES](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L74-L81) values | - |
| borderStyle | [BORDER_STYLE](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L83-L88) values or array of [BORDER_STYLE](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L83-L88) values | - |
## Usage
The following describes the props and example usage for this component.
### Margin
The margin props `margin`, `marginTop`, `marginRight`, `marginBottom`, and `marginLeft` can be used to set the margins of the `Box` component. All of the margin props accept [responsive props](#responsive-props) in the form of array props
Accepted props are: `0, 1, 2, 4, 6, 8, 9, 10, 12, 'auto` or array of these values
<Canvas>
<Story id="ui-components-ui-box-box-stories-js--margin" />
</Canvas>
```jsx
<Box margin={4} />
<Box marginTop={4} />
<Box marginRight={4} />
<Box marginBottom={4} />
<Box marginLeft={'auto'} />
// Responsive props
<Box margin={[4, 8]} />
<Box marginTop={[4, 8]} />
<Box marginRight={[4, 8]} />
<Box marginBottom={[4, 8]} />
<Box marginLeft={['auto', 8]} />
```
### Padding
The padding props work very similarly to margin. The padding props `padding`, `paddingTop`, `paddingRight`, `paddingBottom`, and `paddingLeft` can be used to set the paddings of the `Box` component. All of the padding props accept [responsive props](#responsive-props) in the form of array props
Accepted props are: `0, 1, 2, 4, 6, 8, 9, 10, 12` or array of these values
<Canvas>
<Story id="ui-components-ui-box-box-stories-js--padding" />
</Canvas>
```jsx
<Box padding={4} />
<Box paddingTop={4} />
<Box paddingRight={4} />
<Box paddingBottom={4} />
<Box paddingLeft={4} />
// Responsive props
<Box padding={[4, 8]} />
<Box paddingTop={[4, 8]} />
<Box paddingRight={[4, 8]} />
<Box paddingBottom={[4, 8]} />
<Box paddingLeft={[4, 8]} />
```
### Display
The `display` prop can be used to set the display of the `Box` component. All of the display props accept [responsive props](#responsive-props) in the form of array props.
Accepted props imported from the design system `DISPLAY` const are:
- `DISPLAY.BLOCK`
- `DISPLAY.FLEX`
- `DISPLAY.GRID`
- `DISPLAY.INLINE_BLOCK`
- `DISPLAY.INLINE_FLEX`
- `DISPLAY.INLINE_GRID`
- `DISPLAY.INLINE`
- `DISPLAY.LIST_ITEM`
- `DISPLAY.NONE`
or array of these values.
```jsx
import { DISPLAY } from '../../../helpers/constants/design-system';
import Box from '../ui/box';
<Box display={DISPLAY.BLOCK} />
<Box display={DISPLAY.FLEX} />
<Box display={DISPLAY.GRID} />
<Box display={DISPLAY.INLINE_BLOCK} />
<Box display={DISPLAY.INLINE_FLEX} />
<Box display={DISPLAY.INLINE} />
<Box display={DISPLAY.NONE} />
```
### Background Color
Use the `backgroundColor` prop along with the `COLORS` object from `ui/helpers/constants/design-system.js` to change background color.
Use the `backgroundColor` prop along with the `COLORS` object from `ui/helpers/constants/design-system.js` to change background color. The `backgroundColor` prop accepts [responsive props](#responsive-props) in the form of array props.
````jsx
<Canvas>
<Story id="ui-components-ui-box-box-stories-js--background-color" />
@ -66,11 +151,11 @@ import Box from '../ui/box';
<Box backgroundColor={COLORS.BACKGROUND_DEFAULT}>
<Typography color={COLORS.TEXT_DEFAULT}>COLORS.BACKGROUND_DEFAULT</Typography>
</Box>;
```
````
### Border Color
Use the `borderColor` prop along with the `COLORS` object from `ui/helpers/constants/design-system.js` to change border color
Use the `borderColor` prop along with the `COLORS` object from `ui/helpers/constants/design-system.js` to change border color. The `borderColor` prop accepts [responsive props](#responsive-props) in the form of array props.
<Canvas>
<Story id="ui-components-ui-box-box-stories-js--border-color" />
@ -91,3 +176,63 @@ import Box from '../ui/box';
<Typography color={COLORS.TEXT_DEFAULT}>COLORS.BORDER_DEFAULT</Typography>
</Box>;
```
### Responsive Props
The box component provides a responsive props api in the form of array props. Array props are inspired by [styled-systems array props](https://styled-system.com/guides/array-props). The responsive props follow a mobile first methodology with the first item in the array applying the style to the base level size e.g. `0px` and up. The second item overwrites the first items styles at the next breakpoint.
- All Box props accept the responsive props format
- To skip a breakpoint use `null` as the skipped item's value e.g. `<Box display={['display', null, ;flex']} />`
```
// the responsive props
<Box display={['block', 'flex']} />
// is equivalent to the css
.box {
display: block;
@media screen and (max-width: $breakpoint-sm) {
display: flex;
}
}
```
<Canvas>
<Story id="ui-components-ui-box-box-stories-js--responsive-props" />
</Canvas>
```jsx
import { COLORS } from '../../../helpers/constants/design-system';
import Box from '../ui/box';
<Box
padding={[2, 4]}
gap={[2, 4]}
display={['flex']}
flexDirection={['column', 'row']}
borderColor={COLORS.BORDER_DEFAULT}
>
<Box
padding={[4, 8]}
backgroundColor={COLORS.BACKGROUND_ALTERNATIVE}
borderColor={COLORS.BORDER_MUTED}
>
responsive
</Box>
<Box
padding={[4, 8]}
backgroundColor={COLORS.BACKGROUND_ALTERNATIVE}
borderColor={COLORS.BORDER_MUTED}
>
props
</Box>
<Box
padding={[4, 8]}
backgroundColor={COLORS.BACKGROUND_ALTERNATIVE}
borderColor={COLORS.BORDER_MUTED}
>
example
</Box>
</Box>;
```

@ -1,6 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { memoize } from 'lodash';
import {
ALIGN_ITEMS,
BLOCK_SIZES,
@ -12,26 +13,12 @@ import {
TEXT_ALIGN,
FLEX_DIRECTION,
FLEX_WRAP,
BREAKPOINTS,
} from '../../../helpers/constants/design-system';
const ValidSize = PropTypes.oneOf([
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
'auto',
]);
export const ValidBackgroundColors = [
const BASE_CLASS_NAME = 'box';
const Sizes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
export const BackgroundColors = [
COLORS.BACKGROUND_DEFAULT,
COLORS.BACKGROUND_ALTERNATIVE,
COLORS.OVERLAY_DEFAULT,
@ -67,8 +54,7 @@ export const ValidBackgroundColors = [
COLORS.TRANSPARENT,
COLORS.LOCALHOST,
];
export const ValidBorderColors = [
export const BorderColors = [
COLORS.BORDER_DEFAULT,
COLORS.BORDER_MUTED,
COLORS.PRIMARY_DEFAULT,
@ -104,56 +90,134 @@ export const ValidBorderColors = [
COLORS.LOCALHOST,
];
const ValidSize = PropTypes.oneOf(Sizes);
const ValidSizeAndAuto = PropTypes.oneOf([...Sizes, 'auto']);
const ValidBackgroundColors = PropTypes.oneOf(BackgroundColors);
const ValidBorderColors = PropTypes.oneOf(BorderColors);
const ArrayOfValidSizes = PropTypes.arrayOf(ValidSize);
export const MultipleSizes = PropTypes.oneOfType([
ValidSize,
ArrayOfValidSizes,
]);
function isValidValue(type, value) {
// for now only margin type can have 'auto'
return typeof value === 'number' || (type === 'margin' && value === 'auto');
}
const ArrayOfValidSizesAndAuto = PropTypes.arrayOf(ValidSizeAndAuto);
export const MultipleSizesAndAuto = PropTypes.oneOfType([
ValidSizeAndAuto,
ArrayOfValidSizesAndAuto,
]);
function generateSizeClasses(baseClass, type, main, top, right, bottom, left) {
const arr = Array.isArray(main) ? main : [];
const singleDigit = Array.isArray(main) ? undefined : main;
if (Array.isArray(main) && ![2, 3, 4].includes(main.length)) {
throw new Error(
`Expected prop ${type} to have length between 2 and 4, received ${main.length}`,
);
}
const ArrayOfValidBorderColors = PropTypes.arrayOf(ValidBorderColors);
export const MultipleBorderColors = PropTypes.oneOfType([
ValidBorderColors,
ArrayOfValidBorderColors,
]);
const ArrayOfValidBackgroundColors = PropTypes.arrayOf(ValidBackgroundColors);
export const MultipleBackgroundColors = PropTypes.oneOfType([
ValidBackgroundColors,
ArrayOfValidBackgroundColors,
]);
const isHorizontalAndVertical = arr.length === 2;
const isTopHorizontalAndBottom = arr.length === 3;
const isAllFour = arr.length === 4;
const hasAtLeastTwo = arr.length >= 2;
const hasAtLeastThree = arr.length >= 3;
function isValidSize(type, value) {
// Only margin types allow 'auto'
return (
typeof value === 'number' ||
((type === 'margin' ||
type === 'margin-top' ||
type === 'margin-right' ||
type === 'margin-bottom' ||
type === 'margin-left') &&
value === 'auto')
);
}
return {
[`${baseClass}--${type}-${singleDigit}`]: isValidValue(type, singleDigit),
[`${baseClass}--${type}-top-${top}`]: isValidValue(type, top),
[`${baseClass}--${type}-right-${right}`]: isValidValue(type, right),
[`${baseClass}--${type}-bottom-${bottom}`]: isValidValue(type, bottom),
[`${baseClass}--${type}-left-${left}`]: isValidValue(type, left),
// As long as an array of length >= 2 has been provided, the first number
// will always be for the top value.
[`${baseClass}--${type}-top-${arr?.[0]}`]: hasAtLeastTwo,
// As long as an array of length >= 2 has been provided, the second number
// will always be for the right value.
[`${baseClass}--${type}-right-${arr?.[1]}`]: hasAtLeastTwo,
// If an array has 2 values, the first number is the bottom value. If
// instead if has 3 or more values, the third number will be the bottom.
[`${baseClass}--${type}-bottom-${arr?.[2]}`]: hasAtLeastThree,
[`${baseClass}--${type}-bottom-${arr?.[0]}`]: isHorizontalAndVertical,
// If an array has 2 or 3 values, the second number will be the left value
[`${baseClass}--${type}-left-${arr?.[1]}`]:
isHorizontalAndVertical || isTopHorizontalAndBottom,
// If an array has 4 values, the fourth number is the left value
[`${baseClass}--${type}-left-${arr?.[3]}`]: isAllFour,
};
function isValidString(type, value) {
return typeof type === 'string' && typeof value === 'string';
}
/**
* Generate classnames
* Generates classnames for different utility styles
* Also accepts responsive props in the form of an array
* Maps responsive props to mobile first breakpoints
*
* @param {string} type - The style declaration type "margin", "margin-top", "padding", "display" etc
* @param {array || number || string} value - prop value being passed in array props are responsive props
* @param {*} validatorFn - The validation function for each type of value
* @returns
*/
const generateClassNames = memoize(
(type, value, validatorFn) => {
// if value does not exist return null
if (!value) {
return null;
}
const classesObject = {};
// if value is an array with single item e.g. marginTop={[1]}
const singleArrayItemProp =
Array.isArray(value) && value.length === 1 ? value[0] : undefined;
// if value single value e.g. marginTop={1}
const singleValueProp =
(!Array.isArray(value) && typeof value === 'string') ||
typeof value === 'number'
? value
: undefined;
// single digit equals single value or single array item
const singleValue = singleValueProp || singleArrayItemProp;
// 0 is an acceptable value but is falsy in js
if (singleValue || singleValue === 0) {
// add base style without any breakpoint prefixes to classObject
classesObject[`${BASE_CLASS_NAME}--${type}-${singleValue}`] = validatorFn(
type,
singleValue,
);
} else {
// If array with more than one item
switch (value.length) {
case 4:
// add base/sm/md/lg
classesObject[`${BASE_CLASS_NAME}--${type}-${value[0]}`] =
value[0] && validatorFn(type, value[0]);
classesObject[
`${BASE_CLASS_NAME}--${BREAKPOINTS[1]}:${type}-${value[1]}`
] = value[1] && validatorFn(type, value[1]);
classesObject[
`${BASE_CLASS_NAME}--${BREAKPOINTS[2]}:${type}-${value[2]}`
] = value[2] && validatorFn(type, value[2]);
classesObject[
`${BASE_CLASS_NAME}--${BREAKPOINTS[3]}:${type}-${value[3]}`
] = value[3] && validatorFn(type, value[3]);
break;
case 3:
// add base/sm/md
classesObject[`${BASE_CLASS_NAME}--${type}-${value[0]}`] =
value[0] && validatorFn(type, value[0]);
classesObject[
`${BASE_CLASS_NAME}--${BREAKPOINTS[1]}:${type}-${value[1]}`
] = value[1] && validatorFn(type, value[1]);
classesObject[
`${BASE_CLASS_NAME}--${BREAKPOINTS[2]}:${type}-${value[2]}`
] = value[2] && validatorFn(type, value[2]);
break;
case 2:
// add base/sm
classesObject[`${BASE_CLASS_NAME}--${type}-${value[0]}`] =
value[0] && validatorFn(type, value[0]);
classesObject[
`${BASE_CLASS_NAME}--${BREAKPOINTS[1]}:${type}-${value[1]}`
] = value[1] && validatorFn(type, value[1]);
break;
default:
console.log(`Invalid array prop length: ${value.length}`);
}
}
return classesObject;
},
(type, value) => [type, value],
);
export default function Box({
padding,
paddingTop,
@ -182,56 +246,57 @@ export default function Box({
className,
backgroundColor,
}) {
const boxClassName = classnames('box', className, {
// ---Borders---
// if borderWidth or borderColor is supplied w/o style, default to solid
'box--border-style-solid':
!borderStyle && (Boolean(borderWidth) || Boolean(borderColor)),
// if borderColor supplied w/o width, default to 1
'box--border-size-1': !borderWidth && Boolean(borderColor),
[`box--border-color-${borderColor}`]: Boolean(borderColor),
[`box--rounded-${borderRadius}`]: Boolean(borderRadius),
[`box--border-style-${borderStyle}`]: Boolean(borderStyle),
[`box--border-size-${borderWidth}`]: Boolean(borderWidth),
const boxClassName = classnames(
BASE_CLASS_NAME,
className,
// Margin
...generateSizeClasses(
'box',
'margin',
margin,
marginTop,
marginRight,
marginBottom,
marginLeft,
),
margin && generateClassNames('margin', margin, isValidSize),
marginTop && generateClassNames('margin-top', marginTop, isValidSize),
marginRight && generateClassNames('margin-right', marginRight, isValidSize),
marginBottom &&
generateClassNames('margin-bottom', marginBottom, isValidSize),
marginLeft && generateClassNames('margin-left', marginLeft, isValidSize),
// Padding
...generateSizeClasses(
'box',
'padding',
padding,
paddingTop,
paddingRight,
paddingBottom,
paddingLeft,
),
// ---Flex/Grid alignment---
// if justifyContent or alignItems supplied w/o display, default to flex
'box--display-flex':
!display && (Boolean(justifyContent) || Boolean(alignItems)),
[`box--justify-content-${justifyContent}`]: Boolean(justifyContent),
[`box--align-items-${alignItems}`]: Boolean(alignItems),
[`box--flex-direction-${flexDirection}`]: Boolean(flexDirection),
[`box--flex-wrap-${flexWrap}`]: Boolean(flexWrap),
// text align
[`box--text-align-${textAlign}`]: Boolean(textAlign),
// display
[`box--display-${display}`]: Boolean(display),
// width & height
[`box--width-${width}`]: Boolean(width),
[`box--height-${height}`]: Boolean(height),
// background
[`box--background-color-${backgroundColor}`]: Boolean(backgroundColor),
...generateSizeClasses('box', 'gap', gap),
});
padding && generateClassNames('padding', padding, isValidSize),
paddingTop && generateClassNames('padding-top', paddingTop, isValidSize),
paddingRight &&
generateClassNames('padding-right', paddingRight, isValidSize),
paddingBottom &&
generateClassNames('padding-bottom', paddingBottom, isValidSize),
paddingLeft && generateClassNames('padding-left', paddingLeft, isValidSize),
display && generateClassNames('display', display, isValidString),
gap && generateClassNames('gap', gap, isValidSize),
flexDirection &&
generateClassNames('flex-direction', flexDirection, isValidString),
flexWrap && generateClassNames('flex-wrap', flexWrap, isValidString),
justifyContent &&
generateClassNames('justify-content', justifyContent, isValidString),
alignItems && generateClassNames('align-items', alignItems, isValidString),
textAlign && generateClassNames('text-align', textAlign, isValidString),
width && generateClassNames('width', width, isValidString),
height && generateClassNames('height', height, isValidString),
backgroundColor &&
generateClassNames('background-color', backgroundColor, isValidString),
borderRadius && generateClassNames('rounded', borderRadius, isValidString),
borderStyle &&
generateClassNames('border-style', borderStyle, isValidString),
borderColor &&
generateClassNames('border-color', borderColor, isValidString),
borderWidth && generateClassNames('border-width', borderWidth, isValidSize),
{
// Auto applied classes
// ---Borders---
// if borderWidth or borderColor is supplied w/o style, default to solid
'box--border-style-solid':
!borderStyle && (Boolean(borderWidth) || Boolean(borderColor)),
// if borderColor supplied w/o width, default to 1
'box--border-width-1': !borderWidth && Boolean(borderColor),
// ---Flex/Grid alignment---
// if justifyContent or alignItems supplied w/o display, default to flex
'box--display-flex':
!display && (Boolean(justifyContent) || Boolean(alignItems)),
},
);
// Apply Box styles to any other component using function pattern
if (typeof children === 'function') {
return children(boxClassName);
@ -241,29 +306,62 @@ export default function Box({
Box.propTypes = {
children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
flexDirection: PropTypes.oneOf(Object.values(FLEX_DIRECTION)),
flexWrap: PropTypes.oneOf(Object.values(FLEX_WRAP)),
gap: ValidSize,
margin: MultipleSizes,
marginTop: ValidSize,
marginBottom: ValidSize,
marginRight: ValidSize,
marginLeft: ValidSize,
flexDirection: PropTypes.oneOfType([
PropTypes.oneOf(Object.values(FLEX_DIRECTION)),
PropTypes.arrayOf(PropTypes.oneOf(Object.values(FLEX_DIRECTION))),
]),
flexWrap: PropTypes.oneOfType([
PropTypes.oneOf(Object.values(FLEX_WRAP)),
PropTypes.arrayOf(PropTypes.oneOf(Object.values(FLEX_WRAP))),
]),
gap: MultipleSizes,
margin: MultipleSizesAndAuto,
marginTop: MultipleSizesAndAuto,
marginBottom: MultipleSizesAndAuto,
marginRight: MultipleSizesAndAuto,
marginLeft: MultipleSizesAndAuto,
padding: MultipleSizes,
paddingTop: ValidSize,
paddingBottom: ValidSize,
paddingRight: ValidSize,
paddingLeft: ValidSize,
borderColor: PropTypes.oneOf(Object.values(ValidBorderColors)),
borderWidth: PropTypes.number,
borderRadius: PropTypes.oneOf(Object.values(SIZES)),
borderStyle: PropTypes.oneOf(Object.values(BORDER_STYLE)),
alignItems: PropTypes.oneOf(Object.values(ALIGN_ITEMS)),
justifyContent: PropTypes.oneOf(Object.values(JUSTIFY_CONTENT)),
textAlign: PropTypes.oneOf(Object.values(TEXT_ALIGN)),
display: PropTypes.oneOf(Object.values(DISPLAY)),
width: PropTypes.oneOf(Object.values(BLOCK_SIZES)),
height: PropTypes.oneOf(Object.values(BLOCK_SIZES)),
backgroundColor: PropTypes.oneOf(Object.values(ValidBackgroundColors)),
paddingTop: MultipleSizes,
paddingBottom: MultipleSizes,
paddingRight: MultipleSizes,
paddingLeft: MultipleSizes,
borderColor: MultipleBorderColors,
borderWidth: PropTypes.oneOfType([
PropTypes.number,
PropTypes.arrayOf(PropTypes.number),
]),
borderRadius: PropTypes.oneOfType([
PropTypes.oneOf(Object.values(SIZES)),
PropTypes.arrayOf(PropTypes.oneOf(Object.values(SIZES))),
]),
borderStyle: PropTypes.oneOfType([
PropTypes.oneOf(Object.values(BORDER_STYLE)),
PropTypes.arrayOf(PropTypes.oneOf(Object.values(BORDER_STYLE))),
]),
alignItems: PropTypes.oneOfType([
PropTypes.oneOf(Object.values(ALIGN_ITEMS)),
PropTypes.arrayOf(PropTypes.oneOf(Object.values(ALIGN_ITEMS))),
]),
justifyContent: PropTypes.oneOfType([
PropTypes.oneOf(Object.values(JUSTIFY_CONTENT)),
PropTypes.arrayOf(PropTypes.oneOf(Object.values(JUSTIFY_CONTENT))),
]),
textAlign: PropTypes.oneOfType([
PropTypes.oneOf(Object.values(TEXT_ALIGN)),
PropTypes.arrayOf(PropTypes.oneOf(Object.values(TEXT_ALIGN))),
]),
display: PropTypes.oneOfType([
PropTypes.oneOf(Object.values(DISPLAY)),
PropTypes.arrayOf(PropTypes.oneOf(Object.values(DISPLAY))),
]),
width: PropTypes.oneOfType([
PropTypes.oneOf(Object.values(BLOCK_SIZES)),
PropTypes.arrayOf(PropTypes.oneOf(Object.values(BLOCK_SIZES))),
]),
height: PropTypes.oneOfType([
PropTypes.oneOf(Object.values(BLOCK_SIZES)),
PropTypes.arrayOf(PropTypes.oneOf(Object.values(BLOCK_SIZES))),
]),
backgroundColor: MultipleBackgroundColors,
className: PropTypes.string,
};

@ -15,6 +15,16 @@ $attributesToApplyExtraProperties: margin;
#{$attribute}: utilities.get-spacing($size);
}
}
// breakpoint classes
@each $breakpoint, $min-width in $screen-sizes-map {
@each $size in design-system.$sizes-numeric {
@media screen and (min-width: $min-width) {
&--#{$breakpoint}\:#{$attribute}-#{$size} {
#{$attribute}: utilities.get-spacing($size);
}
}
}
}
@each $size in design-system.$sizes-numeric {
@each $direction in design-system.$directions {
@ -22,6 +32,16 @@ $attributesToApplyExtraProperties: margin;
#{$attribute}-#{$direction}: utilities.get-spacing($size);
}
}
// breakpoint classes
@each $breakpoint, $min-width in $screen-sizes-map {
@each $direction in design-system.$directions {
@media screen and (min-width: $min-width) {
&--#{$breakpoint}\:#{$attribute}-#{$direction}-#{$size} {
#{$attribute}-#{$direction}: utilities.get-spacing($size);
}
}
}
}
}
@if list.index($attributesToApplyExtraProperties, $attribute) {
@ -29,34 +49,85 @@ $attributesToApplyExtraProperties: margin;
&--#{$attribute}-#{$property} {
#{$attribute}: $property;
}
}
@each $property in $extraProperties {
@each $direction in design-system.$directions {
&--#{$attribute}-#{$direction}-#{$property} {
#{$attribute}-#{$direction}: $property;
}
}
}
// breakpoint classes
@each $breakpoint, $min-width in $screen-sizes-map {
@each $property in $extraProperties {
@media screen and (min-width: $min-width) {
&--#{$breakpoint}\:#{$attribute}-#{$property} {
#{$attribute}: $property;
}
}
@each $direction in design-system.$directions {
@media screen and (min-width: $min-width) {
&--#{$breakpoint}\:#{$attribute}-#{$direction}-#{$property} {
#{$attribute}-#{$direction}: $property;
}
}
}
}
}
}
}
// Borders
@each $size in design-system.$sizes-numeric {
&--border-size-#{$size} {
&--border-width-#{$size} {
border-width: #{$size}px;
}
}
// breakpoint classes
@each $breakpoint, $min-width in $screen-sizes-map {
@each $size in design-system.$sizes-numeric {
@media screen and (min-width: $min-width) {
&--#{$breakpoint}\:border-width-#{$size} {
border-width: #{$size}px;
}
}
}
}
// border-color
@each $variant, $color in design-system.$color-map {
&--border-color-#{$variant} {
border-color: var($color);
}
}
// breakpoint classes
@each $breakpoint, $min-width in $screen-sizes-map {
@each $variant, $color in design-system.$color-map {
@media screen and (min-width: $min-width) {
&--#{$breakpoint}\:border-color-#{$variant} {
border-color: var($color);
}
}
}
}
// border-style
@each $border-style in design-system.$border-style {
&--border-style-#{$border-style} {
border-style: $border-style;
}
}
// breakpoint classes
@each $breakpoint, $min-width in $screen-sizes-map {
@each $border-style in design-system.$border-style {
@media screen and (min-width: $min-width) {
&--#{$breakpoint}\:border-style-#{$border-style} {
border-style: $border-style;
}
}
}
}
&--rounded-none {
border-radius: 0;
@ -82,45 +153,140 @@ $attributesToApplyExtraProperties: margin;
border-radius: 0.75rem;
}
// breakpoint classes
@each $breakpoint, $min-width in $screen-sizes-map {
@media screen and (min-width: $min-width) {
&--#{$breakpoint}\:rounded-none {
border-radius: 0;
}
&--#{$breakpoint}\:rounded-xs {
border-radius: 0.125rem;
}
&--#{$breakpoint}\:rounded-sm {
border-radius: 0.25rem;
}
&--#{$breakpoint}\:rounded-md {
border-radius: 0.375rem;
}
&--#{$breakpoint}\:rounded-lg {
border-radius: 0.5rem;
}
&--#{$breakpoint}\:rounded-xl {
border-radius: 0.75rem;
}
}
}
// Display and Flex/Grid alignment
@each $display in design-system.$display {
&--display-#{$display} {
display: $display;
}
}
// breakpoint classes
@each $breakpoint, $min-width in $screen-sizes-map {
@each $display in design-system.$display {
@media screen and (min-width: $min-width) {
&--#{$breakpoint}\:display-#{$display} {
display: $display;
}
}
}
}
@each $alignment in design-system.$align-items {
&--align-items-#{$alignment} {
align-items: $alignment;
}
}
// breakpoint classes
@each $breakpoint, $min-width in $screen-sizes-map {
@each $alignment in design-system.$align-items {
@media screen and (min-width: $min-width) {
&--#{$breakpoint}\:align-items-#{$alignment} {
align-items: $alignment;
}
}
}
}
@each $justification in design-system.$justify-content {
&--justify-content-#{$justification} {
justify-content: $justification;
}
}
// breakpoint classes
@each $breakpoint, $min-width in $screen-sizes-map {
@each $justification in design-system.$justify-content {
@media screen and (min-width: $min-width) {
&--#{$breakpoint}\:justify-content-#{$justification} {
justify-content: $justification;
}
}
}
}
@each $direction in design-system.$flex-direction {
&--flex-direction-#{$direction} {
flex-direction: $direction;
}
}
// breakpoint classes
@each $breakpoint, $min-width in $screen-sizes-map {
@each $direction in design-system.$flex-direction {
@media screen and (min-width: $min-width) {
&--#{$breakpoint}\:flex-direction-#{$direction} {
flex-direction: $direction;
}
}
}
}
@each $wrap in design-system.$flex-wrap {
&--flex-wrap-#{$wrap} {
flex-wrap: $wrap;
}
}
// breakpoint classes
@each $breakpoint, $min-width in $screen-sizes-map {
@each $wrap in design-system.$flex-wrap {
@media screen and (min-width: $min-width) {
&--#{$breakpoint}\:flex-wrap-#{$wrap} {
flex-wrap: $wrap;
}
}
}
}
// Width and Height
&--width-full {
width: 100%;
}
// breakpoint classes
@each $breakpoint, $min-width in $screen-sizes-map {
@media screen and (min-width: $min-width) {
&--#{$breakpoint}\:width-full {
width: 100%;
}
}
}
&--height-full {
height: 100%;
}
// breakpoint classes
@each $breakpoint, $min-width in $screen-sizes-map {
@media screen and (min-width: $min-width) {
&--#{$breakpoint}\:height-full {
height: 100%;
}
}
}
@each $fraction, $value in design-system.$fractions {
&--width-#{$fraction} {
@ -131,30 +297,91 @@ $attributesToApplyExtraProperties: margin;
height: $value;
}
}
// breakpoint classes
@each $breakpoint, $min-width in $screen-sizes-map {
@each $fraction, $value in design-system.$fractions {
@media screen and (min-width: $min-width) {
&--#{$breakpoint}\:width-#{$fraction} {
width: $value;
}
&--#{$breakpoint}\:height-#{$fraction} {
height: $value;
}
}
}
}
&--height-screen {
height: 100vh;
}
// breakpoint classes
@each $breakpoint, $min-width in $screen-sizes-map {
@media screen and (min-width: $min-width) {
&--#{$breakpoint}\:height-screen {
height: 100vh;
}
}
}
&--width-screen {
width: 100vw;
}
// breakpoint classes
@each $breakpoint, $min-width in $screen-sizes-map {
@media screen and (min-width: $min-width) {
&--#{$breakpoint}\:width-screen {
width: 100vw;
}
}
}
&--height-max {
height: max-content;
}
// breakpoint classes
@each $breakpoint, $min-width in $screen-sizes-map {
@media screen and (min-width: $min-width) {
&--#{$breakpoint}\:height-max {
height: max-content;
}
}
}
&--width-max {
width: max-content;
}
// breakpoint classes
@each $breakpoint, $min-width in $screen-sizes-map {
@media screen and (min-width: $min-width) {
&--#{$breakpoint}\:height-max {
height: max-content;
}
}
}
&--height-min {
height: min-content;
}
// breakpoint classes
@each $breakpoint, $min-width in $screen-sizes-map {
@media screen and (min-width: $min-width) {
&--#{$breakpoint}\:height-min {
height: min-content;
}
}
}
&--width-min {
width: min-content;
}
// breakpoint classes
@each $breakpoint, $min-width in $screen-sizes-map {
@media screen and (min-width: $min-width) {
&--#{$breakpoint}\:width-min {
width: min-content;
}
}
}
// text
@each $alignment in design-system.$text-align {
@ -162,6 +389,16 @@ $attributesToApplyExtraProperties: margin;
text-align: $alignment;
}
}
// breakpoint classes
@each $breakpoint, $min-width in $screen-sizes-map {
@each $alignment in design-system.$text-align {
@media screen and (min-width: $min-width) {
&--#{$breakpoint}\:text-align-#{$alignment} {
text-align: $alignment;
}
}
}
}
// background
@each $variant, $color in design-system.$color-map {
@ -169,4 +406,14 @@ $attributesToApplyExtraProperties: margin;
background-color: var($color);
}
}
// breakpoint classes
@each $breakpoint, $min-width in $screen-sizes-map {
@each $variant, $color in design-system.$color-map {
@media screen and (min-width: $min-width) {
&--#{$breakpoint}\background-color-#{$variant} {
background-color: var($color);
}
}
}
}
}

@ -6,15 +6,17 @@ import {
COLORS,
DISPLAY,
JUSTIFY_CONTENT,
SIZES,
TEXT_ALIGN,
FLEX_DIRECTION,
FLEX_WRAP,
} from '../../../helpers/constants/design-system';
import Typography from '../typography';
import Box from './box';
import Box, { BackgroundColors, BorderColors } from './box';
import README from './README.mdx';
import { ValidBackgroundColors, ValidBorderColors } from '.';
const sizeKnobOptions = [undefined, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
const marginSizeKnobOptions = [...sizeKnobOptions, 'auto'];
@ -58,18 +60,44 @@ export default {
table: { category: 'display' },
},
backgroundColor: {
options: ValidBackgroundColors,
options: BackgroundColors,
control: 'select',
table: {
category: 'background',
},
},
borderStyle: {
options: Object.values(BORDER_STYLE),
control: 'select',
defaultValue: BORDER_STYLE.DASHED,
table: { category: 'border' },
},
borderWidth: {
options: sizeKnobOptions,
control: 'number',
table: { category: 'border' },
},
borderColor: {
options: ValidBorderColors,
options: BorderColors,
control: 'select',
defaultValue: COLORS.BORDER_DEFAULT,
table: { category: 'border' },
},
borderRadius: {
options: Object.values(SIZES),
control: 'select',
table: { category: 'border' },
},
flexWrap: {
options: Object.values(FLEX_WRAP),
control: 'select',
table: { category: 'display' },
},
flexDirection: {
options: Object.values(FLEX_DIRECTION),
control: 'select',
table: { category: 'display' },
},
justifyContent: {
options: Object.values(JUSTIFY_CONTENT),
control: 'select',
@ -86,7 +114,7 @@ export default {
options: Object.values(TEXT_ALIGN),
control: 'select',
defaultValue: TEXT_ALIGN.LEFT,
table: { category: 'left' },
table: { category: 'text' },
},
margin: {
options: marginSizeKnobOptions,
@ -138,18 +166,6 @@ export default {
control: 'select',
table: { category: 'padding' },
},
borderStyle: {
options: Object.values(BORDER_STYLE),
control: 'select',
defaultValue: BORDER_STYLE.DASHED,
table: { category: 'border' },
},
borderWidth: {
options: sizeKnobOptions,
control: 'number',
defaultValue: 1,
table: { category: 'border' },
},
},
};
@ -158,7 +174,7 @@ export const DefaultStory = (args) => {
const children = [];
for (let $i = 0; $i < items; $i++) {
children.push(
<img width={size} height={size} src="./images/eth_logo.svg" />,
<img key={$i} width={size} height={size} src="./images/eth_logo.svg" />,
);
}
return <Box {...rest}>{children}</Box>;
@ -166,6 +182,50 @@ export const DefaultStory = (args) => {
DefaultStory.storyName = 'Default';
export const Margin = () => {
return (
<Box borderColor={COLORS.BORDER_MUTED}>
<Box
margin={2}
padding={4}
backgroundColor={COLORS.BACKGROUND_ALTERNATIVE}
borderColor={COLORS.BORDER_MUTED}
>
Static margin
</Box>
<Box
margin={[2, 4, 8, 12]}
padding={[4]}
backgroundColor={COLORS.BACKGROUND_ALTERNATIVE}
borderColor={COLORS.BORDER_MUTED}
>
Responsive margin changes based on breakpoint
</Box>
</Box>
);
};
export const Padding = () => {
return (
<Box borderColor={COLORS.BORDER_MUTED}>
<Box
padding={4}
backgroundColor={COLORS.BACKGROUND_ALTERNATIVE}
borderColor={COLORS.BORDER_MUTED}
>
Static padding
</Box>
<Box
padding={[4, 8, 12]}
backgroundColor={COLORS.BACKGROUND_ALTERNATIVE}
borderColor={COLORS.BORDER_MUTED}
>
Responsive padding changes based on breakpoint
</Box>
</Box>
);
};
export const BackgroundColor = () => {
return (
<>
@ -303,3 +363,46 @@ export const BorderColor = () => {
</>
);
};
export const ResponsiveProps = () => {
return (
<>
<Typography boxProps={{ marginBottom: 4 }}>
Responsive props example. Stacks vertically on small screens and aligns
horizontally on large screens. Padding is also adjusted between small
and large screens
</Typography>
<Box
marginTop="auto"
marginBottom={[0]}
padding={[2, 4]}
gap={[2, 4]}
display={['flex', null, null, 'none']}
flexDirection={['column', 'row']}
borderColor={COLORS.BORDER_DEFAULT}
>
<Box
padding={[4, 8]}
backgroundColor={COLORS.BACKGROUND_ALTERNATIVE}
borderColor={COLORS.BORDER_MUTED}
>
responsive
</Box>
<Box
padding={[4, 8]}
backgroundColor={COLORS.BACKGROUND_ALTERNATIVE}
borderColor={COLORS.BORDER_MUTED}
>
props
</Box>
<Box
padding={[4, 8]}
backgroundColor={COLORS.BACKGROUND_ALTERNATIVE}
borderColor={COLORS.BORDER_MUTED}
>
example
</Box>
</Box>
</>
);
};

@ -0,0 +1,732 @@
import * as React from 'react';
import { render } from '@testing-library/react';
import {
BORDER_STYLE,
COLORS,
DISPLAY,
FLEX_DIRECTION,
FLEX_WRAP,
ALIGN_ITEMS,
JUSTIFY_CONTENT,
TEXT_ALIGN,
SIZES,
BLOCK_SIZES,
} from '../../../helpers/constants/design-system';
import Box from '.';
describe('Box', () => {
it('should render the Box without crashing', () => {
const { getByText } = render(<Box>Box content</Box>);
expect(getByText('Box content')).toBeDefined();
});
describe('margin', () => {
it('should render the Box with the margin class', () => {
const { getByText } = render(<Box margin={1}>Box content</Box>);
expect(getByText('Box content')).toHaveClass('box--margin-1');
});
it('should render the Box with the margin auto class', () => {
const { getByText } = render(<Box margin="auto">Box content</Box>);
expect(getByText('Box content')).toHaveClass('box--margin-auto');
});
it('should render the Box with the responsive margin classes', () => {
const { getByText } = render(
<Box margin={[1, 'auto', 3, 4]}>Box content</Box>,
);
expect(getByText('Box content')).toHaveClass('box--margin-1');
expect(getByText('Box content')).toHaveClass('box--sm:margin-auto');
expect(getByText('Box content')).toHaveClass('box--md:margin-3');
expect(getByText('Box content')).toHaveClass('box--lg:margin-4');
});
it('should render the Box with the marginTop class', () => {
const { getByText } = render(<Box marginTop={1}>Box content</Box>);
expect(getByText('Box content')).toHaveClass('box--margin-top-1');
});
it('should render the Box with the marginTop auto class', () => {
const { getByText } = render(<Box marginTop="auto">Box content</Box>);
expect(getByText('Box content')).toHaveClass('box--margin-top-auto');
});
it('should render the Box with the responsive marginTop classes', () => {
const { getByText } = render(
<Box marginTop={[1, 'auto', 3, 4]}>Box content</Box>,
);
expect(getByText('Box content')).toHaveClass('box--margin-top-1');
expect(getByText('Box content')).toHaveClass('box--sm:margin-top-auto');
expect(getByText('Box content')).toHaveClass('box--md:margin-top-3');
expect(getByText('Box content')).toHaveClass('box--lg:margin-top-4');
});
it('should render the Box with the marginRight class', () => {
const { getByText } = render(<Box marginRight={1}>Box content</Box>);
expect(getByText('Box content')).toHaveClass('box--margin-right-1');
});
it('should render the Box with the marginRight auto class', () => {
const { getByText } = render(<Box marginRight="auto">Box content</Box>);
expect(getByText('Box content')).toHaveClass('box--margin-right-auto');
});
it('should render the Box with the responsive marginRight classes', () => {
const { getByText } = render(
<Box marginRight={[1, 'auto', 3, 4]}>Box content</Box>,
);
expect(getByText('Box content')).toHaveClass('box--margin-right-1');
expect(getByText('Box content')).toHaveClass('box--sm:margin-right-auto');
expect(getByText('Box content')).toHaveClass('box--md:margin-right-3');
expect(getByText('Box content')).toHaveClass('box--lg:margin-right-4');
});
it('should render the Box with the marginBottom class', () => {
const { getByText } = render(<Box marginBottom={1}>Box content</Box>);
expect(getByText('Box content')).toHaveClass('box--margin-bottom-1');
});
it('should render the Box with the responsive marginBottom classes', () => {
const { getByText } = render(
<Box marginBottom={[1, 'auto', 3, 4]}>Box content</Box>,
);
expect(getByText('Box content')).toHaveClass('box--margin-bottom-1');
expect(getByText('Box content')).toHaveClass(
'box--sm:margin-bottom-auto',
);
expect(getByText('Box content')).toHaveClass('box--md:margin-bottom-3');
expect(getByText('Box content')).toHaveClass('box--lg:margin-bottom-4');
});
it('should render the Box with the marginLeft class', () => {
const { getByText } = render(<Box marginLeft={1}>Box content</Box>);
expect(getByText('Box content')).toHaveClass('box--margin-left-1');
});
it('should render the Box with the responsive marginLeft classes', () => {
const { getByText } = render(
<Box marginLeft={[1, 'auto', 3, 4]}>Box content</Box>,
);
expect(getByText('Box content')).toHaveClass('box--margin-left-1');
expect(getByText('Box content')).toHaveClass('box--sm:margin-left-auto');
expect(getByText('Box content')).toHaveClass('box--md:margin-left-3');
expect(getByText('Box content')).toHaveClass('box--lg:margin-left-4');
});
});
describe('padding', () => {
it('should render the Box with the padding class with singular value prop or one item array prop', () => {
const { getByText } = render(
<>
<Box padding={1}>Box content</Box>
<Box padding={[1]}>Box content one item array</Box>
</>,
);
expect(getByText('Box content')).toHaveClass('box--padding-1');
expect(getByText('Box content one item array')).toHaveClass(
'box--padding-1',
);
});
it('should render the Box with the responsive padding classes', () => {
const { getByText } = render(
<Box padding={[1, 2, 3, 4]}>Box content</Box>,
);
expect(getByText('Box content')).toHaveClass('box--padding-1');
expect(getByText('Box content')).toHaveClass('box--sm:padding-2');
expect(getByText('Box content')).toHaveClass('box--md:padding-3');
expect(getByText('Box content')).toHaveClass('box--lg:padding-4');
});
it('should render the Box with the paddingTop class', () => {
const { getByText } = render(<Box paddingTop={1}>Box content</Box>);
expect(getByText('Box content')).toHaveClass('box--padding-top-1');
});
it('should render the Box with the responsive paddingTop classes', () => {
const { getByText } = render(
<Box paddingTop={[1, 2, 3, 4]}>Box content</Box>,
);
expect(getByText('Box content')).toHaveClass('box--padding-top-1');
expect(getByText('Box content')).toHaveClass('box--sm:padding-top-2');
expect(getByText('Box content')).toHaveClass('box--md:padding-top-3');
expect(getByText('Box content')).toHaveClass('box--lg:padding-top-4');
});
it('should render the Box with the paddingRight class', () => {
const { getByText } = render(<Box paddingRight={1}>Box content</Box>);
expect(getByText('Box content')).toHaveClass('box--padding-right-1');
});
it('should render the Box with the responsive paddingRight classes', () => {
const { getByText } = render(
<Box paddingRight={[1, 2, 3, 4]}>Box content</Box>,
);
expect(getByText('Box content')).toHaveClass('box--padding-right-1');
expect(getByText('Box content')).toHaveClass('box--sm:padding-right-2');
expect(getByText('Box content')).toHaveClass('box--md:padding-right-3');
expect(getByText('Box content')).toHaveClass('box--lg:padding-right-4');
});
it('should render the Box with the paddingBottom class', () => {
const { getByText } = render(<Box paddingBottom={1}>Box content</Box>);
expect(getByText('Box content')).toHaveClass('box--padding-bottom-1');
});
it('should render the Box with the responsive paddingBottom classes', () => {
const { getByText } = render(
<Box paddingBottom={[1, 2, 3, 4]}>Box content</Box>,
);
expect(getByText('Box content')).toHaveClass('box--padding-bottom-1');
expect(getByText('Box content')).toHaveClass('box--sm:padding-bottom-2');
expect(getByText('Box content')).toHaveClass('box--md:padding-bottom-3');
expect(getByText('Box content')).toHaveClass('box--lg:padding-bottom-4');
});
it('should render the Box with the paddingLeft class', () => {
const { getByText } = render(<Box paddingLeft={1}>Box content</Box>);
expect(getByText('Box content')).toHaveClass('box--padding-left-1');
});
it('should render the Box with the responsive paddingLeft classes', () => {
const { getByText } = render(
<Box paddingLeft={[1, 2, 3, 4]}>Box content</Box>,
);
expect(getByText('Box content')).toHaveClass('box--padding-left-1');
expect(getByText('Box content')).toHaveClass('box--sm:padding-left-2');
expect(getByText('Box content')).toHaveClass('box--md:padding-left-3');
expect(getByText('Box content')).toHaveClass('box--lg:padding-left-4');
});
});
describe('border', () => {
it('should render the Box with the borderWidth class', () => {
const { getByText } = render(<Box borderWidth={1}>Box content</Box>);
expect(getByText('Box content')).toHaveClass('box--border-width-1');
});
it('should render the Box with the responsive borderWidth classes', () => {
const { getByText } = render(
<Box borderWidth={[1, 2, 3, 4]}>Box content</Box>,
);
expect(getByText('Box content')).toHaveClass('box--border-width-1');
expect(getByText('Box content')).toHaveClass('box--sm:border-width-2');
expect(getByText('Box content')).toHaveClass('box--md:border-width-3');
expect(getByText('Box content')).toHaveClass('box--lg:border-width-4');
});
it('should render the Box with the borderColor class', () => {
const { getByText } = render(
<Box borderColor={COLORS.BORDER_DEFAULT}>Box content</Box>,
);
expect(getByText('Box content')).toHaveClass(
'box--border-color-border-default',
);
});
it('should render the Box with the responsive borderColor classes', () => {
const { getByText } = render(
<Box
borderColor={[
COLORS.BORDER_DEFAULT,
COLORS.ERROR_DEFAULT,
COLORS.INFO_DEFAULT,
COLORS.WARNING_DEFAULT,
]}
>
Box content
</Box>,
);
expect(getByText('Box content')).toHaveClass(
'box--border-color-border-default',
);
expect(getByText('Box content')).toHaveClass(
'box--sm:border-color-error-default',
);
expect(getByText('Box content')).toHaveClass(
'box--md:border-color-info-default',
);
expect(getByText('Box content')).toHaveClass(
'box--lg:border-color-warning-default',
);
});
it('should render the Box with a borderStyle class', () => {
const { getByText } = render(
<Box borderStyle={BORDER_STYLE.SOLID}>Box content</Box>,
);
expect(getByText('Box content')).toHaveClass('box--border-style-solid');
});
it('should render the Box with the responsive borderStyle classes', () => {
const { getByText } = render(
<Box
borderStyle={[
BORDER_STYLE.SOLID,
BORDER_STYLE.DASHED,
BORDER_STYLE.NONE,
BORDER_STYLE.DOTTED,
]}
>
Box content
</Box>,
);
expect(getByText('Box content')).toHaveClass('box--border-style-solid');
expect(getByText('Box content')).toHaveClass(
'box--sm:border-style-dashed',
);
expect(getByText('Box content')).toHaveClass('box--md:border-style-none');
expect(getByText('Box content')).toHaveClass(
'box--lg:border-style-dotted',
);
});
it('should render the Box with the borderRadius class', () => {
const { getByText } = render(
<Box borderRadius={SIZES.XS}>Box content</Box>,
);
expect(getByText('Box content')).toHaveClass('box--rounded-xs');
});
it('should render the Box with the responsive borderRadius classes', () => {
const { getByText } = render(
<Box borderRadius={[SIZES.XS, SIZES.SM, SIZES.MD, SIZES.LG]}>
Box content
</Box>,
);
expect(getByText('Box content')).toHaveClass('box--rounded-xs');
expect(getByText('Box content')).toHaveClass('box--sm:rounded-sm');
expect(getByText('Box content')).toHaveClass('box--md:rounded-md');
expect(getByText('Box content')).toHaveClass('box--lg:rounded-lg');
});
});
describe('display, gap, flexDirection, flexWrap, alignItems, justifyContent', () => {
it('should render the Box with the display classes', () => {
const { getByText } = render(
<>
<Box display={DISPLAY.BLOCK}>Box display-block</Box>
<Box display={DISPLAY.FLEX}>Box display-flex</Box>
<Box display={DISPLAY.GRID}>Box display-grid</Box>
<Box display={DISPLAY.INLINE}>Box display-inline</Box>
<Box display={DISPLAY.INLINE_BLOCK}>Box display-inline-block</Box>
<Box display={DISPLAY.INLINE_FLEX}>Box display-inline-flex</Box>
<Box display={DISPLAY.INLINE_GRID}>Box display-inline-grid</Box>
<Box display={DISPLAY.LIST_ITEM}>Box display-list-item</Box>
<Box display={DISPLAY.NONE}>Box display-none</Box>
</>,
);
expect(getByText('Box display-block')).toHaveClass('box--display-block');
expect(getByText('Box display-flex')).toHaveClass('box--display-flex');
expect(getByText('Box display-grid')).toHaveClass('box--display-grid');
expect(getByText('Box display-inline')).toHaveClass(
'box--display-inline',
);
expect(getByText('Box display-inline-block')).toHaveClass(
'box--display-inline-block',
);
expect(getByText('Box display-inline-flex')).toHaveClass(
'box--display-inline-flex',
);
expect(getByText('Box display-inline-grid')).toHaveClass(
'box--display-inline-grid',
);
expect(getByText('Box display-list-item')).toHaveClass(
'box--display-list-item',
);
});
it('should render the Box with the responsive display classes', () => {
const { getByText } = render(
<>
<Box
display={[DISPLAY.BLOCK, DISPLAY.FLEX, DISPLAY.GRID, DISPLAY.NONE]}
>
Box content
</Box>
</>,
);
expect(getByText('Box content')).toHaveClass('box--display-block');
expect(getByText('Box content')).toHaveClass('box--sm:display-flex');
expect(getByText('Box content')).toHaveClass('box--md:display-grid');
expect(getByText('Box content')).toHaveClass('box--lg:display-none');
});
it('should render the Box with the gap class', () => {
const { getByText } = render(<Box gap={1}>Box content</Box>);
expect(getByText('Box content')).toHaveClass('box--gap-1');
});
it('should render the Box with the responsive gap classes', () => {
const { getByText } = render(<Box gap={[1, 2, 3, 4]}>Box content</Box>);
expect(getByText('Box content')).toHaveClass('box--gap-1');
expect(getByText('Box content')).toHaveClass('box--sm:gap-2');
expect(getByText('Box content')).toHaveClass('box--md:gap-3');
expect(getByText('Box content')).toHaveClass('box--lg:gap-4');
});
it('should render the Box with the flexDirection classes', () => {
const { getByText } = render(
<>
<Box flexDirection={FLEX_DIRECTION.ROW}>Box flex-direction-row</Box>
<Box flexDirection={FLEX_DIRECTION.ROW_REVERSE}>
Box flex-direction-row-reverse
</Box>
<Box flexDirection={FLEX_DIRECTION.COLUMN}>
Box flex-direction-column
</Box>
<Box flexDirection={FLEX_DIRECTION.COLUMN_REVERSE}>
Box flex-direction-column-reverse
</Box>
</>,
);
expect(getByText('Box flex-direction-row')).toHaveClass(
'box--flex-direction-row',
);
expect(getByText('Box flex-direction-row-reverse')).toHaveClass(
'box--flex-direction-row-reverse',
);
expect(getByText('Box flex-direction-column')).toHaveClass(
'box--flex-direction-column',
);
expect(getByText('Box flex-direction-column-reverse')).toHaveClass(
'box--flex-direction-column-reverse',
);
});
it('should render the Box with the responsive flexDirection classes', () => {
const { getByText } = render(
<>
<Box
flexDirection={[
FLEX_DIRECTION.ROW,
FLEX_DIRECTION.ROW_REVERSE,
FLEX_DIRECTION.COLUMN,
FLEX_DIRECTION.COLUMN_REVERSE,
]}
>
Box content
</Box>
</>,
);
expect(getByText('Box content')).toHaveClass('box--flex-direction-row');
expect(getByText('Box content')).toHaveClass(
'box--sm:flex-direction-row-reverse',
);
expect(getByText('Box content')).toHaveClass(
'box--md:flex-direction-column',
);
expect(getByText('Box content')).toHaveClass(
'box--lg:flex-direction-column-reverse',
);
});
it('should render the Box with the flexWrap classes', () => {
const { getByText } = render(
<>
<Box flexWrap={FLEX_WRAP.WRAP}>Box flex-wrap-wrap</Box>
<Box flexWrap={FLEX_WRAP.WRAP_REVERSE}>
Box flex-wrap-wrap-reverse
</Box>
<Box flexWrap={FLEX_WRAP.NO_WRAP}>Box flex-wrap-nowrap</Box>
</>,
);
expect(getByText('Box flex-wrap-wrap')).toHaveClass(
'box--flex-wrap-wrap',
);
expect(getByText('Box flex-wrap-wrap-reverse')).toHaveClass(
'box--flex-wrap-wrap-reverse',
);
expect(getByText('Box flex-wrap-nowrap')).toHaveClass(
'box--flex-wrap-nowrap',
);
});
it('should render the Box with the responsive flexWrap classes', () => {
const { getByText } = render(
<>
<Box
flexWrap={[
FLEX_WRAP.WRAP,
FLEX_WRAP.WRAP_REVERSE,
FLEX_WRAP.NO_WRAP,
]}
>
Box content
</Box>
</>,
);
expect(getByText('Box content')).toHaveClass('box--flex-wrap-wrap');
expect(getByText('Box content')).toHaveClass(
'box--sm:flex-wrap-wrap-reverse',
);
expect(getByText('Box content')).toHaveClass('box--md:flex-wrap-nowrap');
});
it('should render the Box with the alignItems classes', () => {
const { getByText } = render(
<>
<Box alignItems={ALIGN_ITEMS.FLEX_START}>
Box align-items-flex-start
</Box>
<Box alignItems={ALIGN_ITEMS.FLEX_END}>Box align-items-flex-end</Box>
<Box alignItems={ALIGN_ITEMS.CENTER}>Box align-items-center</Box>
<Box alignItems={ALIGN_ITEMS.BASELINE}>Box align-items-baseline</Box>
<Box alignItems={ALIGN_ITEMS.STRETCH}>Box align-items-stretch</Box>
</>,
);
expect(getByText('Box align-items-flex-start')).toHaveClass(
'box--align-items-flex-start',
);
expect(getByText('Box align-items-flex-end')).toHaveClass(
'box--align-items-flex-end',
);
expect(getByText('Box align-items-center')).toHaveClass(
'box--align-items-center',
);
expect(getByText('Box align-items-baseline')).toHaveClass(
'box--align-items-baseline',
);
expect(getByText('Box align-items-stretch')).toHaveClass(
'box--align-items-stretch',
);
});
it('should render the Box with the responsive alignItems classes', () => {
const { getByText } = render(
<>
<Box
alignItems={[
ALIGN_ITEMS.FLEX_START,
ALIGN_ITEMS.FLEX_END,
ALIGN_ITEMS.CENTER,
ALIGN_ITEMS.BASELINE,
]}
>
Box content
</Box>
</>,
);
expect(getByText('Box content')).toHaveClass(
'box--align-items-flex-start',
);
expect(getByText('Box content')).toHaveClass(
'box--sm:align-items-flex-end',
);
expect(getByText('Box content')).toHaveClass(
'box--md:align-items-center',
);
expect(getByText('Box content')).toHaveClass(
'box--lg:align-items-baseline',
);
});
it('should render the Box with the justifyContent classes', () => {
const { getByText } = render(
<>
<Box justifyContent={JUSTIFY_CONTENT.FLEX_START}>
Box justify-content-flex-start
</Box>
<Box justifyContent={JUSTIFY_CONTENT.FLEX_END}>
Box justify-content-flex-end
</Box>
<Box justifyContent={JUSTIFY_CONTENT.CENTER}>
Box justify-content-center
</Box>
<Box justifyContent={JUSTIFY_CONTENT.SPACE_AROUND}>
Box justify-content-space-around
</Box>
<Box justifyContent={JUSTIFY_CONTENT.SPACE_BETWEEN}>
Box justify-content-space-between
</Box>
<Box justifyContent={JUSTIFY_CONTENT.SPACE_EVENLY}>
Box justify-content-space-evenly
</Box>
</>,
);
expect(getByText('Box justify-content-flex-start')).toHaveClass(
'box--justify-content-flex-start',
);
expect(getByText('Box justify-content-flex-end')).toHaveClass(
'box--justify-content-flex-end',
);
expect(getByText('Box justify-content-center')).toHaveClass(
'box--justify-content-center',
);
expect(getByText('Box justify-content-space-around')).toHaveClass(
'box--justify-content-space-around',
);
expect(getByText('Box justify-content-space-between')).toHaveClass(
'box--justify-content-space-between',
);
});
it('should render the Box with the responsive justifyContent classes', () => {
const { getByText } = render(
<>
<Box
justifyContent={[
JUSTIFY_CONTENT.FLEX_START,
JUSTIFY_CONTENT.FLEX_END,
JUSTIFY_CONTENT.CENTER,
JUSTIFY_CONTENT.SPACE_AROUND,
]}
>
Box content
</Box>
</>,
);
expect(getByText('Box content')).toHaveClass(
'box--justify-content-flex-start',
);
expect(getByText('Box content')).toHaveClass(
'box--sm:justify-content-flex-end',
);
expect(getByText('Box content')).toHaveClass(
'box--md:justify-content-center',
);
expect(getByText('Box content')).toHaveClass(
'box--lg:justify-content-space-around',
);
});
});
describe('textAlign', () => {
it('should render the Box with the textAlign auto class', () => {
const { getByText } = render(
<>
<Box textAlign={TEXT_ALIGN.LEFT}>Box left</Box>
<Box textAlign={TEXT_ALIGN.CENTER}>Box center</Box>
<Box textAlign={TEXT_ALIGN.RIGHT}>Box right</Box>
<Box textAlign={TEXT_ALIGN.JUSTIFY}>Box justify</Box>
<Box textAlign={TEXT_ALIGN.END}>Box end</Box>
</>,
);
expect(getByText('Box left')).toHaveClass('box--text-align-left');
expect(getByText('Box center')).toHaveClass('box--text-align-center');
expect(getByText('Box right')).toHaveClass('box--text-align-right');
expect(getByText('Box justify')).toHaveClass('box--text-align-justify');
expect(getByText('Box end')).toHaveClass('box--text-align-end');
});
it('should render the Box with the responsive textAlign classes', () => {
const { getByText } = render(
<Box
textAlign={[
TEXT_ALIGN.LEFT,
TEXT_ALIGN.CENTER,
TEXT_ALIGN.RIGHT,
TEXT_ALIGN.JUSTIFY,
]}
>
Box content
</Box>,
);
expect(getByText('Box content')).toHaveClass('box--text-align-left');
expect(getByText('Box content')).toHaveClass('box--sm:text-align-center');
expect(getByText('Box content')).toHaveClass('box--md:text-align-right');
expect(getByText('Box content')).toHaveClass(
'box--lg:text-align-justify',
);
});
});
describe('background', () => {
it('should render the Box with the backgroundColor class', () => {
const { getByText } = render(
<Box backgroundColor={COLORS.BACKGROUND_DEFAULT}>Box content</Box>,
);
expect(getByText('Box content')).toHaveClass(
'box--background-color-background-default',
);
});
it('should render the Box with the responsive backgroundColor classes', () => {
const { getByText } = render(
<Box
backgroundColor={[
COLORS.BACKGROUND_DEFAULT,
COLORS.ERROR_DEFAULT,
COLORS.INFO_DEFAULT,
COLORS.WARNING_DEFAULT,
]}
>
Box content
</Box>,
);
expect(getByText('Box content')).toHaveClass(
'box--background-color-background-default',
);
expect(getByText('Box content')).toHaveClass(
'box--sm:background-color-error-default',
);
expect(getByText('Box content')).toHaveClass(
'box--md:background-color-info-default',
);
expect(getByText('Box content')).toHaveClass(
'box--lg:background-color-warning-default',
);
});
});
describe('width, height', () => {
it('should render the Box with the width class', () => {
const { getByText } = render(
<>
<Box width={BLOCK_SIZES.HALF}>Box half</Box>
<Box width={BLOCK_SIZES.ONE_FOURTH}>Box one fourth</Box>
<Box width={BLOCK_SIZES.MAX}>Box max</Box>
<Box width={BLOCK_SIZES.MIN}>Box min</Box>
</>,
);
expect(getByText('Box half')).toHaveClass('box--width-1/2');
expect(getByText('Box one fourth')).toHaveClass('box--width-1/4');
expect(getByText('Box max')).toHaveClass('box--width-max');
expect(getByText('Box min')).toHaveClass('box--width-min');
});
it('should render the Box with the responsive width classes', () => {
const { getByText } = render(
<>
<Box
width={[
BLOCK_SIZES.HALF,
BLOCK_SIZES.ONE_FOURTH,
BLOCK_SIZES.MAX,
BLOCK_SIZES.MIN,
]}
>
Box content
</Box>
</>,
);
expect(getByText('Box content')).toHaveClass('box--width-1/2');
expect(getByText('Box content')).toHaveClass('box--sm:width-1/4');
expect(getByText('Box content')).toHaveClass('box--md:width-max');
expect(getByText('Box content')).toHaveClass('box--lg:width-min');
});
it('should render the Box with the height class', () => {
const { getByText } = render(
<>
<Box height={BLOCK_SIZES.HALF}>Box half</Box>
<Box height={BLOCK_SIZES.ONE_FOURTH}>Box one fourth</Box>
<Box height={BLOCK_SIZES.MAX}>Box max</Box>
<Box height={BLOCK_SIZES.MIN}>Box min</Box>
</>,
);
expect(getByText('Box half')).toHaveClass('box--height-1/2');
expect(getByText('Box one fourth')).toHaveClass('box--height-1/4');
expect(getByText('Box max')).toHaveClass('box--height-max');
expect(getByText('Box min')).toHaveClass('box--height-min');
});
it('should render the Box with the responsive height classes', () => {
const { getByText } = render(
<>
<Box
height={[
BLOCK_SIZES.HALF,
BLOCK_SIZES.ONE_FOURTH,
BLOCK_SIZES.MAX,
BLOCK_SIZES.MIN,
]}
>
Box content
</Box>
</>,
);
expect(getByText('Box content')).toHaveClass('box--height-1/2');
expect(getByText('Box content')).toHaveClass('box--sm:height-1/4');
expect(getByText('Box content')).toHaveClass('box--md:height-max');
expect(getByText('Box content')).toHaveClass('box--lg:height-min');
});
});
});

@ -1,6 +1 @@
export {
default,
MultipleSizes,
ValidBackgroundColors,
ValidBorderColors,
} from './box';
export { default, MultipleSizes, MultipleSizesAndAuto } from './box';

@ -22,7 +22,7 @@ export default {
};
export const PersistentCallout = (args) => (
<Box borderColor={COLORS.BORDER_DEFAULT} padding={[8, 0, 0, 0]}>
<Box borderColor={COLORS.BORDER_DEFAULT} paddingTop={8}>
<Box margin={2}>
<Typography variant={TYPOGRAPHY.H4}>This is your private key:</Typography>
<Typography variant={TYPOGRAPHY.H6}>
@ -36,7 +36,7 @@ export const PersistentCallout = (args) => (
export const DismissibleCallout = (args) => {
const [dismissed, setDismissed] = useState(false);
return (
<Box borderColor={COLORS.BORDER_DEFAULT} padding={[8, 0, 0, 0]}>
<Box borderColor={COLORS.BORDER_DEFAULT} paddingTop={8}>
<Box margin={2}>
<Typography variant={TYPOGRAPHY.H4}>
This is your private key:
@ -81,7 +81,7 @@ export const MultipleDismissibleCallouts = () => {
};
return (
<Box borderColor={COLORS.BORDER_DEFAULT} padding={[8, 0, 0, 0]}>
<Box borderColor={COLORS.BORDER_DEFAULT} paddingTop={8}>
<Box margin={2}>
<Typography variant={TYPOGRAPHY.H4}>
This is your private key:

@ -38,7 +38,7 @@ const TextArea = ({
borderColor={COLORS.BORDER_DEFAULT}
borderRadius={SIZES.SM}
borderStyle={BORDER_STYLE.SOLID}
padding={[4, 4]}
padding={4}
width={BLOCK_SIZES.FULL}
{...boxProps}
>

@ -9,7 +9,7 @@ import {
TYPOGRAPHY,
OVERFLOW_WRAP,
} from '../../../helpers/constants/design-system';
import Box, { MultipleSizes } from '../box';
import Box, { MultipleSizesAndAuto } from '../box';
const { H6, H7, H8, H9 } = TYPOGRAPHY;
@ -58,7 +58,11 @@ export default function Typography({
overflowWrap,
title,
tag,
margin = [1, 0],
margin,
marginTop = 1,
marginRight,
marginBottom = 1,
marginLeft,
boxProps = {},
className,
children,
@ -90,7 +94,16 @@ export default function Typography({
}
return (
<Box margin={margin} {...boxProps}>
<Box
{...{
margin,
marginTop,
marginRight,
marginBottom,
marginLeft,
...boxProps,
}}
>
{(boxClassName) => (
<Tag
className={classnames(boxClassName, computedClassName)}
@ -138,10 +151,13 @@ Typography.propTypes = {
*/
tag: PropTypes.oneOf(ValidTags),
/**
* Adds margin to the Typography component should use valid sizes
* 1,2,4,6,8 or an array of those values
* Adds margin to the Typography component should use valid size
*/
margin: MultipleSizes,
margin: MultipleSizesAndAuto,
marginTop: MultipleSizesAndAuto,
marginBottom: MultipleSizesAndAuto,
marginRight: MultipleSizesAndAuto,
marginLeft: MultipleSizesAndAuto,
/**
* Used to pass any valid Box component props such as margin or padding
* to the Typography component

@ -38,11 +38,11 @@ $fractions: (
$sizes-numeric: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12;
$sizes-strings: xs, sm, md, lg, xl, none;
$sizes-strings: xs, sm, md, lg, xl;
$border-style: solid, double, none, dashed, dotted;
$directions: top, right, bottom, left;
$display: block, grid, flex, inline-block, inline-grid, inline-flex, list-item;
$display: block, flex, grid, inline-block, inline-grid, inline-flex, list-item, none;
$text-align: left, right, center, justify, end;
$overflow-wrap: normal, break-word;
$font-weight: bold, normal, 100, 200, 300, 400, 500, 600, 700, 800, 900;

@ -65,3 +65,9 @@ DEPRECATED
$break-small: 575px;
$break-midpoint: 780px;
$break-large: 576px;
$screen-sizes-map: (
'sm': 576px,
'md': 768px,
'lg': 1280px,
);

@ -127,9 +127,11 @@ export const DISPLAY = {
FLEX: 'flex',
GRID: 'grid',
INLINE_BLOCK: 'inline-block',
INLINE: 'inline',
INLINE_FLEX: 'inline-flex',
INLINE_GRID: 'inline-grid',
LIST_ITEM: 'list-item',
NONE: 'none',
};
export const FRACTIONS = {
@ -207,3 +209,5 @@ export const RESIZE = {
INITIAL: 'initial',
INHERIT: 'inherit',
};
export const BREAKPOINTS = ['base', 'sm', 'md', 'lg'];

@ -59,7 +59,7 @@ const TransactionAlerts = ({
<Typography
align="left"
className="transaction-alerts__pending-transactions"
margin={[0, 0]}
margin={0}
tag={TYPOGRAPHY.Paragraph}
variant={TYPOGRAPHY.H7}
>
@ -127,7 +127,7 @@ const TransactionAlerts = ({
message={
<Typography
align="left"
margin={[0, 0]}
margin={0}
tag={TYPOGRAPHY.Paragraph}
variant={TYPOGRAPHY.H7}
>
@ -144,7 +144,7 @@ const TransactionAlerts = ({
message={
<Typography
align="left"
margin={[0, 0]}
margin={0}
tag={TYPOGRAPHY.Paragraph}
variant={TYPOGRAPHY.H7}
>

@ -202,7 +202,10 @@ export default function ConfirmationPage() {
<Box
alignItems="center"
marginTop={1}
padding={[1, 4, 4]}
paddingTop={1}
paddingRight={4}
paddingLeft={4}
paddingBottom={4}
flexDirection={FLEX_DIRECTION.COLUMN}
>
<SiteOrigin

@ -488,12 +488,15 @@ export default class Home extends PureComponent {
<i className="fa fa-check-circle fa-2x home__new-network-added__check-circle" />
<Typography
variant={TYPOGRAPHY.H4}
margin={[5, 9, 0, 9]}
marginTop={5}
marginRight={9}
marginLeft={9}
marginBottom={0}
fontWeight={FONT_WEIGHT.BOLD}
>
{t('networkAddedSuccessfully')}
</Typography>
<Box margin={[8, 8, 5, 8]}>
<Box marginTop={8} marginRight={8} marginLeft={8} marginBottom={5}>
<Button
type="primary"
className="home__new-network-added__switch-to-button"

@ -78,7 +78,11 @@ class RestoreVaultPage extends Component {
<Typography color={COLORS.TEXT_DEFAULT}>
{t('resetWalletSubHeader')}
</Typography>
<Typography color={COLORS.TEXT_DEFAULT} margin={[4, 0]}>
<Typography
color={COLORS.TEXT_DEFAULT}
marginTop={4}
marginBottom={4}
>
{t('resetWalletUsingSRP', [
<Button
type="link"
@ -112,7 +116,7 @@ class RestoreVaultPage extends Component {
</Button>,
])}
</Typography>
<Typography color={COLORS.TEXT_DEFAULT} margin={[0, 0, 4]}>
<Typography color={COLORS.TEXT_DEFAULT} margin={0} marginBottom={4}>
{t('resetWalletWarning')}
</Typography>
<CreateNewVault

@ -225,7 +225,10 @@ export default class SettingsTab extends PureComponent {
<Typography
color={COLORS.TEXT_DEFAULT}
variant={TYPOGRAPHY.H7}
margin={[0, 12, 0, 3]}
marginTop={0}
marginRight={12}
marginBottom={0}
marginLeft={3}
>
{t('jazzicons')}
</Typography>
@ -253,7 +256,8 @@ export default class SettingsTab extends PureComponent {
<Typography
color={COLORS.TEXT_DEFAULT}
variant={TYPOGRAPHY.H7}
margin={[0, 0, 0, 3]}
margin={0}
marginBottom={3}
>
{t('blockies')}
</Typography>

@ -47,7 +47,9 @@ export default function ImportToken({
footer={ImportTokenModalFooter}
>
<Box
padding={[0, 6, 4, 6]}
paddingRight={6}
paddingBottom={4}
paddingLeft={4}
alignItems={ALIGN_ITEMS.CENTER}
display={DISPLAY.FLEX}
className="import-token"

@ -70,7 +70,8 @@ export default function TokenDetailsPage() {
<Box marginLeft={5} marginRight={6}>
<Typography
fontWeight={FONT_WEIGHT.BOLD}
margin={[4, 0, 0, 0]}
margin={0}
marginTop={4}
variant={TYPOGRAPHY.H6}
color={COLORS.TEXT_DEFAULT}
className="token-details__title"
@ -86,7 +87,8 @@ export default function TokenDetailsPage() {
<Typography
align={TEXT_ALIGN.CENTER}
fontWeight={FONT_WEIGHT.BOLD}
margin={[0, 5, 0, 0]}
margin={0}
marginRight={5}
variant={TYPOGRAPHY.H4}
color={COLORS.TEXT_DEFAULT}
className="token-details__token-value"
@ -102,14 +104,16 @@ export default function TokenDetailsPage() {
</Box>
</Box>
<Typography
margin={[4, 0, 0, 0]}
margin={0}
marginTop={4}
variant={TYPOGRAPHY.H7}
color={COLORS.TEXT_ALTERNATIVE}
>
{tokenCurrencyBalance || ''}
</Typography>
<Typography
margin={[6, 0, 0, 0]}
margin={0}
marginTop={6}
variant={TYPOGRAPHY.H9}
color={COLORS.TEXT_ALTERNATIVE}
fontWeight={FONT_WEIGHT.BOLD}
@ -119,7 +123,8 @@ export default function TokenDetailsPage() {
<Box display={DISPLAY.FLEX}>
<Typography
variant={TYPOGRAPHY.H7}
margin={[2, 0, 0, 0]}
margin={0}
marginTop={2}
color={COLORS.TEXT_DEFAULT}
overflowWrap={OVERFLOW_WRAP.BREAK_WORD}
className="token-details__token-address"
@ -144,7 +149,8 @@ export default function TokenDetailsPage() {
</Box>
<Typography
variant={TYPOGRAPHY.H9}
margin={[4, 0, 0, 0]}
margin={0}
marginTop={4}
color={COLORS.TEXT_ALTERNATIVE}
fontWeight={FONT_WEIGHT.BOLD}
>
@ -152,14 +158,16 @@ export default function TokenDetailsPage() {
</Typography>
<Typography
variant={TYPOGRAPHY.H7}
margin={[1, 0, 0, 0]}
margin={0}
marginTop={1}
color={COLORS.TEXT_DEFAULT}
>
{token.decimals}
</Typography>
<Typography
variant={TYPOGRAPHY.H9}
margin={[4, 0, 0, 0]}
margin={0}
marginTop={4}
color={COLORS.TEXT_ALTERNATIVE}
fontWeight={FONT_WEIGHT.BOLD}
>
@ -167,7 +175,8 @@ export default function TokenDetailsPage() {
</Typography>
<Typography
variant={TYPOGRAPHY.H7}
margin={[1, 0, 0, 0]}
margin={1}
marginTop={0}
color={COLORS.TEXT_DEFAULT}
>
{networkType === NETWORK_TYPE_RPC
@ -178,7 +187,8 @@ export default function TokenDetailsPage() {
<>
<Typography
variant={TYPOGRAPHY.H9}
margin={[4, 0, 0, 0]}
margin={0}
marginTop={4}
color={COLORS.TEXT_ALTERNATIVE}
fontWeight={FONT_WEIGHT.BOLD}
>
@ -186,7 +196,8 @@ export default function TokenDetailsPage() {
</Typography>
<Typography
variant={TYPOGRAPHY.H7}
margin={[1, 0, 0, 0]}
margin={0}
marginTop={1}
color={COLORS.TEXT_DEFAULT}
>
{`${aggregators}.`}

Loading…
Cancel
Save