diff --git a/ui/components/component-library/box/README.mdx b/ui/components/component-library/box/README.mdx new file mode 100644 index 000000000..1b2ee880f --- /dev/null +++ b/ui/components/component-library/box/README.mdx @@ -0,0 +1,368 @@ +import { Story, Canvas, ArgsTable } from '@storybook/addon-docs'; + +import { Box } from './box'; + +# Box + +The `Box` is a utility component that accepts many helper props to make styling easier. + + + + + +## Props + + + +## Usage + +The following describes the props and example usage for this component. + +### Margin + +The margin props `margin`, `marginTop`, `marginRight`, `marginBottom`, `marginLeft`, `marginInline`, `marginInlineStart`, and `marginInlineEnd` 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 + + + + + +```jsx + + + + + + + + + +// Responsive props + + + + + + + + +``` + +### Padding + +The padding props work very similarly to margin. The padding props `padding`, `paddingTop`, `paddingRight`, `paddingBottom`, `paddingLeft`, `paddingInline`, `paddingInlineStart`, and `paddingInlineEnd` 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 + + + + + +```jsx + + + + + + +// Responsive props + + + + + +``` + +### 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.InlineBlock` +- `Display.InlineFlex` +- `Display.InlineGrid` +- `Display.Inline` +- `Display.ListItem` +- `Display.None` + +or array of these values. + +```jsx +import { Display } from '../../../helpers/constants/design-system'; +import Box from '../ui/box'; + + + + + + + + +``` + +### Color + +The `color` prop can be used to set the color of the content in Box component. The `color` prop accepts [responsive props](#responsive-props) in the form of array props. Defaults to `Color.textDefault`. + + + + + +Example of importing `TextColor` object with `Box` component + +```jsx +import { TextColor } from '../../../helpers/constants/design-system'; +import Box from '../ui/box'; + +Text goes here; +``` + +### Background Color + +Use the `backgroundColor` prop along with the `Color` or `BackgroundColor` 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. + + + + + +Example of importing `BackgroundColor` object with `Box` component + +```jsx +import { + BackgroundColor, + TextColor, +} from '../../../helpers/constants/design-system'; +import Box from '../ui/box'; + + + + BackgroundColor.backgroundDefault + +; +``` + +### Border Color + +Use the `borderColor` prop along with the `Color` or `BorderColor` 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. + + + + + +Example of importing `BorderColor` object with `Box` component + +```jsx +import { + BackgroundColor, + BorderColor, + TextColor, +} from '../../../helpers/constants/design-system'; +import Box from '../ui/box'; + + + + BorderColor.borderDefault + +; +``` + +### Border Radius + +Use the `borderRadius` prop along with the `BorderRadius` object from `ui/helpers/constants/design-system.js` to change border radius. The `borderRadius` prop accepts [responsive props](#responsive-props) in the form of array props. + + + + + +Example of importing `BorderRadius` object with `Box` component + +```jsx +import { BorderRadius } from '../../../helpers/constants/design-system'; +import Box from '../ui/box'; + +BorderRadius.none 0px +BorderRadius.XS 2px +BorderRadius.SM 4px +BorderRadius.MD 6px +BorderRadius.LG 8px +BorderRadius.XL 12px +BorderRadius.pill 9999px +BorderRadius.full 50% +``` + +### 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. `` + +``` +// the responsive props + + +// is equivalent to the css +.box { + display: block; + + @media screen and (max-width: $breakpoint-sm) { + display: flex; + } +} +``` + + + + + +```jsx +import { + BorderColor, + BackgroundColor, +} from '../../../helpers/constants/design-system'; +import Box from '../ui/box'; + + + + responsive + + + props + + + example + +; +``` + +### As + +The polymorphic `as` prop allows you to change the root HTML element of the Box component. Defaults to `'div'` + + + + + +```jsx +import Box from '../../ui/box'; + +div(default) +ul +li +button +header +``` + +### Width + +Use the `width` prop to pass a singular `BlockSize` or for a responsive width pass an array up to 4 `BlockSize` + +Responsive widths go from smallest to largest screen sizes + +Example: [BlockSize.Half, BlockSize.ThreeFourths, BlockSize.OneFifth, BlockSize.ThreeSixths] + +- BlockSize.Half is the default width for `base screen size (0px)` and up +- BlockSize.ThreeFourths is the width for `small screen size (576px) ` and up +- BlockSize.OneFifth is the width for `medium screen size (768px)` and up +- BlockSize.ThreeSixths is the width for `large screen size (1280px)` and up + + + + + +```jsx +import { + BlockSize, + Display, + FlexWrap, +} from '../../../helpers/constants/design-system'; +import Box from '../../ui/box'; + +<> +

Static widths

+ + + BlockSize.Full + BlockSize.Half + BlockSize.Half + BlockSize.OneThird + BlockSize.OneThird + BlockSize.OneThird + BlockSize.OneFourth + BlockSize.OneFourth + BlockSize.OneFourth + BlockSize.OneFourth + + +

Responsive widths

