src/dialog/styled-components.ts (170 lines of code) (raw):

/* Copyright (c) Uber Technologies, Inc. This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. */ import { styled } from '../styles'; import { SIZE, PLACEMENT } from './constants'; import type { Size, Placement } from './types'; const getPlacementStyles = (placement: Placement, gutter: string) => { const defaultStyles = { top: 'auto', right: 'auto', bottom: 'auto', left: 'auto' }; switch (placement) { case PLACEMENT.topLeft: return { ...defaultStyles, top: gutter, left: gutter }; case PLACEMENT.topCenter: return { ...defaultStyles, top: gutter, left: '50%', transform: 'translateX(-50%)' }; case PLACEMENT.topRight: return { ...defaultStyles, top: gutter, right: gutter }; case PLACEMENT.bottomLeft: return { ...defaultStyles, bottom: gutter, left: gutter }; case PLACEMENT.bottomCenter: return { ...defaultStyles, bottom: gutter, left: '50%', transform: 'translateX(-50%)' }; case PLACEMENT.bottomRight: return { ...defaultStyles, bottom: gutter, right: gutter }; case PLACEMENT.center: return { ...defaultStyles, top: '50%', left: '50%', transform: 'translate(-50%, -50%)' }; default: return defaultStyles; } }; const getAnimationStyles = (placement: Placement) => { const transformValuesByPlacement = { [PLACEMENT.topLeft]: ['translateY(16px)', 'translateY(0px)'], [PLACEMENT.topCenter]: [ 'translateX(-50%) translateY(16px)', 'translateX(-50%) translateY(0px)', ], [PLACEMENT.topRight]: ['translateY(16px)', 'translateY(0px)'], [PLACEMENT.bottomLeft]: ['translateY(16px)', 'translateY(0px)'], [PLACEMENT.bottomCenter]: [ 'translateX(-50%) translateY(16px)', 'translateX(-50%) translateY(0px)', ], [PLACEMENT.bottomRight]: ['translateY(16px)', 'translateY(0px)'], [PLACEMENT.center]: [ 'translateX(-50%) translateY(calc(-50% + 16px))', 'translateX(-50%) translateY(-50%)', ], }; return { animationDuration: '400ms', animationTimingFunction: 'cubic-bezier(0.22, 1, 0.36, 1)', animationName: { from: { opacity: 0, transform: transformValuesByPlacement[placement][0], }, to: { opacity: 1, transform: transformValuesByPlacement[placement][1], }, }, }; }; const DIALOG_WIDTHS = { [SIZE.xSmall]: '480px', [SIZE.small]: '640px', [SIZE.medium]: '800px', [SIZE.large]: '100%', }; export const StyledRoot = styled<'div', { $size: Size; $placement: Placement }>( 'div', ({ $theme, $size, $placement = PLACEMENT.center }) => { const narrowViewportGutter = '16px'; const wideViewportGutter = '40px'; return { display: 'flex', flexDirection: 'column', alignItems: 'center', position: 'fixed', maxHeight: `calc(100vh - (2 * ${wideViewportGutter}))`, maxWidth: `calc(100% - (2 * ${wideViewportGutter}))`, borderRadius: $theme.borders.radius500, boxShadow: $theme.lighting.shallowBelow, backgroundColor: $theme.colors.backgroundPrimary, color: $theme.colors.contentPrimary, overflow: 'hidden', border: 'none', width: DIALOG_WIDTHS[$size], ...getPlacementStyles($placement, wideViewportGutter), ...getAnimationStyles($placement), '@media (max-width: 599px)': { width: `calc(100% - (2 * ${narrowViewportGutter}))`, maxWidth: 'none', ...getPlacementStyles(PLACEMENT.bottomCenter, narrowViewportGutter), ...getAnimationStyles(PLACEMENT.bottomCenter), }, }; } ); StyledRoot.displayName = 'StyledRoot'; export const StyledOverlay = styled('div', ({ $theme }) => ({ position: 'fixed', top: 0, left: 0, width: '100%', height: '100%', backgroundColor: $theme.colors.backgroundOverlay, animationDuration: '100ms', animationName: { from: { opacity: 0, }, to: { opacity: 1, }, }, })); StyledOverlay.displayName = 'StyledOverlay'; export const StyledScrollContainer = styled<'div', {}>('div', () => { return { flex: 1, overflowY: 'auto', position: 'relative', width: '100%', }; }); function getLineWrapStyle(numHeadingLines) { if (numHeadingLines === 1) { return { overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis', }; } return { overflow: 'hidden', display: '-webkit-box', WebkitLineClamp: `${numHeadingLines}`, WebkitBoxOrient: 'vertical', }; } export const StyledHeading = styled<'div', { $numHeadingLines: number }>( 'div', // @ts-ignore-next-line - TODO: StyledObject does not support whiteSpace property? ({ $theme, $numHeadingLines = 2 }) => { return { position: 'sticky', top: 0, paddingTop: $theme.sizing.scale800, paddingLeft: $theme.sizing.scale800, paddingRight: $theme.sizing.scale800, '@media (max-width: 599px)': { paddingLeft: $theme.sizing.scale600, paddingRight: $theme.sizing.scale600, }, backgroundColor: $theme.colors.backgroundPrimary, ...getLineWrapStyle($numHeadingLines), ...$theme.typography.HeadingMedium, }; } ); StyledHeading.displayName = 'StyledHeading'; export const StyledBody = styled<'div', {}>('div', ({ $theme }) => { return { marginTop: $theme.sizing.scale300, marginBottom: $theme.sizing.scale800, paddingLeft: $theme.sizing.scale800, paddingRight: $theme.sizing.scale800, '@media (max-width: 599px)': { paddingLeft: $theme.sizing.scale600, paddingRight: $theme.sizing.scale600, }, ...$theme.typography.ParagraphLarge, }; }); StyledBody.displayName = 'StyledBody';