import * as React from 'react'; import classNames from 'classnames'; import { generateResponsiveClassNames, mergeResponsiveProps, } from '../utils/responsive-props'; import type {ResponsivePropType} from '../utils/responsive-props'; type ColorType = | 'transparent' | 'white' | 'gray-40' | 'gray-20' | 'gray-10' | 'blue-40' | 'blue-30' | 'blue-20' | 'green-40' | 'green-30' | 'green-20' | 'green-10' | 'indigo-40' | 'indigo-20' | 'indigo-10' | 'red-40' | 'red-30' | 'red-20' | 'yellow-40' | 'yellow-20'; export const COLOR = { transparent: 'transparent', white: 'white', 'gray-40': 'gray-40', 'gray-20': 'gray-20', 'gray-10': 'gray-10', 'blue-40': 'blue-40', 'blue-30': 'blue-30', 'blue-20': 'blue-20', 'green-40': 'green-40', 'green-30': 'green-30', 'green-20': 'green-20', 'green-10': 'green-10', 'indigo-40': 'indigo-40', 'indigo-20': 'indigo-20', 'indigo-10': 'indigo-10', 'red-40': 'red-40', 'red-30': 'red-30', 'red-20': 'red-20', 'yellow-40': 'yellow-40', 'yellow-20': 'yellow-20', } as const; type PaddingType = 'none' | 'xxs' | 'xs' | 's' | 'm' | 'l' | 'xl'; export const PADDING = { none: 'none', xxs: 'xxs', xs: 'xs', s: 's', m: 'm', l: 'l', xl: 'xl', } as const; export type BoxPropsType = { /** * Children to be rendered inside of the Box * @example Text inside Box */ children?: React.ReactNode; /** * Additional class names */ className?: string | null | undefined; /** * Box background color * @example Text on a 'green-30' background */ color?: ColorType | null | undefined; /** * Box shadow * @example Text inside box with shadow * @default false */ shadow?: ResponsivePropType; /** * Padding size. Defaults to 'm' size, pass null to set it to 0 * @example Text inside Box with large padding */ padding?: ResponsivePropType; /** * Disable border radius * @example Text inside Box with no border radius * @default false */ noBorderRadius?: ResponsivePropType; /** * Show border * @example Text inside bordered Box * @default false */ border?: ResponsivePropType; /** * Border color (works only with `border` prop) * @example Text inside Box with 'green-40' border */ borderColor?: ColorType | null | undefined; } & Omit< React.AllHTMLAttributes, | 'children' | 'className' | 'color' | 'shadow' | 'padding' | 'noBorderRadius' | 'border' | 'borderColor' >; /** * Container for grouping elements. It provides padding, background color, border and shadow. * * @see react docs: https://styleguide.brainly.com/latest/docs/interactive.html#boxes * @see twig-compatible docs: https://styleguide.brainly.com/latest/docs/containers.html#box * * @example Text inside Box * @returns {JSX.Element} Box component */ const Box = React.forwardRef( ( { children, className, color = COLOR.transparent, padding = 'm', border = false, borderColor = COLOR['gray-20'], noBorderRadius = false, shadow = false, ...props }: BoxPropsType, ref ) => { const classes = classNames( 'sg-box', { [`sg-box--${String(color)}`]: color, [`sg-box--border-color-${String(borderColor)}`]: border && borderColor, }, ...generateResponsiveClassNames( shadow => (shadow ? 'sg-box--shadow' : 'sg-box--no-shadow'), shadow ), ...generateResponsiveClassNames( noBorderRadius => noBorderRadius ? 'sg-box--no-border-radius' : 'sg-box--border-radius', noBorderRadius ), ...generateResponsiveClassNames( border => (border ? 'sg-box--border' : 'sg-box--no-border'), border ), ...generateResponsiveClassNames( padding => `sg-box--padding-${String(padding)}`, padding ), ...generateResponsiveClassNames( ([padding, border]: [PaddingType, boolean]) => padding && border ? `sg-box--padding-${padding}-border` : '', mergeResponsiveProps([padding, border]) ), ...generateResponsiveClassNames( ([border, borderColor]: [boolean, ColorType]) => border && borderColor ? `sg-box--border-color-${String(borderColor)}` : '', mergeResponsiveProps([border, borderColor]) ), className ); return (
{children}
); } ); Box.displayName = 'Box'; export default Box;