import * as React from "react"; import { css, cx } from "@emotion/css"; import { visuallyHidden } from "../../../shared/styles/styleUtils"; interface BgImageOptions { size?: React.CSSProperties["backgroundSize"]; position?: React.CSSProperties["backgroundPosition"]; repeat?: React.CSSProperties["backgroundRepeat"]; } export interface BoxProps { /** * Applies a background color */ bgColor?: React.CSSProperties["backgroundColor"]; /** * Applies a background image */ bgImageUrl?: string; /** * Options for how the background image should be displayed */ bgImageOptions?: BgImageOptions; /** * Modifies the `display` property */ display?: React.CSSProperties["display"]; /** * Vertically aligns the direct children of the component */ vertAlignChildren?: "top" | "bottom" | "center"; /** * Hides the component and it's children visually, but still keeps them visual to screenreaders */ isVisuallyHidden?: boolean; /** * Aligns text or inline and inline-block elements */ textAlign?: React.CSSProperties["textAlign"]; /** * Which HTML tag to render the component with */ tag?: keyof React.ReactHTML; /** * Allows custom styling */ className?: string; /** * Human-readable selector used for writing tests */ "data-cy"?: string; children?: React.ReactNode; } const Box = (props: BoxProps) => { const { bgColor, bgImageUrl, bgImageOptions = { size: undefined, position: undefined, repeat: undefined }, display, vertAlignChildren, isVisuallyHidden, textAlign, tag = "div", className, "data-cy": dataCy = "box", ...other } = props; const getBgImageOptionVal = (option: "size" | "position" | "repeat") => bgImageOptions ? bgImageOptions[option] : null; const displayValue = vertAlignChildren ? "flex" : display; const vertAlignMap = { top: "flex-start", bottom: "flex-end", center: "center" }; const getVertAlignChildrenStyles = vertAlignChildren => vertAlignChildren ? ` display: flex; flex-direction: column; justify-content: ${vertAlignMap[vertAlignChildren]}; ` : null; const BoxEl = tag; const boxStyles = css` background-color: ${bgColor}; background-image: ${bgImageUrl ? `url(${bgImageUrl})` : null}; background-position: ${getBgImageOptionVal("position")}; background-repeat: ${getBgImageOptionVal("repeat") || "no-repeat"}; background-size: ${getBgImageOptionVal("size")}; display: ${displayValue}; text-align: ${textAlign}; ${isVisuallyHidden ? visuallyHidden : null}; ${getVertAlignChildrenStyles(vertAlignChildren)}; `; return ( ); }; export default Box;