+ + + + BlockSize.Full, BlockSize.Half, BlockSize.OneThird, BlockSize.OneFourth, + + + BlockSize.Full, BlockSize.Half, BlockSize.OneThird, BlockSize.OneFourth, + + + BlockSize.Full, BlockSize.Half, BlockSize.OneThird, BlockSize.OneFourth, + + + BlockSize.Full, BlockSize.Half, BlockSize.OneThird, BlockSize.OneFourth, + + +; +``` diff --git a/ui/components/component-library/box/box.scss b/ui/components/component-library/box/box.scss new file mode 100644 index 000000000..841afe88c --- /dev/null +++ b/ui/components/component-library/box/box.scss @@ -0,0 +1,402 @@ +@use "sass:list"; +@use "sass:map"; +@use "design-system"; +@use "utilities"; + +$attributes: padding, margin, gap; +$extraProperties: auto; +$attributesToApplyExtraProperties: margin; + +.mm-box { + // Padding, Margin, and Gap + @each $attribute in $attributes { + @each $size in design-system.$sizes-numeric { + &--#{$attribute}-#{$size} { + #{$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 { + &--#{$attribute}-#{$direction}-#{$size} { + #{$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) { + @each $property in $extraProperties { + &--#{$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-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; + } + } + } + } + // border-radius + @each $radius, $value in design-system.$border-radius { + &--rounded-#{$radius} { + border-radius: $value; + } + } + // breakpoint classes + @each $breakpoint, $min-width in $screen-sizes-map { + @each $radius, $value in design-system.$border-radius { + @media screen and (min-width: $min-width) { + &--#{$breakpoint}\:rounded-#{$radius} { + border-radius: $value; + } + } + } + } + + // 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%; + } + + + &--height-full { + height: 100%; + } + + @each $fraction, $value in design-system.$fractions { + &--width-#{$fraction} { + width: $value; + } + + &--height-#{$fraction} { + 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; + } + } + } + } + + // breakpoint classes + @each $breakpoint, $min-width in $screen-sizes-map { + @media screen and (min-width: $min-width) { + &--#{$breakpoint}\:width-full { + width: 100%; + } + } + } + + // breakpoint classes + @each $breakpoint, $min-width in $screen-sizes-map { + @media screen and (min-width: $min-width) { + &--#{$breakpoint}\:height-full { + height: 100%; + } + } + } + + &--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 { + &--text-align-#{$alignment} { + 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 { + &--background-color-#{$variant} { + 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); + } + } + } + } + + // color + @each $variant, $color in design-system.$color-map { + &--color-#{$variant} { + 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}\color-#{$variant} { + color: var($color); + } + } + } + } +} diff --git a/ui/components/component-library/box/box.stories.tsx b/ui/components/component-library/box/box.stories.tsx new file mode 100644 index 000000000..c9d14bc4a --- /dev/null +++ b/ui/components/component-library/box/box.stories.tsx @@ -0,0 +1,956 @@ +import React from 'react'; +import { StoryFn, Meta } from '@storybook/react'; + +import { + BlockSize, + BorderStyle, + BorderRadius, + TextColor, + BorderColor, + BackgroundColor, + Display, + AlignItems, + JustifyContent, + TextAlign, + FlexDirection, + FlexWrap, +} from '../../../helpers/constants/design-system'; + +import { Text } from '..'; + +import { Box } from './box'; + +import README from './README.mdx'; + +const sizeControlOptions = [ + undefined, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, +]; +const marginSizeControlOptions = [...sizeControlOptions, 'auto']; + +export default { + title: 'Components/ComponentLibrary/Box', + component: Box, + parameters: { + docs: { + page: README, + }, + }, + argTypes: { + children: { + table: { category: 'children' }, + }, + display: { + options: Object.values(Display), + control: 'select', + table: { category: 'display' }, + }, + width: { + options: Object.values(BlockSize), + control: 'multi-select', + table: { category: 'display' }, + }, + height: { + options: Object.values(BlockSize), + control: 'select', + table: { category: 'display' }, + }, + gap: { + control: 'select', + options: sizeControlOptions, + table: { category: 'display' }, + }, + backgroundColor: { + options: Object.values(BackgroundColor), + control: 'select', + table: { + category: 'background', + }, + }, + color: { + options: Object.values(TextColor), + control: 'select', + table: { category: 'color' }, + }, + borderStyle: { + options: Object.values(BorderStyle), + control: 'select', + table: { category: 'border' }, + }, + borderWidth: { + options: sizeControlOptions, + control: 'select', + table: { category: 'border' }, + }, + borderColor: { + options: Object.values(BorderColor), + control: 'select', + table: { category: 'border' }, + }, + borderRadius: { + options: Object.values(BorderRadius), + control: 'select', + table: { category: 'border' }, + }, + flexWrap: { + options: Object.values(FlexWrap), + control: 'select', + table: { category: 'display' }, + }, + flexDirection: { + options: Object.values(FlexDirection), + control: 'select', + table: { category: 'display' }, + }, + justifyContent: { + options: Object.values(JustifyContent), + control: 'select', + table: { category: 'display' }, + }, + alignItems: { + options: Object.values(AlignItems), + control: 'select', + table: { category: 'display' }, + }, + textAlign: { + options: Object.values(TextAlign), + control: 'select', + table: { category: 'text' }, + }, + margin: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'margin' }, + }, + marginTop: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'margin' }, + }, + marginRight: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'margin' }, + }, + marginBottom: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'margin' }, + }, + marginLeft: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'margin' }, + }, + marginInline: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'margin' }, + }, + marginInlineStart: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'margin' }, + }, + marginInlineEnd: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'margin' }, + }, + padding: { + options: sizeControlOptions, + control: 'select', + table: { category: 'padding' }, + }, + paddingTop: { + options: sizeControlOptions, + control: 'select', + table: { category: 'padding' }, + }, + paddingRight: { + options: sizeControlOptions, + control: 'select', + table: { category: 'padding' }, + }, + paddingBottom: { + options: sizeControlOptions, + control: 'select', + table: { category: 'padding' }, + }, + paddingLeft: { + options: sizeControlOptions, + control: 'select', + table: { category: 'padding' }, + }, + paddingInline: { + options: sizeControlOptions, + control: 'select', + table: { category: 'padding' }, + }, + paddingInlineStart: { + options: sizeControlOptions, + control: 'select', + table: { category: 'padding' }, + }, + paddingInlineEnd: { + options: sizeControlOptions, + control: 'select', + table: { category: 'padding' }, + }, + as: { + control: 'select', + options: ['div', 'ul', 'li', 'span', 'a', 'button'], + table: { category: 'as (root html element)' }, + }, + }, +} as Meta; + +export const BoxDefaultStory: StoryFn = (args) => ; + +BoxDefaultStory.args = { + children: 'Box component', + display: Display.Flex, + justifyContent: JustifyContent.center, + alignItems: AlignItems.center, + width: BlockSize.Half, + height: BlockSize.Half, + borderColor: BorderColor.borderDefault, + padding: 4, +}; + +BoxDefaultStory.storyName = 'Default'; + +export const Margin: StoryFn = (args) => { + return ( + + + Static margin + + + Responsive margin changes based on breakpoint + + + ); +}; + +export const Padding: StoryFn = (args) => { + return ( + + + Static padding + + + Responsive padding changes based on breakpoint + + + ); +}; + +export const ColorStory: StoryFn = (args) => { + return ( + <> + + TextColor.textDefault + + + TextColor.textAlternative + + + TextColor.textMuted + + + TextColor.primaryDefault + + + TextColor.primaryInverse + + + TextColor.errorDefault + + + TextColor.errorInverse + + + TextColor.successDefault + + + TextColor.successInverse + + + TextColor.warningDefault + + + TextColor.warningInverse + + + TextColor.infoDefault + + + TextColor.infoInverse + + + TextColor.inherit + + + TextColor.sepoliaInverse + + + TextColor.goerliInverse + + + ); +}; +ColorStory.storyName = 'Color'; + +export const BackgroundColorStory = () => { + return ( + <> + + + BackgroundColor.backgroundDefault + + + + + BackgroundColor.backgroundAlternative + + + + + BackgroundColor.overlayDefault + + + + + BackgroundColor.primaryDefault + + + + BackgroundColor.primaryMuted + + + BackgroundColor.errorDefault + + + BackgroundColor.errorMuted + + + + BackgroundColor.successDefault + + + + BackgroundColor.successMuted + + + + BackgroundColor.warningDefault + + + + BackgroundColor.warningMuted + + + BackgroundColor.sepolia + + + BackgroundColor.goerli + + + ); +}; +BackgroundColorStory.storyName = 'BackgroundColor'; + +export const BorderColorStory = () => { + return ( + <> + + BorderColor.borderDefault + + + BorderColor.borderMuted + + + BorderColor.primaryDefault + + + BorderColor.errorDefault + + + BorderColor.successDefault + + + BorderColor.warningDefault + + + ); +}; +BorderColorStory.storyName = 'BorderColor'; + +export const BorderRadiusStory = () => { + return ( + <> + + + BorderRadius.NONE 0px + + + BorderRadius.XS 2px + + + BorderRadius.SM 4px + + + BorderRadius.MD 6px + + + BorderRadius.LG 8px + + + BorderRadius.XL 12px + + + BorderRadius.pill 9999px + + + + BorderRadius.full 50% + + + ); +}; +BorderRadiusStory.storyName = 'BorderRadius'; + +export const ResponsiveProps = () => { + return ( + <> + + Responsive props example. Stacks vertically on small screens and aligns + horizontally on large screens. Padding is also adjusted between small + and large screens + + + + responsive + + + props + + + example + + + Responsive Border Radius 1 + + + Responsive Border Radius 2 + + + + ); +}; + +export const As: StoryFn = (args) => { + return ( + <> + + You can change the root element of the Box component using the as prop. + Inspect the below elements to see the underlying HTML elements + + div(default) + + Box as 'button' tag + +
+ + Box as 'button' tag and disabled + +
+ + Box as 'a' tag with href + +
+ + Box as 'p' tag with href and data-testid + +
+ + Box as 'p' tag and disabled + +
+ Box as 'span' tag (default) +
+ Box as 'p' tag +
+ Box as 'li' tag +
+ Box as 'h1' tag + + ); +}; + +export const Width: StoryFn = () => { + const getColumns = (): JSX.Element[] => { + const content: JSX.Element[] = []; + for (let i = 0; i < 12; i++) { + content.push( + , + ); + } + return content; + }; + + return ( + <> +

+ Static widths +

+ + {getColumns()} + + + + BlockSize.Full + + + BlockSize.Half + + + BlockSize.Half + + + BlockSize.OneThird + + + BlockSize.OneThird + + + BlockSize.OneThird + + + BlockSize.OneFourth + + + BlockSize.OneFourth + + + BlockSize.OneFourth + + + BlockSize.OneFourth + + + +

+ Responsive widths +

+ + {getColumns()} + + + + BlockSize.Full, BlockSize.Half, BlockSize.OneThird, + BlockSize.OneFourth, + + + BlockSize.Full, BlockSize.Half, BlockSize.OneThird, + BlockSize.OneFourth, + + + BlockSize.Full, BlockSize.Half, BlockSize.OneThird, + BlockSize.OneFourth, + + + BlockSize.Full, BlockSize.Half, BlockSize.OneThird, + BlockSize.OneFourth, + + + + + ); +}; diff --git a/ui/components/component-library/box/box.test.tsx b/ui/components/component-library/box/box.test.tsx new file mode 100644 index 000000000..e49eddcff --- /dev/null +++ b/ui/components/component-library/box/box.test.tsx @@ -0,0 +1,2044 @@ +import * as React from 'react'; +import { render } from '@testing-library/react'; +import { + BorderStyle, + Display, + FlexDirection, + FlexWrap, + AlignItems, + JustifyContent, + TextAlign, + BlockSize, + BorderRadius, + BorderColor, + BackgroundColor, + TextColor, +} from '../../../helpers/constants/design-system'; + +import { Box } from '.'; + +describe('Box', () => { + it('should render the Box without crashing', () => { + const { getByText } = render(Box content); + + expect(getByText('Box content')).toBeDefined(); + }); + describe('margin', () => { + it('should render the Box with the margin classes', () => { + const { getByText } = render( + <> + Box margin 0 + Box margin 1 + Box margin 2 + Box margin 3 + Box margin 4 + Box margin 5 + Box margin 6 + Box margin 7 + Box margin 8 + Box margin 9 + Box margin 10 + Box margin 11 + Box margin 12 + Box margin auto + , + ); + + expect(getByText('Box margin 0')).toHaveClass('mm-box--margin-0'); + expect(getByText('Box margin 1')).toHaveClass('mm-box--margin-1'); + expect(getByText('Box margin 2')).toHaveClass('mm-box--margin-2'); + expect(getByText('Box margin 3')).toHaveClass('mm-box--margin-3'); + expect(getByText('Box margin 4')).toHaveClass('mm-box--margin-4'); + expect(getByText('Box margin 5')).toHaveClass('mm-box--margin-5'); + expect(getByText('Box margin 6')).toHaveClass('mm-box--margin-6'); + expect(getByText('Box margin 7')).toHaveClass('mm-box--margin-7'); + expect(getByText('Box margin 8')).toHaveClass('mm-box--margin-8'); + expect(getByText('Box margin 9')).toHaveClass('mm-box--margin-9'); + expect(getByText('Box margin 10')).toHaveClass('mm-box--margin-10'); + expect(getByText('Box margin 11')).toHaveClass('mm-box--margin-11'); + expect(getByText('Box margin 12')).toHaveClass('mm-box--margin-12'); + expect(getByText('Box margin auto')).toHaveClass('mm-box--margin-auto'); + }); + it('should render the Box with the responsive margin classes', () => { + const { getByText } = render( + <> + Box margin 0 + Box margin 1 + Box margin 2 + Box margin 3 + Box margin 4 + Box margin 5 + Box margin 6 + Box margin 7 + Box margin 8 + Box margin 9 + Box margin 10 + Box margin 11 + Box margin 12 + Box margin auto + , + ); + expect(getByText('Box margin 0')).toHaveClass( + 'mm-box--margin-0 mm-box--sm:margin-0 mm-box--md:margin-0 mm-box--lg:margin-0', + ); + expect(getByText('Box margin 1')).toHaveClass( + 'mm-box--margin-1 mm-box--sm:margin-1 mm-box--md:margin-1 mm-box--lg:margin-1', + ); + expect(getByText('Box margin 2')).toHaveClass( + 'mm-box--margin-2 mm-box--sm:margin-2 mm-box--md:margin-2 mm-box--lg:margin-2', + ); + expect(getByText('Box margin 3')).toHaveClass( + 'mm-box--margin-3 mm-box--sm:margin-3 mm-box--md:margin-3 mm-box--lg:margin-3', + ); + expect(getByText('Box margin 4')).toHaveClass( + 'mm-box--margin-4 mm-box--sm:margin-4 mm-box--md:margin-4 mm-box--lg:margin-4', + ); + expect(getByText('Box margin 5')).toHaveClass( + 'mm-box--margin-5 mm-box--sm:margin-5 mm-box--md:margin-5 mm-box--lg:margin-5', + ); + expect(getByText('Box margin 6')).toHaveClass( + 'mm-box--margin-6 mm-box--sm:margin-6 mm-box--md:margin-6 mm-box--lg:margin-6', + ); + expect(getByText('Box margin 7')).toHaveClass( + 'mm-box--margin-7 mm-box--sm:margin-7 mm-box--md:margin-7 mm-box--lg:margin-7', + ); + expect(getByText('Box margin 8')).toHaveClass( + 'mm-box--margin-8 mm-box--sm:margin-8 mm-box--md:margin-8 mm-box--lg:margin-8', + ); + expect(getByText('Box margin 9')).toHaveClass( + 'mm-box--margin-9 mm-box--sm:margin-9 mm-box--md:margin-9 mm-box--lg:margin-9', + ); + expect(getByText('Box margin 10')).toHaveClass( + 'mm-box--margin-10 mm-box--sm:margin-10 mm-box--md:margin-10 mm-box--lg:margin-10', + ); + expect(getByText('Box margin 11')).toHaveClass( + 'mm-box--margin-11 mm-box--sm:margin-11 mm-box--md:margin-11 mm-box--lg:margin-11', + ); + expect(getByText('Box margin 12')).toHaveClass( + 'mm-box--margin-12 mm-box--sm:margin-12 mm-box--md:margin-12 mm-box--lg:margin-12', + ); + + expect(getByText('Box margin auto')).toHaveClass( + 'mm-box--margin-auto mm-box--sm:margin-auto mm-box--md:margin-auto mm-box--lg:margin-auto', + ); + }); + it('should render the Box with the marginTop classes', () => { + const { getByText } = render( + <> + Box marginTop 0 + Box marginTop 1 + Box marginTop 2 + Box marginTop 3 + Box marginTop 4 + Box marginTop 5 + Box marginTop 6 + Box marginTop 7 + Box marginTop 8 + Box marginTop 9 + Box marginTop 10 + Box marginTop 11 + Box marginTop 12 + Box marginTop auto + , + ); + + expect(getByText('Box marginTop 0')).toHaveClass('mm-box--margin-top-0'); + expect(getByText('Box marginTop 1')).toHaveClass('mm-box--margin-top-1'); + expect(getByText('Box marginTop 2')).toHaveClass('mm-box--margin-top-2'); + expect(getByText('Box marginTop 3')).toHaveClass('mm-box--margin-top-3'); + expect(getByText('Box marginTop 4')).toHaveClass('mm-box--margin-top-4'); + expect(getByText('Box marginTop 5')).toHaveClass('mm-box--margin-top-5'); + expect(getByText('Box marginTop 6')).toHaveClass('mm-box--margin-top-6'); + expect(getByText('Box marginTop 7')).toHaveClass('mm-box--margin-top-7'); + expect(getByText('Box marginTop 8')).toHaveClass('mm-box--margin-top-8'); + expect(getByText('Box marginTop 9')).toHaveClass('mm-box--margin-top-9'); + expect(getByText('Box marginTop 10')).toHaveClass( + 'mm-box--margin-top-10', + ); + expect(getByText('Box marginTop 11')).toHaveClass( + 'mm-box--margin-top-11', + ); + expect(getByText('Box marginTop 12')).toHaveClass( + 'mm-box--margin-top-12', + ); + expect(getByText('Box marginTop auto')).toHaveClass( + 'mm-box--margin-top-auto', + ); + }); + it('should render the Box with the responsive marginTop classes', () => { + const { getByText } = render( + <> + Box marginTop 0 + Box marginTop 1 + Box marginTop 2 + Box marginTop 3 + Box marginTop 4 + Box marginTop 5 + Box marginTop 6 + Box marginTop 7 + Box marginTop 8 + Box marginTop 9 + Box marginTop 10 + Box marginTop 11 + Box marginTop 12 + + Box marginTop auto + + , + ); + expect(getByText('Box marginTop 0')).toHaveClass( + 'mm-box--margin-top-0 mm-box--sm:margin-top-0 mm-box--md:margin-top-0 mm-box--lg:margin-top-0', + ); + expect(getByText('Box marginTop 1')).toHaveClass( + 'mm-box--margin-top-1 mm-box--sm:margin-top-1 mm-box--md:margin-top-1 mm-box--lg:margin-top-1', + ); + expect(getByText('Box marginTop 2')).toHaveClass( + 'mm-box--margin-top-2 mm-box--sm:margin-top-2 mm-box--md:margin-top-2 mm-box--lg:margin-top-2', + ); + expect(getByText('Box marginTop 3')).toHaveClass( + 'mm-box--margin-top-3 mm-box--sm:margin-top-3 mm-box--md:margin-top-3 mm-box--lg:margin-top-3', + ); + expect(getByText('Box marginTop 4')).toHaveClass( + 'mm-box--margin-top-4 mm-box--sm:margin-top-4 mm-box--md:margin-top-4 mm-box--lg:margin-top-4', + ); + expect(getByText('Box marginTop 5')).toHaveClass( + 'mm-box--margin-top-5 mm-box--sm:margin-top-5 mm-box--md:margin-top-5 mm-box--lg:margin-top-5', + ); + expect(getByText('Box marginTop 6')).toHaveClass( + 'mm-box--margin-top-6 mm-box--sm:margin-top-6 mm-box--md:margin-top-6 mm-box--lg:margin-top-6', + ); + expect(getByText('Box marginTop 7')).toHaveClass( + 'mm-box--margin-top-7 mm-box--sm:margin-top-7 mm-box--md:margin-top-7 mm-box--lg:margin-top-7', + ); + expect(getByText('Box marginTop 8')).toHaveClass( + 'mm-box--margin-top-8 mm-box--sm:margin-top-8 mm-box--md:margin-top-8 mm-box--lg:margin-top-8', + ); + expect(getByText('Box marginTop 9')).toHaveClass( + 'mm-box--margin-top-9 mm-box--sm:margin-top-9 mm-box--md:margin-top-9 mm-box--lg:margin-top-9', + ); + expect(getByText('Box marginTop 10')).toHaveClass( + 'mm-box--margin-top-10 mm-box--sm:margin-top-10 mm-box--md:margin-top-10 mm-box--lg:margin-top-10', + ); + expect(getByText('Box marginTop 11')).toHaveClass( + 'mm-box--margin-top-11 mm-box--sm:margin-top-11 mm-box--md:margin-top-11 mm-box--lg:margin-top-11', + ); + expect(getByText('Box marginTop 12')).toHaveClass( + 'mm-box--margin-top-12 mm-box--sm:margin-top-12 mm-box--md:margin-top-12 mm-box--lg:margin-top-12', + ); + + expect(getByText('Box marginTop auto')).toHaveClass( + 'mm-box--margin-top-auto mm-box--sm:margin-top-auto mm-box--md:margin-top-auto mm-box--lg:margin-top-auto', + ); + }); + it('should render the Box with the marginRight classes', () => { + const { getByText } = render( + <> + Box marginRight 0 + Box marginRight 1 + Box marginRight 2 + Box marginRight 3 + Box marginRight 4 + Box marginRight 5 + Box marginRight 6 + Box marginRight 7 + Box marginRight 8 + Box marginRight 9 + Box marginRight 10 + Box marginRight 11 + Box marginRight 12 + Box marginRight auto + , + ); + + expect(getByText('Box marginRight 0')).toHaveClass( + 'mm-box--margin-right-0', + ); + expect(getByText('Box marginRight 1')).toHaveClass( + 'mm-box--margin-right-1', + ); + expect(getByText('Box marginRight 2')).toHaveClass( + 'mm-box--margin-right-2', + ); + expect(getByText('Box marginRight 3')).toHaveClass( + 'mm-box--margin-right-3', + ); + expect(getByText('Box marginRight 4')).toHaveClass( + 'mm-box--margin-right-4', + ); + expect(getByText('Box marginRight 5')).toHaveClass( + 'mm-box--margin-right-5', + ); + expect(getByText('Box marginRight 6')).toHaveClass( + 'mm-box--margin-right-6', + ); + expect(getByText('Box marginRight 7')).toHaveClass( + 'mm-box--margin-right-7', + ); + expect(getByText('Box marginRight 8')).toHaveClass( + 'mm-box--margin-right-8', + ); + expect(getByText('Box marginRight 9')).toHaveClass( + 'mm-box--margin-right-9', + ); + expect(getByText('Box marginRight 10')).toHaveClass( + 'mm-box--margin-right-10', + ); + expect(getByText('Box marginRight 11')).toHaveClass( + 'mm-box--margin-right-11', + ); + expect(getByText('Box marginRight 12')).toHaveClass( + 'mm-box--margin-right-12', + ); + expect(getByText('Box marginRight auto')).toHaveClass( + 'mm-box--margin-right-auto', + ); + }); + it('should render the Box with the responsive marginRight classes', () => { + const { getByText } = render( + <> + Box marginRight 0 + Box marginRight 1 + Box marginRight 2 + Box marginRight 3 + Box marginRight 4 + Box marginRight 5 + Box marginRight 6 + Box marginRight 7 + Box marginRight 8 + Box marginRight 9 + Box marginRight 10 + Box marginRight 11 + Box marginRight 12 + + Box marginRight auto + + , + ); + expect(getByText('Box marginRight 0')).toHaveClass( + 'mm-box--margin-right-0 mm-box--sm:margin-right-0 mm-box--md:margin-right-0 mm-box--lg:margin-right-0', + ); + expect(getByText('Box marginRight 1')).toHaveClass( + 'mm-box--margin-right-1 mm-box--sm:margin-right-1 mm-box--md:margin-right-1 mm-box--lg:margin-right-1', + ); + expect(getByText('Box marginRight 2')).toHaveClass( + 'mm-box--margin-right-2 mm-box--sm:margin-right-2 mm-box--md:margin-right-2 mm-box--lg:margin-right-2', + ); + expect(getByText('Box marginRight 3')).toHaveClass( + 'mm-box--margin-right-3 mm-box--sm:margin-right-3 mm-box--md:margin-right-3 mm-box--lg:margin-right-3', + ); + expect(getByText('Box marginRight 4')).toHaveClass( + 'mm-box--margin-right-4 mm-box--sm:margin-right-4 mm-box--md:margin-right-4 mm-box--lg:margin-right-4', + ); + expect(getByText('Box marginRight 5')).toHaveClass( + 'mm-box--margin-right-5 mm-box--sm:margin-right-5 mm-box--md:margin-right-5 mm-box--lg:margin-right-5', + ); + expect(getByText('Box marginRight 6')).toHaveClass( + 'mm-box--margin-right-6 mm-box--sm:margin-right-6 mm-box--md:margin-right-6 mm-box--lg:margin-right-6', + ); + expect(getByText('Box marginRight 7')).toHaveClass( + 'mm-box--margin-right-7 mm-box--sm:margin-right-7 mm-box--md:margin-right-7 mm-box--lg:margin-right-7', + ); + expect(getByText('Box marginRight 8')).toHaveClass( + 'mm-box--margin-right-8 mm-box--sm:margin-right-8 mm-box--md:margin-right-8 mm-box--lg:margin-right-8', + ); + expect(getByText('Box marginRight 9')).toHaveClass( + 'mm-box--margin-right-9 mm-box--sm:margin-right-9 mm-box--md:margin-right-9 mm-box--lg:margin-right-9', + ); + expect(getByText('Box marginRight 10')).toHaveClass( + 'mm-box--margin-right-10 mm-box--sm:margin-right-10 mm-box--md:margin-right-10 mm-box--lg:margin-right-10', + ); + expect(getByText('Box marginRight 11')).toHaveClass( + 'mm-box--margin-right-11 mm-box--sm:margin-right-11 mm-box--md:margin-right-11 mm-box--lg:margin-right-11', + ); + expect(getByText('Box marginRight 12')).toHaveClass( + 'mm-box--margin-right-12 mm-box--sm:margin-right-12 mm-box--md:margin-right-12 mm-box--lg:margin-right-12', + ); + + expect(getByText('Box marginRight auto')).toHaveClass( + 'mm-box--margin-right-auto mm-box--sm:margin-right-auto mm-box--md:margin-right-auto mm-box--lg:margin-right-auto', + ); + }); + it('should render the Box with the marginBottom classes', () => { + const { getByText } = render( + <> + Box marginBottom 0 + Box marginBottom 1 + Box marginBottom 2 + Box marginBottom 3 + Box marginBottom 4 + Box marginBottom 5 + Box marginBottom 6 + Box marginBottom 7 + Box marginBottom 8 + Box marginBottom 9 + Box marginBottom 10 + Box marginBottom 11 + Box marginBottom 12 + Box marginBottom auto + , + ); + + expect(getByText('Box marginBottom 0')).toHaveClass( + 'mm-box--margin-bottom-0', + ); + expect(getByText('Box marginBottom 1')).toHaveClass( + 'mm-box--margin-bottom-1', + ); + expect(getByText('Box marginBottom 2')).toHaveClass( + 'mm-box--margin-bottom-2', + ); + expect(getByText('Box marginBottom 3')).toHaveClass( + 'mm-box--margin-bottom-3', + ); + expect(getByText('Box marginBottom 4')).toHaveClass( + 'mm-box--margin-bottom-4', + ); + expect(getByText('Box marginBottom 5')).toHaveClass( + 'mm-box--margin-bottom-5', + ); + expect(getByText('Box marginBottom 6')).toHaveClass( + 'mm-box--margin-bottom-6', + ); + expect(getByText('Box marginBottom 7')).toHaveClass( + 'mm-box--margin-bottom-7', + ); + expect(getByText('Box marginBottom 8')).toHaveClass( + 'mm-box--margin-bottom-8', + ); + expect(getByText('Box marginBottom 9')).toHaveClass( + 'mm-box--margin-bottom-9', + ); + expect(getByText('Box marginBottom 10')).toHaveClass( + 'mm-box--margin-bottom-10', + ); + expect(getByText('Box marginBottom 11')).toHaveClass( + 'mm-box--margin-bottom-11', + ); + expect(getByText('Box marginBottom 12')).toHaveClass( + 'mm-box--margin-bottom-12', + ); + expect(getByText('Box marginBottom auto')).toHaveClass( + 'mm-box--margin-bottom-auto', + ); + }); + it('should render the Box with the responsive marginBottom classes', () => { + const { getByText } = render( + <> + Box marginBottom 0 + Box marginBottom 1 + Box marginBottom 2 + Box marginBottom 3 + Box marginBottom 4 + Box marginBottom 5 + Box marginBottom 6 + Box marginBottom 7 + Box marginBottom 8 + Box marginBottom 9 + Box marginBottom 10 + Box marginBottom 11 + Box marginBottom 12 + + Box marginBottom auto + + , + ); + expect(getByText('Box marginBottom 0')).toHaveClass( + 'mm-box--margin-bottom-0 mm-box--sm:margin-bottom-0 mm-box--md:margin-bottom-0 mm-box--lg:margin-bottom-0', + ); + expect(getByText('Box marginBottom 1')).toHaveClass( + 'mm-box--margin-bottom-1 mm-box--sm:margin-bottom-1 mm-box--md:margin-bottom-1 mm-box--lg:margin-bottom-1', + ); + expect(getByText('Box marginBottom 2')).toHaveClass( + 'mm-box--margin-bottom-2 mm-box--sm:margin-bottom-2 mm-box--md:margin-bottom-2 mm-box--lg:margin-bottom-2', + ); + expect(getByText('Box marginBottom 3')).toHaveClass( + 'mm-box--margin-bottom-3 mm-box--sm:margin-bottom-3 mm-box--md:margin-bottom-3 mm-box--lg:margin-bottom-3', + ); + expect(getByText('Box marginBottom 4')).toHaveClass( + 'mm-box--margin-bottom-4 mm-box--sm:margin-bottom-4 mm-box--md:margin-bottom-4 mm-box--lg:margin-bottom-4', + ); + expect(getByText('Box marginBottom 5')).toHaveClass( + 'mm-box--margin-bottom-5 mm-box--sm:margin-bottom-5 mm-box--md:margin-bottom-5 mm-box--lg:margin-bottom-5', + ); + expect(getByText('Box marginBottom 6')).toHaveClass( + 'mm-box--margin-bottom-6 mm-box--sm:margin-bottom-6 mm-box--md:margin-bottom-6 mm-box--lg:margin-bottom-6', + ); + expect(getByText('Box marginBottom 7')).toHaveClass( + 'mm-box--margin-bottom-7 mm-box--sm:margin-bottom-7 mm-box--md:margin-bottom-7 mm-box--lg:margin-bottom-7', + ); + expect(getByText('Box marginBottom 8')).toHaveClass( + 'mm-box--margin-bottom-8 mm-box--sm:margin-bottom-8 mm-box--md:margin-bottom-8 mm-box--lg:margin-bottom-8', + ); + expect(getByText('Box marginBottom 9')).toHaveClass( + 'mm-box--margin-bottom-9 mm-box--sm:margin-bottom-9 mm-box--md:margin-bottom-9 mm-box--lg:margin-bottom-9', + ); + expect(getByText('Box marginBottom 10')).toHaveClass( + 'mm-box--margin-bottom-10 mm-box--sm:margin-bottom-10 mm-box--md:margin-bottom-10 mm-box--lg:margin-bottom-10', + ); + expect(getByText('Box marginBottom 11')).toHaveClass( + 'mm-box--margin-bottom-11 mm-box--sm:margin-bottom-11 mm-box--md:margin-bottom-11 mm-box--lg:margin-bottom-11', + ); + expect(getByText('Box marginBottom 12')).toHaveClass( + 'mm-box--margin-bottom-12 mm-box--sm:margin-bottom-12 mm-box--md:margin-bottom-12 mm-box--lg:margin-bottom-12', + ); + + expect(getByText('Box marginBottom auto')).toHaveClass( + 'mm-box--margin-bottom-auto mm-box--sm:margin-bottom-auto mm-box--md:margin-bottom-auto mm-box--lg:margin-bottom-auto', + ); + }); + it('should render the Box with the marginLeft classes', () => { + const { getByText } = render( + <> + Box marginLeft 0 + Box marginLeft 1 + Box marginLeft 2 + Box marginLeft 3 + Box marginLeft 4 + Box marginLeft 5 + Box marginLeft 6 + Box marginLeft 7 + Box marginLeft 8 + Box marginLeft 9 + Box marginLeft 10 + Box marginLeft 11 + Box marginLeft 12 + Box marginLeft auto + , + ); + + expect(getByText('Box marginLeft 0')).toHaveClass( + 'mm-box--margin-left-0', + ); + expect(getByText('Box marginLeft 1')).toHaveClass( + 'mm-box--margin-left-1', + ); + expect(getByText('Box marginLeft 2')).toHaveClass( + 'mm-box--margin-left-2', + ); + expect(getByText('Box marginLeft 3')).toHaveClass( + 'mm-box--margin-left-3', + ); + expect(getByText('Box marginLeft 4')).toHaveClass( + 'mm-box--margin-left-4', + ); + expect(getByText('Box marginLeft 5')).toHaveClass( + 'mm-box--margin-left-5', + ); + expect(getByText('Box marginLeft 6')).toHaveClass( + 'mm-box--margin-left-6', + ); + expect(getByText('Box marginLeft 7')).toHaveClass( + 'mm-box--margin-left-7', + ); + expect(getByText('Box marginLeft 8')).toHaveClass( + 'mm-box--margin-left-8', + ); + expect(getByText('Box marginLeft 9')).toHaveClass( + 'mm-box--margin-left-9', + ); + expect(getByText('Box marginLeft 10')).toHaveClass( + 'mm-box--margin-left-10', + ); + expect(getByText('Box marginLeft 11')).toHaveClass( + 'mm-box--margin-left-11', + ); + expect(getByText('Box marginLeft 12')).toHaveClass( + 'mm-box--margin-left-12', + ); + expect(getByText('Box marginLeft auto')).toHaveClass( + 'mm-box--margin-left-auto', + ); + }); + it('should render the Box with the responsive marginLeft classes', () => { + const { getByText } = render( + <> + Box marginLeft 0 + Box marginLeft 1 + Box marginLeft 2 + Box marginLeft 3 + Box marginLeft 4 + Box marginLeft 5 + Box marginLeft 6 + Box marginLeft 7 + Box marginLeft 8 + Box marginLeft 9 + Box marginLeft 10 + Box marginLeft 11 + Box marginLeft 12 + + Box marginLeft auto + + , + ); + expect(getByText('Box marginLeft 0')).toHaveClass( + 'mm-box--margin-left-0 mm-box--sm:margin-left-0 mm-box--md:margin-left-0 mm-box--lg:margin-left-0', + ); + expect(getByText('Box marginLeft 1')).toHaveClass( + 'mm-box--margin-left-1 mm-box--sm:margin-left-1 mm-box--md:margin-left-1 mm-box--lg:margin-left-1', + ); + expect(getByText('Box marginLeft 2')).toHaveClass( + 'mm-box--margin-left-2 mm-box--sm:margin-left-2 mm-box--md:margin-left-2 mm-box--lg:margin-left-2', + ); + expect(getByText('Box marginLeft 3')).toHaveClass( + 'mm-box--margin-left-3 mm-box--sm:margin-left-3 mm-box--md:margin-left-3 mm-box--lg:margin-left-3', + ); + expect(getByText('Box marginLeft 4')).toHaveClass( + 'mm-box--margin-left-4 mm-box--sm:margin-left-4 mm-box--md:margin-left-4 mm-box--lg:margin-left-4', + ); + expect(getByText('Box marginLeft 5')).toHaveClass( + 'mm-box--margin-left-5 mm-box--sm:margin-left-5 mm-box--md:margin-left-5 mm-box--lg:margin-left-5', + ); + expect(getByText('Box marginLeft 6')).toHaveClass( + 'mm-box--margin-left-6 mm-box--sm:margin-left-6 mm-box--md:margin-left-6 mm-box--lg:margin-left-6', + ); + expect(getByText('Box marginLeft 7')).toHaveClass( + 'mm-box--margin-left-7 mm-box--sm:margin-left-7 mm-box--md:margin-left-7 mm-box--lg:margin-left-7', + ); + expect(getByText('Box marginLeft 8')).toHaveClass( + 'mm-box--margin-left-8 mm-box--sm:margin-left-8 mm-box--md:margin-left-8 mm-box--lg:margin-left-8', + ); + expect(getByText('Box marginLeft 9')).toHaveClass( + 'mm-box--margin-left-9 mm-box--sm:margin-left-9 mm-box--md:margin-left-9 mm-box--lg:margin-left-9', + ); + expect(getByText('Box marginLeft 10')).toHaveClass( + 'mm-box--margin-left-10 mm-box--sm:margin-left-10 mm-box--md:margin-left-10 mm-box--lg:margin-left-10', + ); + expect(getByText('Box marginLeft 11')).toHaveClass( + 'mm-box--margin-left-11 mm-box--sm:margin-left-11 mm-box--md:margin-left-11 mm-box--lg:margin-left-11', + ); + expect(getByText('Box marginLeft 12')).toHaveClass( + 'mm-box--margin-left-12 mm-box--sm:margin-left-12 mm-box--md:margin-left-12 mm-box--lg:margin-left-12', + ); + + expect(getByText('Box marginLeft auto')).toHaveClass( + 'mm-box--margin-left-auto mm-box--sm:margin-left-auto mm-box--md:margin-left-auto mm-box--lg:margin-left-auto', + ); + }); + it('should render the Box with the marginInline class', () => { + const { getByText } = render(Box content); + + expect(getByText('Box content')).toHaveClass('mm-box--margin-inline-1'); + }); + it('should render the Box with the marginInline auto class', () => { + const { getByText } = render(Box content); + + expect(getByText('Box content')).toHaveClass( + 'mm-box--margin-inline-auto', + ); + }); + it('should render the Box with the responsive marginInline classes', () => { + const { getByText } = render( + Box content, + ); + + expect(getByText('Box content')).toHaveClass('mm-box--margin-inline-1'); + expect(getByText('Box content')).toHaveClass( + 'mm-box--sm:margin-inline-auto', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--md:margin-inline-3', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--lg:margin-inline-4', + ); + }); + it('should render the Box with the marginInlineStart class', () => { + const { getByText } = render( + Box content, + ); + + expect(getByText('Box content')).toHaveClass( + 'mm-box--margin-inline-start-1', + ); + }); + it('should render the Box with the marginInlineStart auto class', () => { + const { getByText } = render( + Box content, + ); + + expect(getByText('Box content')).toHaveClass( + 'mm-box--margin-inline-start-auto', + ); + }); + it('should render the Box with the responsive marginInlineStart classes', () => { + const { getByText } = render( + Box content, + ); + + expect(getByText('Box content')).toHaveClass( + 'mm-box--margin-inline-start-1', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--sm:margin-inline-start-auto', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--md:margin-inline-start-3', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--lg:margin-inline-start-4', + ); + }); + it('should render the Box with the marginInlineEnd class', () => { + const { getByText } = render(Box content); + + expect(getByText('Box content')).toHaveClass( + 'mm-box--margin-inline-end-1', + ); + }); + it('should render the Box with the marginInlineEnd auto class', () => { + const { getByText } = render( + Box content, + ); + + expect(getByText('Box content')).toHaveClass( + 'mm-box--margin-inline-end-auto', + ); + }); + it('should render the Box with the responsive marginInlineEnd classes', () => { + const { getByText } = render( + Box content, + ); + + expect(getByText('Box content')).toHaveClass( + 'mm-box--margin-inline-end-1', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--sm:margin-inline-end-auto', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--md:margin-inline-end-3', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--lg:margin-inline-end-4', + ); + }); + }); + describe('padding', () => { + it('should render the Box with the padding classes', () => { + const { getByText } = render( + <> + Box padding 0 + Box padding 1 + Box padding 2 + Box padding 3 + Box padding 4 + Box padding 5 + Box padding 6 + Box padding 7 + Box padding 8 + Box padding 9 + Box padding 10 + Box padding 11 + Box padding 12 + , + ); + + expect(getByText('Box padding 0')).toHaveClass('mm-box--padding-0'); + expect(getByText('Box padding 1')).toHaveClass('mm-box--padding-1'); + expect(getByText('Box padding 2')).toHaveClass('mm-box--padding-2'); + expect(getByText('Box padding 3')).toHaveClass('mm-box--padding-3'); + expect(getByText('Box padding 4')).toHaveClass('mm-box--padding-4'); + expect(getByText('Box padding 5')).toHaveClass('mm-box--padding-5'); + expect(getByText('Box padding 6')).toHaveClass('mm-box--padding-6'); + expect(getByText('Box padding 7')).toHaveClass('mm-box--padding-7'); + expect(getByText('Box padding 8')).toHaveClass('mm-box--padding-8'); + expect(getByText('Box padding 9')).toHaveClass('mm-box--padding-9'); + expect(getByText('Box padding 10')).toHaveClass('mm-box--padding-10'); + expect(getByText('Box padding 11')).toHaveClass('mm-box--padding-11'); + expect(getByText('Box padding 12')).toHaveClass('mm-box--padding-12'); + }); + it('should render the Box with the responsive padding classes', () => { + const { getByText } = render( + <> + Box padding 0 + Box padding 1 + Box padding 2 + Box padding 3 + Box padding 4 + Box padding 5 + Box padding 6 + Box padding 7 + Box padding 8 + Box padding 9 + Box padding 10 + Box padding 11 + Box padding 12 + , + ); + expect(getByText('Box padding 0')).toHaveClass( + 'mm-box--padding-0 mm-box--sm:padding-0 mm-box--md:padding-0 mm-box--lg:padding-0', + ); + expect(getByText('Box padding 1')).toHaveClass( + 'mm-box--padding-1 mm-box--sm:padding-1 mm-box--md:padding-1 mm-box--lg:padding-1', + ); + expect(getByText('Box padding 2')).toHaveClass( + 'mm-box--padding-2 mm-box--sm:padding-2 mm-box--md:padding-2 mm-box--lg:padding-2', + ); + expect(getByText('Box padding 3')).toHaveClass( + 'mm-box--padding-3 mm-box--sm:padding-3 mm-box--md:padding-3 mm-box--lg:padding-3', + ); + expect(getByText('Box padding 4')).toHaveClass( + 'mm-box--padding-4 mm-box--sm:padding-4 mm-box--md:padding-4 mm-box--lg:padding-4', + ); + expect(getByText('Box padding 5')).toHaveClass( + 'mm-box--padding-5 mm-box--sm:padding-5 mm-box--md:padding-5 mm-box--lg:padding-5', + ); + expect(getByText('Box padding 6')).toHaveClass( + 'mm-box--padding-6 mm-box--sm:padding-6 mm-box--md:padding-6 mm-box--lg:padding-6', + ); + expect(getByText('Box padding 7')).toHaveClass( + 'mm-box--padding-7 mm-box--sm:padding-7 mm-box--md:padding-7 mm-box--lg:padding-7', + ); + expect(getByText('Box padding 8')).toHaveClass( + 'mm-box--padding-8 mm-box--sm:padding-8 mm-box--md:padding-8 mm-box--lg:padding-8', + ); + expect(getByText('Box padding 9')).toHaveClass( + 'mm-box--padding-9 mm-box--sm:padding-9 mm-box--md:padding-9 mm-box--lg:padding-9', + ); + expect(getByText('Box padding 10')).toHaveClass( + 'mm-box--padding-10 mm-box--sm:padding-10 mm-box--md:padding-10 mm-box--lg:padding-10', + ); + expect(getByText('Box padding 11')).toHaveClass( + 'mm-box--padding-11 mm-box--sm:padding-11 mm-box--md:padding-11 mm-box--lg:padding-11', + ); + expect(getByText('Box padding 12')).toHaveClass( + 'mm-box--padding-12 mm-box--sm:padding-12 mm-box--md:padding-12 mm-box--lg:padding-12', + ); + }); + it('should render the Box with the paddingTop classes', () => { + const { getByText } = render( + <> + Box paddingTop 0 + Box paddingTop 1 + Box paddingTop 2 + Box paddingTop 3 + Box paddingTop 4 + Box paddingTop 5 + Box paddingTop 6 + Box paddingTop 7 + Box paddingTop 8 + Box paddingTop 9 + Box paddingTop 10 + Box paddingTop 11 + Box paddingTop 12 + , + ); + + expect(getByText('Box paddingTop 0')).toHaveClass( + 'mm-box--padding-top-0', + ); + expect(getByText('Box paddingTop 1')).toHaveClass( + 'mm-box--padding-top-1', + ); + expect(getByText('Box paddingTop 2')).toHaveClass( + 'mm-box--padding-top-2', + ); + expect(getByText('Box paddingTop 3')).toHaveClass( + 'mm-box--padding-top-3', + ); + expect(getByText('Box paddingTop 4')).toHaveClass( + 'mm-box--padding-top-4', + ); + expect(getByText('Box paddingTop 5')).toHaveClass( + 'mm-box--padding-top-5', + ); + expect(getByText('Box paddingTop 6')).toHaveClass( + 'mm-box--padding-top-6', + ); + expect(getByText('Box paddingTop 7')).toHaveClass( + 'mm-box--padding-top-7', + ); + expect(getByText('Box paddingTop 8')).toHaveClass( + 'mm-box--padding-top-8', + ); + expect(getByText('Box paddingTop 9')).toHaveClass( + 'mm-box--padding-top-9', + ); + expect(getByText('Box paddingTop 10')).toHaveClass( + 'mm-box--padding-top-10', + ); + expect(getByText('Box paddingTop 11')).toHaveClass( + 'mm-box--padding-top-11', + ); + expect(getByText('Box paddingTop 12')).toHaveClass( + 'mm-box--padding-top-12', + ); + }); + it('should render the Box with the responsive paddingTop classes', () => { + const { getByText } = render( + <> + Box paddingTop 0 + Box paddingTop 1 + Box paddingTop 2 + Box paddingTop 3 + Box paddingTop 4 + Box paddingTop 5 + Box paddingTop 6 + Box paddingTop 7 + Box paddingTop 8 + Box paddingTop 9 + Box paddingTop 10 + Box paddingTop 11 + Box paddingTop 12 + , + ); + expect(getByText('Box paddingTop 0')).toHaveClass( + 'mm-box--padding-top-0 mm-box--sm:padding-top-0 mm-box--md:padding-top-0 mm-box--lg:padding-top-0', + ); + expect(getByText('Box paddingTop 1')).toHaveClass( + 'mm-box--padding-top-1 mm-box--sm:padding-top-1 mm-box--md:padding-top-1 mm-box--lg:padding-top-1', + ); + expect(getByText('Box paddingTop 2')).toHaveClass( + 'mm-box--padding-top-2 mm-box--sm:padding-top-2 mm-box--md:padding-top-2 mm-box--lg:padding-top-2', + ); + expect(getByText('Box paddingTop 3')).toHaveClass( + 'mm-box--padding-top-3 mm-box--sm:padding-top-3 mm-box--md:padding-top-3 mm-box--lg:padding-top-3', + ); + expect(getByText('Box paddingTop 4')).toHaveClass( + 'mm-box--padding-top-4 mm-box--sm:padding-top-4 mm-box--md:padding-top-4 mm-box--lg:padding-top-4', + ); + expect(getByText('Box paddingTop 5')).toHaveClass( + 'mm-box--padding-top-5 mm-box--sm:padding-top-5 mm-box--md:padding-top-5 mm-box--lg:padding-top-5', + ); + expect(getByText('Box paddingTop 6')).toHaveClass( + 'mm-box--padding-top-6 mm-box--sm:padding-top-6 mm-box--md:padding-top-6 mm-box--lg:padding-top-6', + ); + expect(getByText('Box paddingTop 7')).toHaveClass( + 'mm-box--padding-top-7 mm-box--sm:padding-top-7 mm-box--md:padding-top-7 mm-box--lg:padding-top-7', + ); + expect(getByText('Box paddingTop 8')).toHaveClass( + 'mm-box--padding-top-8 mm-box--sm:padding-top-8 mm-box--md:padding-top-8 mm-box--lg:padding-top-8', + ); + expect(getByText('Box paddingTop 9')).toHaveClass( + 'mm-box--padding-top-9 mm-box--sm:padding-top-9 mm-box--md:padding-top-9 mm-box--lg:padding-top-9', + ); + expect(getByText('Box paddingTop 10')).toHaveClass( + 'mm-box--padding-top-10 mm-box--sm:padding-top-10 mm-box--md:padding-top-10 mm-box--lg:padding-top-10', + ); + expect(getByText('Box paddingTop 11')).toHaveClass( + 'mm-box--padding-top-11 mm-box--sm:padding-top-11 mm-box--md:padding-top-11 mm-box--lg:padding-top-11', + ); + expect(getByText('Box paddingTop 12')).toHaveClass( + 'mm-box--padding-top-12 mm-box--sm:padding-top-12 mm-box--md:padding-top-12 mm-box--lg:padding-top-12', + ); + }); + it('should render the Box with the paddingRight classes', () => { + const { getByText } = render( + <> + Box paddingRight 0 + Box paddingRight 1 + Box paddingRight 2 + Box paddingRight 3 + Box paddingRight 4 + Box paddingRight 5 + Box paddingRight 6 + Box paddingRight 7 + Box paddingRight 8 + Box paddingRight 9 + Box paddingRight 10 + Box paddingRight 11 + Box paddingRight 12 + , + ); + + expect(getByText('Box paddingRight 0')).toHaveClass( + 'mm-box--padding-right-0', + ); + expect(getByText('Box paddingRight 1')).toHaveClass( + 'mm-box--padding-right-1', + ); + expect(getByText('Box paddingRight 2')).toHaveClass( + 'mm-box--padding-right-2', + ); + expect(getByText('Box paddingRight 3')).toHaveClass( + 'mm-box--padding-right-3', + ); + expect(getByText('Box paddingRight 4')).toHaveClass( + 'mm-box--padding-right-4', + ); + expect(getByText('Box paddingRight 5')).toHaveClass( + 'mm-box--padding-right-5', + ); + expect(getByText('Box paddingRight 6')).toHaveClass( + 'mm-box--padding-right-6', + ); + expect(getByText('Box paddingRight 7')).toHaveClass( + 'mm-box--padding-right-7', + ); + expect(getByText('Box paddingRight 8')).toHaveClass( + 'mm-box--padding-right-8', + ); + expect(getByText('Box paddingRight 9')).toHaveClass( + 'mm-box--padding-right-9', + ); + expect(getByText('Box paddingRight 10')).toHaveClass( + 'mm-box--padding-right-10', + ); + expect(getByText('Box paddingRight 11')).toHaveClass( + 'mm-box--padding-right-11', + ); + expect(getByText('Box paddingRight 12')).toHaveClass( + 'mm-box--padding-right-12', + ); + }); + it('should render the Box with the responsive paddingRight classes', () => { + const { getByText } = render( + <> + Box paddingRight 0 + Box paddingRight 1 + Box paddingRight 2 + Box paddingRight 3 + Box paddingRight 4 + Box paddingRight 5 + Box paddingRight 6 + Box paddingRight 7 + Box paddingRight 8 + Box paddingRight 9 + Box paddingRight 10 + Box paddingRight 11 + Box paddingRight 12 + , + ); + expect(getByText('Box paddingRight 0')).toHaveClass( + 'mm-box--padding-right-0 mm-box--sm:padding-right-0 mm-box--md:padding-right-0 mm-box--lg:padding-right-0', + ); + expect(getByText('Box paddingRight 1')).toHaveClass( + 'mm-box--padding-right-1 mm-box--sm:padding-right-1 mm-box--md:padding-right-1 mm-box--lg:padding-right-1', + ); + expect(getByText('Box paddingRight 2')).toHaveClass( + 'mm-box--padding-right-2 mm-box--sm:padding-right-2 mm-box--md:padding-right-2 mm-box--lg:padding-right-2', + ); + expect(getByText('Box paddingRight 3')).toHaveClass( + 'mm-box--padding-right-3 mm-box--sm:padding-right-3 mm-box--md:padding-right-3 mm-box--lg:padding-right-3', + ); + expect(getByText('Box paddingRight 4')).toHaveClass( + 'mm-box--padding-right-4 mm-box--sm:padding-right-4 mm-box--md:padding-right-4 mm-box--lg:padding-right-4', + ); + expect(getByText('Box paddingRight 5')).toHaveClass( + 'mm-box--padding-right-5 mm-box--sm:padding-right-5 mm-box--md:padding-right-5 mm-box--lg:padding-right-5', + ); + expect(getByText('Box paddingRight 6')).toHaveClass( + 'mm-box--padding-right-6 mm-box--sm:padding-right-6 mm-box--md:padding-right-6 mm-box--lg:padding-right-6', + ); + expect(getByText('Box paddingRight 7')).toHaveClass( + 'mm-box--padding-right-7 mm-box--sm:padding-right-7 mm-box--md:padding-right-7 mm-box--lg:padding-right-7', + ); + expect(getByText('Box paddingRight 8')).toHaveClass( + 'mm-box--padding-right-8 mm-box--sm:padding-right-8 mm-box--md:padding-right-8 mm-box--lg:padding-right-8', + ); + expect(getByText('Box paddingRight 9')).toHaveClass( + 'mm-box--padding-right-9 mm-box--sm:padding-right-9 mm-box--md:padding-right-9 mm-box--lg:padding-right-9', + ); + expect(getByText('Box paddingRight 10')).toHaveClass( + 'mm-box--padding-right-10 mm-box--sm:padding-right-10 mm-box--md:padding-right-10 mm-box--lg:padding-right-10', + ); + expect(getByText('Box paddingRight 11')).toHaveClass( + 'mm-box--padding-right-11 mm-box--sm:padding-right-11 mm-box--md:padding-right-11 mm-box--lg:padding-right-11', + ); + expect(getByText('Box paddingRight 12')).toHaveClass( + 'mm-box--padding-right-12 mm-box--sm:padding-right-12 mm-box--md:padding-right-12 mm-box--lg:padding-right-12', + ); + }); + it('should render the Box with the paddingBottom classes', () => { + const { getByText } = render( + <> + Box paddingBottom 0 + Box paddingBottom 1 + Box paddingBottom 2 + Box paddingBottom 3 + Box paddingBottom 4 + Box paddingBottom 5 + Box paddingBottom 6 + Box paddingBottom 7 + Box paddingBottom 8 + Box paddingBottom 9 + Box paddingBottom 10 + Box paddingBottom 11 + Box paddingBottom 12 + , + ); + + expect(getByText('Box paddingBottom 0')).toHaveClass( + 'mm-box--padding-bottom-0', + ); + expect(getByText('Box paddingBottom 1')).toHaveClass( + 'mm-box--padding-bottom-1', + ); + expect(getByText('Box paddingBottom 2')).toHaveClass( + 'mm-box--padding-bottom-2', + ); + expect(getByText('Box paddingBottom 3')).toHaveClass( + 'mm-box--padding-bottom-3', + ); + expect(getByText('Box paddingBottom 4')).toHaveClass( + 'mm-box--padding-bottom-4', + ); + expect(getByText('Box paddingBottom 5')).toHaveClass( + 'mm-box--padding-bottom-5', + ); + expect(getByText('Box paddingBottom 6')).toHaveClass( + 'mm-box--padding-bottom-6', + ); + expect(getByText('Box paddingBottom 7')).toHaveClass( + 'mm-box--padding-bottom-7', + ); + expect(getByText('Box paddingBottom 8')).toHaveClass( + 'mm-box--padding-bottom-8', + ); + expect(getByText('Box paddingBottom 9')).toHaveClass( + 'mm-box--padding-bottom-9', + ); + expect(getByText('Box paddingBottom 10')).toHaveClass( + 'mm-box--padding-bottom-10', + ); + expect(getByText('Box paddingBottom 11')).toHaveClass( + 'mm-box--padding-bottom-11', + ); + expect(getByText('Box paddingBottom 12')).toHaveClass( + 'mm-box--padding-bottom-12', + ); + }); + it('should render the Box with the responsive paddingBottom classes', () => { + const { getByText } = render( + <> + Box paddingBottom 0 + Box paddingBottom 1 + Box paddingBottom 2 + Box paddingBottom 3 + Box paddingBottom 4 + Box paddingBottom 5 + Box paddingBottom 6 + Box paddingBottom 7 + Box paddingBottom 8 + Box paddingBottom 9 + Box paddingBottom 10 + Box paddingBottom 11 + Box paddingBottom 12 + , + ); + expect(getByText('Box paddingBottom 0')).toHaveClass( + 'mm-box--padding-bottom-0 mm-box--sm:padding-bottom-0 mm-box--md:padding-bottom-0 mm-box--lg:padding-bottom-0', + ); + expect(getByText('Box paddingBottom 1')).toHaveClass( + 'mm-box--padding-bottom-1 mm-box--sm:padding-bottom-1 mm-box--md:padding-bottom-1 mm-box--lg:padding-bottom-1', + ); + expect(getByText('Box paddingBottom 2')).toHaveClass( + 'mm-box--padding-bottom-2 mm-box--sm:padding-bottom-2 mm-box--md:padding-bottom-2 mm-box--lg:padding-bottom-2', + ); + expect(getByText('Box paddingBottom 3')).toHaveClass( + 'mm-box--padding-bottom-3 mm-box--sm:padding-bottom-3 mm-box--md:padding-bottom-3 mm-box--lg:padding-bottom-3', + ); + expect(getByText('Box paddingBottom 4')).toHaveClass( + 'mm-box--padding-bottom-4 mm-box--sm:padding-bottom-4 mm-box--md:padding-bottom-4 mm-box--lg:padding-bottom-4', + ); + expect(getByText('Box paddingBottom 5')).toHaveClass( + 'mm-box--padding-bottom-5 mm-box--sm:padding-bottom-5 mm-box--md:padding-bottom-5 mm-box--lg:padding-bottom-5', + ); + expect(getByText('Box paddingBottom 6')).toHaveClass( + 'mm-box--padding-bottom-6 mm-box--sm:padding-bottom-6 mm-box--md:padding-bottom-6 mm-box--lg:padding-bottom-6', + ); + expect(getByText('Box paddingBottom 7')).toHaveClass( + 'mm-box--padding-bottom-7 mm-box--sm:padding-bottom-7 mm-box--md:padding-bottom-7 mm-box--lg:padding-bottom-7', + ); + expect(getByText('Box paddingBottom 8')).toHaveClass( + 'mm-box--padding-bottom-8 mm-box--sm:padding-bottom-8 mm-box--md:padding-bottom-8 mm-box--lg:padding-bottom-8', + ); + expect(getByText('Box paddingBottom 9')).toHaveClass( + 'mm-box--padding-bottom-9 mm-box--sm:padding-bottom-9 mm-box--md:padding-bottom-9 mm-box--lg:padding-bottom-9', + ); + expect(getByText('Box paddingBottom 10')).toHaveClass( + 'mm-box--padding-bottom-10 mm-box--sm:padding-bottom-10 mm-box--md:padding-bottom-10 mm-box--lg:padding-bottom-10', + ); + expect(getByText('Box paddingBottom 11')).toHaveClass( + 'mm-box--padding-bottom-11 mm-box--sm:padding-bottom-11 mm-box--md:padding-bottom-11 mm-box--lg:padding-bottom-11', + ); + expect(getByText('Box paddingBottom 12')).toHaveClass( + 'mm-box--padding-bottom-12 mm-box--sm:padding-bottom-12 mm-box--md:padding-bottom-12 mm-box--lg:padding-bottom-12', + ); + }); + it('should render the Box with the paddingLeft classes', () => { + const { getByText } = render( + <> + Box paddingLeft 0 + Box paddingLeft 1 + Box paddingLeft 2 + Box paddingLeft 3 + Box paddingLeft 4 + Box paddingLeft 5 + Box paddingLeft 6 + Box paddingLeft 7 + Box paddingLeft 8 + Box paddingLeft 9 + Box paddingLeft 10 + Box paddingLeft 11 + Box paddingLeft 12 + , + ); + + expect(getByText('Box paddingLeft 0')).toHaveClass( + 'mm-box--padding-left-0', + ); + expect(getByText('Box paddingLeft 1')).toHaveClass( + 'mm-box--padding-left-1', + ); + expect(getByText('Box paddingLeft 2')).toHaveClass( + 'mm-box--padding-left-2', + ); + expect(getByText('Box paddingLeft 3')).toHaveClass( + 'mm-box--padding-left-3', + ); + expect(getByText('Box paddingLeft 4')).toHaveClass( + 'mm-box--padding-left-4', + ); + expect(getByText('Box paddingLeft 5')).toHaveClass( + 'mm-box--padding-left-5', + ); + expect(getByText('Box paddingLeft 6')).toHaveClass( + 'mm-box--padding-left-6', + ); + expect(getByText('Box paddingLeft 7')).toHaveClass( + 'mm-box--padding-left-7', + ); + expect(getByText('Box paddingLeft 8')).toHaveClass( + 'mm-box--padding-left-8', + ); + expect(getByText('Box paddingLeft 9')).toHaveClass( + 'mm-box--padding-left-9', + ); + expect(getByText('Box paddingLeft 10')).toHaveClass( + 'mm-box--padding-left-10', + ); + expect(getByText('Box paddingLeft 11')).toHaveClass( + 'mm-box--padding-left-11', + ); + expect(getByText('Box paddingLeft 12')).toHaveClass( + 'mm-box--padding-left-12', + ); + }); + it('should render the Box with the responsive paddingLeft classes', () => { + const { getByText } = render( + <> + Box paddingLeft 0 + Box paddingLeft 1 + Box paddingLeft 2 + Box paddingLeft 3 + Box paddingLeft 4 + Box paddingLeft 5 + Box paddingLeft 6 + Box paddingLeft 7 + Box paddingLeft 8 + Box paddingLeft 9 + Box paddingLeft 10 + Box paddingLeft 11 + Box paddingLeft 12 + , + ); + expect(getByText('Box paddingLeft 0')).toHaveClass( + 'mm-box--padding-left-0 mm-box--sm:padding-left-0 mm-box--md:padding-left-0 mm-box--lg:padding-left-0', + ); + expect(getByText('Box paddingLeft 1')).toHaveClass( + 'mm-box--padding-left-1 mm-box--sm:padding-left-1 mm-box--md:padding-left-1 mm-box--lg:padding-left-1', + ); + expect(getByText('Box paddingLeft 2')).toHaveClass( + 'mm-box--padding-left-2 mm-box--sm:padding-left-2 mm-box--md:padding-left-2 mm-box--lg:padding-left-2', + ); + expect(getByText('Box paddingLeft 3')).toHaveClass( + 'mm-box--padding-left-3 mm-box--sm:padding-left-3 mm-box--md:padding-left-3 mm-box--lg:padding-left-3', + ); + expect(getByText('Box paddingLeft 4')).toHaveClass( + 'mm-box--padding-left-4 mm-box--sm:padding-left-4 mm-box--md:padding-left-4 mm-box--lg:padding-left-4', + ); + expect(getByText('Box paddingLeft 5')).toHaveClass( + 'mm-box--padding-left-5 mm-box--sm:padding-left-5 mm-box--md:padding-left-5 mm-box--lg:padding-left-5', + ); + expect(getByText('Box paddingLeft 6')).toHaveClass( + 'mm-box--padding-left-6 mm-box--sm:padding-left-6 mm-box--md:padding-left-6 mm-box--lg:padding-left-6', + ); + expect(getByText('Box paddingLeft 7')).toHaveClass( + 'mm-box--padding-left-7 mm-box--sm:padding-left-7 mm-box--md:padding-left-7 mm-box--lg:padding-left-7', + ); + expect(getByText('Box paddingLeft 8')).toHaveClass( + 'mm-box--padding-left-8 mm-box--sm:padding-left-8 mm-box--md:padding-left-8 mm-box--lg:padding-left-8', + ); + expect(getByText('Box paddingLeft 9')).toHaveClass( + 'mm-box--padding-left-9 mm-box--sm:padding-left-9 mm-box--md:padding-left-9 mm-box--lg:padding-left-9', + ); + expect(getByText('Box paddingLeft 10')).toHaveClass( + 'mm-box--padding-left-10 mm-box--sm:padding-left-10 mm-box--md:padding-left-10 mm-box--lg:padding-left-10', + ); + expect(getByText('Box paddingLeft 11')).toHaveClass( + 'mm-box--padding-left-11 mm-box--sm:padding-left-11 mm-box--md:padding-left-11 mm-box--lg:padding-left-11', + ); + expect(getByText('Box paddingLeft 12')).toHaveClass( + 'mm-box--padding-left-12 mm-box--sm:padding-left-12 mm-box--md:padding-left-12 mm-box--lg:padding-left-12', + ); + }); + it('should render the Box with the responsive paddingInline classes', () => { + const { getByText } = render( + Box content, + ); + + expect(getByText('Box content')).toHaveClass('mm-box--padding-inline-1'); + expect(getByText('Box content')).toHaveClass( + 'mm-box--sm:padding-inline-2', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--md:padding-inline-3', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--lg:padding-inline-4', + ); + }); + it('should render the Box with the responsive paddingInlineStart classes', () => { + const { getByText } = render( + Box content, + ); + + expect(getByText('Box content')).toHaveClass( + 'mm-box--padding-inline-start-1', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--sm:padding-inline-start-2', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--md:padding-inline-start-3', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--lg:padding-inline-start-4', + ); + }); + it('should render the Box with the responsive paddingInlineEnd classes', () => { + const { getByText } = render( + Box content, + ); + + expect(getByText('Box content')).toHaveClass( + 'mm-box--padding-inline-end-1', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--sm:padding-inline-end-2', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--md:padding-inline-end-3', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--lg:padding-inline-end-4', + ); + }); + }); + describe('border', () => { + it('should render the Box with the borderWidth class', () => { + const { getByText } = render(Box content); + + expect(getByText('Box content')).toHaveClass('mm-box--border-width-1'); + }); + it('should render the Box with the responsive borderWidth classes', () => { + const { getByText } = render( + Box content, + ); + + expect(getByText('Box content')).toHaveClass('mm-box--border-width-1'); + expect(getByText('Box content')).toHaveClass('mm-box--sm:border-width-2'); + expect(getByText('Box content')).toHaveClass('mm-box--md:border-width-3'); + expect(getByText('Box content')).toHaveClass('mm-box--lg:border-width-4'); + }); + it('should render the Box with the borderColor class', () => { + const { getByText } = render( + Box content, + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--border-color-border-default', + ); + }); + it('should render the Box with the responsive borderColor classes', () => { + const { getByText } = render( + + Box content + , + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--border-color-border-default', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--sm:border-color-error-default', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--md:border-color-info-default', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--lg:border-color-warning-default', + ); + }); + it('should render the Box with a borderStyle class', () => { + const { getByText } = render( + Box content, + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--border-style-solid', + ); + }); + it('should render the Box with the responsive borderStyle classes', () => { + const { getByText } = render( + + Box content + , + ); + + expect(getByText('Box content')).toHaveClass( + 'mm-box--border-style-solid', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--sm:border-style-dashed', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--md:border-style-none', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--lg:border-style-dotted', + ); + }); + it('should render the Box with the borderRadius class', () => { + const { getByText } = render( + <> + border radius xs + border radius sm + border radius md + border radius lg + border radius xl + border radius pill + border radius full + border radius none + , + ); + + expect(getByText('border radius xs')).toHaveClass('mm-box--rounded-xs'); + expect(getByText('border radius sm')).toHaveClass('mm-box--rounded-sm'); + expect(getByText('border radius md')).toHaveClass('mm-box--rounded-md'); + expect(getByText('border radius lg')).toHaveClass('mm-box--rounded-lg'); + expect(getByText('border radius xl')).toHaveClass('mm-box--rounded-xl'); + expect(getByText('border radius pill')).toHaveClass( + 'mm-box--rounded-pill', + ); + expect(getByText('border radius full')).toHaveClass( + 'mm-box--rounded-full', + ); + expect(getByText('border radius none')).toHaveClass( + 'mm-box--rounded-none', + ); + }); + it('should render the Box with the responsive borderRadius classes', () => { + const { getByText } = render( + <> + + Border radius set 1 + + + Border radius set 2 + + , + ); + + expect(getByText('Border radius set 1')).toHaveClass( + 'mm-box--rounded-xs', + ); + expect(getByText('Border radius set 1')).toHaveClass( + 'mm-box--sm:rounded-sm', + ); + expect(getByText('Border radius set 1')).toHaveClass( + 'mm-box--md:rounded-md', + ); + expect(getByText('Border radius set 1')).toHaveClass( + 'mm-box--lg:rounded-lg', + ); + expect(getByText('Border radius set 2')).toHaveClass( + 'mm-box--rounded-xl', + ); + expect(getByText('Border radius set 2')).toHaveClass( + 'mm-box--sm:rounded-pill', + ); + expect(getByText('Border radius set 2')).toHaveClass( + 'mm-box--md:rounded-none', + ); + expect(getByText('Border radius set 2')).toHaveClass( + 'mm-box--lg:rounded-full', + ); + }); + }); + describe('display, gap, flexDirection, flexWrap, alignItems, justifyContent', () => { + it('should render the Box with the display classes', () => { + const { getByText } = render( + <> + Box display-block + Box display-flex + Box display-grid + Box display-inline + Box display-inline-block + Box display-inline-flex + Box display-inline-grid + Box display-list-item + Box display-none + , + ); + + expect(getByText('Box display-block')).toHaveClass( + 'mm-box--display-block', + ); + expect(getByText('Box display-flex')).toHaveClass('mm-box--display-flex'); + expect(getByText('Box display-grid')).toHaveClass('mm-box--display-grid'); + expect(getByText('Box display-inline')).toHaveClass( + 'mm-box--display-inline', + ); + expect(getByText('Box display-inline-block')).toHaveClass( + 'mm-box--display-inline-block', + ); + expect(getByText('Box display-inline-flex')).toHaveClass( + 'mm-box--display-inline-flex', + ); + expect(getByText('Box display-inline-grid')).toHaveClass( + 'mm-box--display-inline-grid', + ); + expect(getByText('Box display-list-item')).toHaveClass( + 'mm-box--display-list-item', + ); + }); + it('should render the Box with the responsive display classes', () => { + const { getByText } = render( + + Box content + , + ); + expect(getByText('Box content')).toHaveClass('mm-box--display-block'); + expect(getByText('Box content')).toHaveClass('mm-box--sm:display-flex'); + expect(getByText('Box content')).toHaveClass('mm-box--md:display-grid'); + expect(getByText('Box content')).toHaveClass('mm-box--lg:display-none'); + }); + it('should render the Box with the gap class', () => { + const { getByText } = render( + <> + Box gap 0 + Box gap 1 + Box gap 2 + Box gap 3 + Box gap 4 + Box gap 5 + Box gap 6 + Box gap 7 + Box gap 8 + Box gap 9 + Box gap 10 + Box gap 11 + Box gap 12 + , + ); + + expect(getByText('Box gap 1')).toHaveClass('mm-box--gap-1'); + expect(getByText('Box gap 2')).toHaveClass('mm-box--gap-2'); + expect(getByText('Box gap 3')).toHaveClass('mm-box--gap-3'); + expect(getByText('Box gap 4')).toHaveClass('mm-box--gap-4'); + expect(getByText('Box gap 5')).toHaveClass('mm-box--gap-5'); + expect(getByText('Box gap 6')).toHaveClass('mm-box--gap-6'); + expect(getByText('Box gap 7')).toHaveClass('mm-box--gap-7'); + expect(getByText('Box gap 8')).toHaveClass('mm-box--gap-8'); + expect(getByText('Box gap 9')).toHaveClass('mm-box--gap-9'); + expect(getByText('Box gap 10')).toHaveClass('mm-box--gap-10'); + expect(getByText('Box gap 11')).toHaveClass('mm-box--gap-11'); + expect(getByText('Box gap 12')).toHaveClass('mm-box--gap-12'); + }); + it('should render the Box with the responsive gap classes', () => { + const { getByText } = render( + <> + Box gap 0123 + Box gap 4567 + Box gap 891011 + Box gap 12 + , + ); + + expect(getByText('Box gap 0123')).toHaveClass( + 'mm-box--gap-0 mm-box--sm:gap-1 mm-box--md:gap-2 mm-box--lg:gap-3', + ); + expect(getByText('Box gap 4567')).toHaveClass( + 'mm-box--gap-4 mm-box--sm:gap-5 mm-box--md:gap-6 mm-box--lg:gap-7', + ); + expect(getByText('Box gap 891011')).toHaveClass( + 'mm-box--gap-8 mm-box--sm:gap-9 mm-box--md:gap-10 mm-box--lg:gap-11', + ); + expect(getByText('Box gap 12')).toHaveClass( + 'mm-box--gap-12 mm-box--sm:gap-12 mm-box--md:gap-12 mm-box--lg:gap-12', + ); + }); + it('should render the Box with the flexDirection classes', () => { + const { getByText } = render( + <> + Box flex-direction-row + + Box flex-direction-row-reverse + + + Box flex-direction-column + + + Box flex-direction-column-reverse + + , + ); + + expect(getByText('Box flex-direction-row')).toHaveClass( + 'mm-box--flex-direction-row', + ); + expect(getByText('Box flex-direction-row-reverse')).toHaveClass( + 'mm-box--flex-direction-row-reverse', + ); + expect(getByText('Box flex-direction-column')).toHaveClass( + 'mm-box--flex-direction-column', + ); + expect(getByText('Box flex-direction-column-reverse')).toHaveClass( + 'mm-box--flex-direction-column-reverse', + ); + }); + it('should render the Box with the responsive flexDirection classes', () => { + const { getByText } = render( + + Box content + , + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--flex-direction-row', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--sm:flex-direction-row-reverse', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--md:flex-direction-column', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--lg:flex-direction-column-reverse', + ); + }); + it('should render the Box with the flexWrap classes', () => { + const { getByText } = render( + <> + Box flex-wrap-wrap + Box flex-wrap-wrap-reverse + Box flex-wrap-nowrap + , + ); + + expect(getByText('Box flex-wrap-wrap')).toHaveClass( + 'mm-box--flex-wrap-wrap', + ); + expect(getByText('Box flex-wrap-wrap-reverse')).toHaveClass( + 'mm-box--flex-wrap-wrap-reverse', + ); + expect(getByText('Box flex-wrap-nowrap')).toHaveClass( + 'mm-box--flex-wrap-nowrap', + ); + }); + it('should render the Box with the responsive flexWrap classes', () => { + const { getByText } = render( + + Box content + , + ); + expect(getByText('Box content')).toHaveClass('mm-box--flex-wrap-wrap'); + expect(getByText('Box content')).toHaveClass( + 'mm-box--sm:flex-wrap-wrap-reverse', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--md:flex-wrap-nowrap', + ); + }); + it('should render the Box with the alignItems classes', () => { + const { getByText } = render( + <> + + Box align-items-flex-start + + Box align-items-flex-end + Box align-items-center + Box align-items-baseline + Box align-items-stretch + , + ); + + expect(getByText('Box align-items-flex-start')).toHaveClass( + 'mm-box--align-items-flex-start', + ); + expect(getByText('Box align-items-flex-end')).toHaveClass( + 'mm-box--align-items-flex-end', + ); + expect(getByText('Box align-items-center')).toHaveClass( + 'mm-box--align-items-center', + ); + expect(getByText('Box align-items-baseline')).toHaveClass( + 'mm-box--align-items-baseline', + ); + expect(getByText('Box align-items-stretch')).toHaveClass( + 'mm-box--align-items-stretch', + ); + }); + it('should render the Box with the responsive alignItems classes', () => { + const { getByText } = render( + <> + + Box content + + , + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--align-items-flex-start', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--sm:align-items-flex-end', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--md:align-items-center', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--lg:align-items-baseline', + ); + }); + it('should render the Box with the justifyContent classes', () => { + const { getByText } = render( + <> + + Box justify-content-flex-start + + + Box justify-content-flex-end + + + Box justify-content-center + + + Box justify-content-space-around + + + Box justify-content-space-between + + + Box justify-content-space-evenly + + , + ); + + expect(getByText('Box justify-content-flex-start')).toHaveClass( + 'mm-box--justify-content-flex-start', + ); + expect(getByText('Box justify-content-flex-end')).toHaveClass( + 'mm-box--justify-content-flex-end', + ); + expect(getByText('Box justify-content-center')).toHaveClass( + 'mm-box--justify-content-center', + ); + expect(getByText('Box justify-content-space-around')).toHaveClass( + 'mm-box--justify-content-space-around', + ); + expect(getByText('Box justify-content-space-between')).toHaveClass( + 'mm-box--justify-content-space-between', + ); + }); + it('should render the Box with the responsive justifyContent classes', () => { + const { getByText } = render( + <> + + Box content + + , + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--justify-content-flex-start', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--sm:justify-content-flex-end', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--md:justify-content-center', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--lg:justify-content-space-around', + ); + }); + }); + describe('textAlign', () => { + it('should render the Box with the textAlign auto class', () => { + const { getByText } = render( + <> + Box left + Box center + Box right + Box justify + Box end + , + ); + + expect(getByText('Box left')).toHaveClass('mm-box--text-align-left'); + expect(getByText('Box center')).toHaveClass('mm-box--text-align-center'); + expect(getByText('Box right')).toHaveClass('mm-box--text-align-right'); + expect(getByText('Box justify')).toHaveClass( + 'mm-box--text-align-justify', + ); + expect(getByText('Box end')).toHaveClass('mm-box--text-align-end'); + }); + it('should render the Box with the responsive textAlign classes', () => { + const { getByText } = render( + + Box content + , + ); + + expect(getByText('Box content')).toHaveClass('mm-box--text-align-left'); + expect(getByText('Box content')).toHaveClass( + 'mm-box--sm:text-align-center', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--md:text-align-right', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--lg:text-align-justify', + ); + }); + }); + describe('background', () => { + it('should render the Box with the backgroundColor class', () => { + const { getByText } = render( + + Box content + , + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--background-color-background-default', + ); + }); + it('should render the Box with the responsive backgroundColor classes', () => { + const { getByText } = render( + + Box content + , + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--background-color-background-default', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--sm:background-color-error-default', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--md:background-color-info-default', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--lg:background-color-warning-default', + ); + }); + }); + describe('color', () => { + it('should render the Box with the color class', () => { + const { getByText } = render( + Box content, + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--color-text-default', + ); + }); + it('should render the Box with the responsive color classes', () => { + const { getByText } = render( + + Box content + , + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--color-text-default', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--sm:color-primary-default', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--md:color-error-default', + ); + expect(getByText('Box content')).toHaveClass( + 'mm-box--lg:color-success-default', + ); + }); + }); + describe('width, height', () => { + it('should render the Box with the width class', () => { + const { getByText } = render( + <> + Box half + Box one fourth + Box max + Box min + , + ); + expect(getByText('Box half')).toHaveClass('mm-box--width-1/2'); + expect(getByText('Box one fourth')).toHaveClass('mm-box--width-1/4'); + expect(getByText('Box max')).toHaveClass('mm-box--width-max'); + expect(getByText('Box min')).toHaveClass('mm-box--width-min'); + }); + it('should render the Box with the responsive width classes', () => { + const { getByText } = render( + + Box content + , + ); + expect(getByText('Box content')).toHaveClass('mm-box--width-1/2'); + expect(getByText('Box content')).toHaveClass('mm-box--sm:width-1/4'); + expect(getByText('Box content')).toHaveClass('mm-box--md:width-max'); + expect(getByText('Box content')).toHaveClass('mm-box--lg:width-min'); + }); + it('should render the Box with the height class', () => { + const { getByText } = render( + <> + Box half + Box one fourth + Box max + Box min + , + ); + expect(getByText('Box half')).toHaveClass('mm-box--height-1/2'); + expect(getByText('Box one fourth')).toHaveClass('mm-box--height-1/4'); + expect(getByText('Box max')).toHaveClass('mm-box--height-max'); + expect(getByText('Box min')).toHaveClass('mm-box--height-min'); + }); + it('should render the Box with the responsive height classes', () => { + const { getByText } = render( + <> + + Box content + + , + ); + expect(getByText('Box content')).toHaveClass('mm-box--height-1/2'); + expect(getByText('Box content')).toHaveClass('mm-box--sm:height-1/4'); + expect(getByText('Box content')).toHaveClass('mm-box--md:height-max'); + expect(getByText('Box content')).toHaveClass('mm-box--lg:height-min'); + }); + }); + describe('polymorphic "as" prop', () => { + it('should render the Box with different html root elements', () => { + const { container } = render( + <> + Box as div (default) + Box as ul + Box as button + , + ); + expect(container.querySelector('div')).toHaveTextContent( + 'Box as div (default)', + ); + expect(container.querySelector('ul')).toHaveTextContent('Box as ul'); + expect(container.querySelector('button')).toHaveTextContent( + 'Box as button', + ); + }); + }); + it('should accept a ref prop that is passed down to the html element', () => { + const mockRef = React.createRef(); + render(hello); + expect(mockRef.current).toBeInTheDocument(); + expect(mockRef.current?.tagName).toBe('DIV'); + }); + it('should render with a varying range of array props', () => { + const { getByText } = render( + <> + 1 item + 2 items + 3 items + too many items + , + ); + + expect(getByText('1 item')).toHaveClass('mm-box--margin-0'); + expect(getByText('2 items')).toHaveClass( + 'mm-box--margin-0 mm-box--sm:margin-1', + ); + expect(getByText('3 items')).toHaveClass( + 'mm-box--margin-0 mm-box--sm:margin-1 mm-box--md:margin-2', + ); + }); +}); diff --git a/ui/components/component-library/box/box.tsx b/ui/components/component-library/box/box.tsx new file mode 100644 index 000000000..409b0b640 --- /dev/null +++ b/ui/components/component-library/box/box.tsx @@ -0,0 +1,234 @@ +import React from 'react'; +import classnames from 'classnames'; +import { memoize } from 'lodash'; + +import { BREAKPOINTS } from '../../../helpers/constants/design-system'; + +import type { + BoxComponent, + BoxProps, + PolymorphicRef, + StyleDeclarationType, + StylePropValueType, + ClassNamesObject, +} from './box.types'; + +const BASE_CLASS_NAME = 'mm-box'; + +function isValidSize( + styleProp: StyleDeclarationType, + value: StylePropValueType, +) { + // Only margin types allow 'auto' + return ( + typeof value === 'number' || + ((styleProp === 'margin' || + styleProp === 'margin-top' || + styleProp === 'margin-right' || + styleProp === 'margin-bottom' || + styleProp === 'margin-left' || + styleProp === 'margin-inline' || + styleProp === 'margin-inline-start' || + styleProp === 'margin-inline-end') && + value === 'auto') + ); +} + +function isValidString(type: StyleDeclarationType, value: StylePropValueType) { + 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} styleDeclaration - 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( + ( + styleDeclaration: StyleDeclarationType, + value: StylePropValueType, + validatorFn: typeof isValidString | typeof isValidSize, + ) => { + // if value does not exist return empty object for classnames library + // Accepts 0 as a valid value + if (!value && typeof value !== 'number') { + return {}; + } + const classNamesObject: ClassNamesObject = {}; + // 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 + let singleValue; + if (singleValueProp || singleValueProp === 0) { + singleValue = singleValueProp; + } + if (singleArrayItemProp || singleArrayItemProp === 0) { + singleValue = singleArrayItemProp; + } + // 0 is an acceptable value but is falsy in js + if (singleValue || singleValue === 0) { + // add base style without any breakpoint prefixes to classObject + classNamesObject[ + `${BASE_CLASS_NAME}--${styleDeclaration}-${singleValue}` + ] = validatorFn(styleDeclaration, singleValue); + } else if (Array.isArray(value)) { + // If array with more than one item + switch (value.length) { + case 4: + // add base/sm/md/lg + classNamesObject[ + `${BASE_CLASS_NAME}--${styleDeclaration}-${value[0]}` + ] = validatorFn(styleDeclaration, value[0]); + classNamesObject[ + `${BASE_CLASS_NAME}--${BREAKPOINTS[1]}:${styleDeclaration}-${value[1]}` + ] = validatorFn(styleDeclaration, value[1]); + classNamesObject[ + `${BASE_CLASS_NAME}--${BREAKPOINTS[2]}:${styleDeclaration}-${value[2]}` + ] = validatorFn(styleDeclaration, value[2]); + classNamesObject[ + `${BASE_CLASS_NAME}--${BREAKPOINTS[3]}:${styleDeclaration}-${value[3]}` + ] = validatorFn(styleDeclaration, value[3]); + break; + case 3: + // add base/sm/md + classNamesObject[ + `${BASE_CLASS_NAME}--${styleDeclaration}-${value[0]}` + ] = validatorFn(styleDeclaration, value[0]); + classNamesObject[ + `${BASE_CLASS_NAME}--${BREAKPOINTS[1]}:${styleDeclaration}-${value[1]}` + ] = validatorFn(styleDeclaration, value[1]); + classNamesObject[ + `${BASE_CLASS_NAME}--${BREAKPOINTS[2]}:${styleDeclaration}-${value[2]}` + ] = validatorFn(styleDeclaration, value[2]); + break; + case 2: + // add base/sm + classNamesObject[ + `${BASE_CLASS_NAME}--${styleDeclaration}-${value[0]}` + ] = validatorFn(styleDeclaration, value[0]); + classNamesObject[ + `${BASE_CLASS_NAME}--${BREAKPOINTS[1]}:${styleDeclaration}-${value[1]}` + ] = validatorFn(styleDeclaration, value[1]); + break; + default: + console.log(`Invalid array prop length: ${value.length}`); + } + } + return classNamesObject; + }, + (styleDeclaration, value) => [styleDeclaration, value], +); + +export const Box: BoxComponent = React.forwardRef( + ( + { + as, + padding, + paddingTop, + paddingRight, + paddingBottom, + paddingLeft, + paddingInline, + paddingInlineStart, + paddingInlineEnd, + margin, + marginTop, + marginRight, + marginBottom, + marginLeft, + marginInline, + marginInlineStart, + marginInlineEnd, + borderColor, + borderWidth, + borderRadius, + borderStyle, + alignItems, + justifyContent, + textAlign, + flexDirection, + flexWrap, + gap, + display, + width, + height, + children, + className = '', + backgroundColor, + color, + ...props + }: BoxProps, + ref?: PolymorphicRef, + ) => { + const Component = as || 'div'; + const boxClassName = classnames( + BASE_CLASS_NAME, + className, + // Margin + generateClassNames('margin', margin, isValidSize), + generateClassNames('margin-top', marginTop, isValidSize), + generateClassNames('margin-right', marginRight, isValidSize), + generateClassNames('margin-bottom', marginBottom, isValidSize), + generateClassNames('margin-left', marginLeft, isValidSize), + generateClassNames('margin-inline', marginInline, isValidSize), + generateClassNames('margin-inline-start', marginInlineStart, isValidSize), + generateClassNames('margin-inline-end', marginInlineEnd, isValidSize), + // Padding + generateClassNames('padding', padding, isValidSize), + generateClassNames('padding-top', paddingTop, isValidSize), + generateClassNames('padding-right', paddingRight, isValidSize), + generateClassNames('padding-bottom', paddingBottom, isValidSize), + generateClassNames('padding-left', paddingLeft, isValidSize), + generateClassNames('padding-inline', paddingInline, isValidSize), + generateClassNames( + 'padding-inline-start', + paddingInlineStart, + isValidSize, + ), + generateClassNames('padding-inline-end', paddingInlineEnd, isValidSize), + generateClassNames('display', display, isValidString), + generateClassNames('gap', gap, isValidSize), + generateClassNames('flex-direction', flexDirection, isValidString), + generateClassNames('flex-wrap', flexWrap, isValidString), + generateClassNames('justify-content', justifyContent, isValidString), + generateClassNames('align-items', alignItems, isValidString), + generateClassNames('text-align', textAlign, isValidString), + generateClassNames('width', width, isValidString), + generateClassNames('height', height, isValidString), + generateClassNames('color', color, isValidString), + generateClassNames('background-color', backgroundColor, isValidString), + generateClassNames('rounded', borderRadius, isValidString), + generateClassNames('border-style', borderStyle, isValidString), + generateClassNames('border-color', borderColor, isValidString), + 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), + }, + ); + return ( + + {children} + + ); + }, +); diff --git a/ui/components/component-library/box/box.types.ts b/ui/components/component-library/box/box.types.ts new file mode 100644 index 000000000..8344b72de --- /dev/null +++ b/ui/components/component-library/box/box.types.ts @@ -0,0 +1,433 @@ +import React from 'react'; + +import { + AlignItems, + BackgroundColor, + BlockSize, + BorderColor, + BorderRadius, + BorderStyle, + Color, + Display, + FlexDirection, + FlexWrap, + IconColor, + JustifyContent, + TextAlign, + TextColor, +} from '../../../helpers/constants/design-system'; + +export type StyleDeclarationType = + | 'margin' + | 'margin-top' + | 'margin-right' + | 'margin-bottom' + | 'margin-left' + | 'margin-inline' + | 'margin-inline-start' + | 'margin-inline-end' + | 'padding' + | 'padding-top' + | 'padding-right' + | 'padding-bottom' + | 'padding-left' + | 'padding-inline' + | 'padding-inline-start' + | 'padding-inline-end' + | 'display' + | 'gap' + | 'flex-direction' + | 'flex-wrap' + | 'justify-content' + | 'align-items' + | 'text-align' + | 'width' + | 'height' + | 'color' + | 'background-color' + | 'rounded' + | 'border-style' + | 'border-color' + | 'border-width'; + +export type StylePropValueType = + | AlignItems + | AlignItemsArray + | BackgroundColor + | BackgroundColorArray + | BlockSize + | BlockSizeArray + | BorderColor + | BorderColorArray + | BorderRadius + | BorderRadiusArray + | BorderStyle + | BorderStyleArray + | Color + | Display + | DisplayArray + | FlexDirection + | FlexDirectionArray + | FlexWrap + | FlexWrapArray + | IconColor + | JustifyContent + | JustifyContentArray + | SizeNumberAndAuto + | SizeNumberAndAutoArray + | TextAlign + | TextAlignArray + | TextColor + | TextColorArray + | IconColor + | IconColorArray + | undefined; + +export interface ClassNamesObject { + [key: string]: any; +} + +export type FlexDirectionArray = [ + FlexDirection, + FlexDirection?, + FlexDirection?, + FlexDirection?, +]; +export type FlexWrapArray = [FlexWrap, FlexWrap?, FlexWrap?, FlexWrap?]; +export type TextAlignArray = [TextAlign, TextAlign?, TextAlign?, TextAlign?]; +export type DisplayArray = [Display, Display?, Display?, Display?]; +export type BlockSizeArray = [BlockSize, BlockSize?, BlockSize?, BlockSize?]; + +export type SizeNumber = + | 0 + | 1 + | 2 + | 3 + | 4 + | 5 + | 6 + | 7 + | 8 + | 9 + | 10 + | 11 + | 12 + | null; + +export type SizeNumberArray = [ + SizeNumber, + SizeNumber?, + SizeNumber?, + SizeNumber?, +]; + +export type SizeNumberAndAuto = SizeNumber | 'auto'; + +export type SizeNumberAndAutoArray = [ + SizeNumberAndAuto, + SizeNumberAndAuto?, + SizeNumberAndAuto?, + SizeNumberAndAuto?, +]; + +export type BorderColorArray = [ + BorderColor, + BorderColor?, + BorderColor?, + BorderColor?, +]; + +export type BorderRadiusArray = [ + BorderRadius, + BorderRadius?, + BorderRadius?, + BorderRadius?, +]; + +export type BorderStyleArray = [ + BorderStyle, + BorderStyle?, + BorderStyle?, + BorderStyle?, +]; + +export type AlignItemsArray = [ + AlignItems, + AlignItems?, + AlignItems?, + AlignItems?, +]; + +export type JustifyContentArray = [ + JustifyContent, + JustifyContent?, + JustifyContent?, + JustifyContent?, +]; + +export type BackgroundColorArray = [ + BackgroundColor, + BackgroundColor?, + BackgroundColor?, + BackgroundColor?, +]; + +export type TextColorArray = [TextColor, TextColor?, TextColor?, TextColor?]; + +export type IconColorArray = [IconColor, IconColor?, IconColor?, IconColor?]; + +/** + * Polymorphic props based on Ohans Emmanuel's article below + * https://blog.logrocket.com/build-strongly-typed-polymorphic-components-react-typescript/#ensuring-as-prop-only-receives-valid-html-element-strings + */ + +/** + * Uses generic type C to create polymorphic ref type + */ +export type PolymorphicRef = + React.ComponentPropsWithRef['ref']; + +/** + * Uses generic type C to define the type for the polymorphic "as" prop + * "as" can be used to override the default HTML element + */ +type AsProp = { + /** + * An override of the default HTML tag. + * Can also be a React component. + */ + as?: C; +}; + +/** + * Omits the as prop and props from component definition + */ +type PropsToOmit = keyof (AsProp & P); + +/** + * Accepts 2 generic types: C which represents the as prop and the component props - Props + */ +type PolymorphicComponentProp< + C extends React.ElementType, + // eslint-disable-next-line @typescript-eslint/ban-types + Props = {}, +> = React.PropsWithChildren> & + Omit, PropsToOmit>; + +export type PolymorphicComponentPropWithRef< + C extends React.ElementType, + // eslint-disable-next-line @typescript-eslint/ban-types + Props = {}, +> = PolymorphicComponentProp & { ref?: PolymorphicRef }; + +/** + * Includes all style utility props. This should be used to extend the props of a component. + */ +export interface StyleUtilityProps { + /** + * The flex direction of the Box component. + * Use the FlexDirection enum from '../../../helpers/constants/design-system'; + * Accepts responsive props in the form of an array. + */ + flexDirection?: FlexDirection | FlexDirectionArray; + /** + * The flex wrap of the Box component. + * Use the FlexWrap enum from '../../../helpers/constants/design-system'; + * Accepts responsive props in the form of an array. + */ + flexWrap?: FlexWrap | FlexWrapArray; + /** + * The gap between the Box component's children. + * Use 1-12 for a gap of 4px-48px. + * Accepts responsive props in the form of an array. + */ + gap?: SizeNumber | SizeNumberArray | undefined; + /** + * The margin of the Box component. + * Use 1-12 for 4px-48px or 'auto'. + * Accepts responsive props in the form of an array. + */ + margin?: SizeNumberAndAuto | SizeNumberAndAutoArray; + /** + * The margin-top of the Box component. + * Use 1-12 for 4px-48px or 'auto'. + * Accepts responsive props in the form of an array. + */ + marginTop?: SizeNumberAndAuto | SizeNumberAndAutoArray; + /** + * The margin-bottom of the Box component. + * Use 1-12 for 4px-48px or 'auto'. + * Accepts responsive props in the form of an array. + */ + marginBottom?: SizeNumberAndAuto | SizeNumberAndAutoArray; + /** + * The margin-right of the Box component. + * Use 1-12 for 4px-48px or 'auto'. + * Accepts responsive props in the form of an array. + */ + marginRight?: SizeNumberAndAuto | SizeNumberAndAutoArray; + /** + * The margin-left of the Box component. + * Use 1-12 for 4px-48px or 'auto'. + * Accepts responsive props in the form of an array. + */ + marginLeft?: SizeNumberAndAuto | SizeNumberAndAutoArray; + /** + * The margin-inline of the Box component. + * Use 1-12 for 4px-48px or 'auto'. + * Accepts responsive props in the form of an array. + */ + marginInline?: SizeNumberAndAuto | SizeNumberAndAutoArray; + /** + * The margin-inline-start of the Box component. + * Use 1-12 for 4px-48px or 'auto'. + * Accepts responsive props in the form of an array. + */ + marginInlineStart?: SizeNumberAndAuto | SizeNumberAndAutoArray; + /** + * The margin-inline-end of the Box component. + * Use 1-12 for 4px-48px or 'auto'. + * Accepts responsive props in the form of an array. + */ + marginInlineEnd?: SizeNumberAndAuto | SizeNumberAndAutoArray; + /** + * The padding of the Box component. + * Use 1-12 for 4px-48px. + * Accepts responsive props in the form of an array. + */ + padding?: SizeNumber | SizeNumberArray; + /** + * The padding-top of the Box component. + * Use 1-12 for 4px-48px. + * Accepts responsive props in the form of an array. + */ + paddingTop?: SizeNumber | SizeNumberArray; + /** + * The padding-bottom of the Box component. + * Use 1-12 for 4px-48px. + * Accepts responsive props in the form of an array. + */ + paddingBottom?: SizeNumber | SizeNumberArray; + /** + * The padding-right of the Box component. + * Use 1-12 for 4px-48px. + * Accepts responsive props in the form of an array. + */ + paddingRight?: SizeNumber | SizeNumberArray; + /** + * The padding-left of the Box component. + * Use 1-12 for 4px-48px. + * Accepts responsive props in the form of an array. + */ + paddingLeft?: SizeNumber | SizeNumberArray; + /** + * The padding-inline of the Box component. + * Use 1-12 for 4px-48px. + * Accepts responsive props in the form of an array. + */ + paddingInline?: SizeNumber | SizeNumberArray; + /** + * The padding-inline-start of the Box component. + * Use 1-12 for 4px-48px. + * Accepts responsive props in the form of an array. + */ + paddingInlineStart?: SizeNumber | SizeNumberArray; + /** + * The padding-inline-end of the Box component. + * Use 1-12 for 4px-48px. + * Accepts responsive props in the form of an array. + */ + paddingInlineEnd?: SizeNumber | SizeNumberArray; + /** + * The border-color of the Box component. + * Use BorderColor enum from '../../../helpers/constants/design-system'; + * Accepts responsive props in the form of an array. + */ + borderColor?: BorderColor | BorderColorArray; + /** + * The border-width of the Box component. + * Use 1-12 for 1px-12px. + * Accepts responsive props in the form of an array. + */ + borderWidth?: SizeNumber | SizeNumberArray; + /** + * The border-radius of the Box component. + * Use BorderRadius enum from '../../../helpers/constants/design-system'; + * Accepts responsive props in the form of an array. + */ + borderRadius?: BorderRadius | BorderRadiusArray; + /** + * The border-style of the Box component. + * Use BorderStyle enum from '../../../helpers/constants/design-system'; + * Accepts responsive props in the form of an array. + */ + borderStyle?: BorderStyle | BorderStyleArray; + /** + * The align-items of the Box component. + * Use AlignItems enum from '../../../helpers/constants/design-system'; + * Accepts responsive props in the form of an array. + */ + alignItems?: AlignItems | AlignItemsArray; + /** + * The justify-content of the Box component. + * Use JustifyContent enum from '../../../helpers/constants/design-system'; + * Accepts responsive props in the form of an array. + */ + justifyContent?: JustifyContent | JustifyContentArray; + /** + * The text-align of the Box component. + * Use TextAlign enum from '../../../helpers/constants/design-system'; + * Accepts responsive props in the form of an array. + */ + textAlign?: TextAlign | TextAlignArray; + /** + * The display of the Box component. + * Use Display enum from '../../../helpers/constants/design-system'; + * Accepts responsive props in the form of an array. + */ + display?: Display | DisplayArray; + /** + * The width of the Box component. + * Use BlockSize enum from '../../../helpers/constants/design-system'; + * Accepts responsive props in the form of an array. + */ + width?: BlockSize | BlockSizeArray; + /** + * The height of the Box component. + * Use BlockSize enum from '../../../helpers/constants/design-system'; + * Accepts responsive props in the form of an array. + */ + height?: BlockSize | BlockSizeArray; + /** + * The background-color of the Box component. + * Use BackgroundColor enum from '../../../helpers/constants/design-system'; + * Accepts responsive props in the form of an array. + */ + backgroundColor?: BackgroundColor | BackgroundColorArray; + /** + * The text-color of the Box component. + * Use TextColor enum from '../../../helpers/constants/design-system'; + * Accepts responsive props in the form of an array. + */ + color?: TextColor | TextColorArray | IconColor | IconColorArray; +} +/** + * Box component props. + */ +interface Props extends StyleUtilityProps { + /** + * The content of the Box component. + */ + children?: React.ReactNode; + /** + * Additional className to apply to the Box component. + */ + className?: string; +} + +export type BoxProps = + PolymorphicComponentPropWithRef; + +export type BoxComponent = ( + props: BoxProps, +) => React.ReactElement | null; diff --git a/ui/components/component-library/box/index.ts b/ui/components/component-library/box/index.ts new file mode 100644 index 000000000..e31576438 --- /dev/null +++ b/ui/components/component-library/box/index.ts @@ -0,0 +1,8 @@ +export { Box } from './box'; +export type { + PolymorphicRef, + PolymorphicComponentPropWithRef, + StyleUtilityProps, + BoxProps, + BoxComponent, +} from './box.types'; diff --git a/ui/components/component-library/component-library-components.scss b/ui/components/component-library/component-library-components.scss index d8c6e9a2c..68f1085c9 100644 --- a/ui/components/component-library/component-library-components.scss +++ b/ui/components/component-library/component-library-components.scss @@ -5,6 +5,7 @@ * unintended overrides. **/ // Atoms +@import 'box/box'; @import 'text/text'; @import 'icon/icon'; @import 'label/label'; diff --git a/ui/components/component-library/index.js b/ui/components/component-library/index.js index 6117cae00..4da644ec7 100644 --- a/ui/components/component-library/index.js +++ b/ui/components/component-library/index.js @@ -8,12 +8,13 @@ export { AvatarFavicon, AVATAR_FAVICON_SIZES } from './avatar-favicon'; export { AvatarIcon, AVATAR_ICON_SIZES } from './avatar-icon'; export { AvatarNetwork, AVATAR_NETWORK_SIZES } from './avatar-network'; export { AvatarToken } from './avatar-token'; +export { AvatarBase } from './avatar-base'; export { BadgeWrapper, BadgeWrapperPosition, BadgeWrapperAnchorElementShape, } from './badge-wrapper'; -export { AvatarBase } from './avatar-base'; +export { Box } from './box'; export { Button, BUTTON_VARIANT, BUTTON_SIZES } from './button'; export { ButtonBase, BUTTON_BASE_SIZES } from './button-base'; export { ButtonIcon, ButtonIconSize } from './button-icon';