From bf051376d09fffedd448f435645705134740ec6d Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Fri, 23 Jun 2023 19:13:57 -0700 Subject: [PATCH] Fix dialog styles --- .../common/DialogContent/index.module.scss | 125 +----------------- components/common/DialogContent/index.tsx | 15 ++- .../common/DialogFooter/index.module.scss | 20 +++ components/common/DialogFooter/index.tsx | 39 ++++++ .../common/DialogHeader/index.module.scss | 82 ++++++++++++ components/common/DialogHeader/index.tsx | 42 ++++++ 6 files changed, 197 insertions(+), 126 deletions(-) create mode 100644 components/common/DialogFooter/index.module.scss create mode 100644 components/common/DialogFooter/index.tsx create mode 100644 components/common/DialogHeader/index.module.scss create mode 100644 components/common/DialogHeader/index.tsx diff --git a/components/common/DialogContent/index.module.scss b/components/common/DialogContent/index.module.scss index 7d1a311c..9d5e4882 100644 --- a/components/common/DialogContent/index.module.scss +++ b/components/common/DialogContent/index.module.scss @@ -1,4 +1,4 @@ -.Dialog { +.dialog { position: fixed; box-sizing: border-box; background: none; @@ -13,7 +13,7 @@ color: inherit; z-index: 10; - .DialogContent { + .dialogContent { $multiplier: 4; // animation: $duration-modal-open cubic-bezier(0.16, 1, 0.3, 1) 0s 1 normal @@ -59,136 +59,19 @@ width: 100%; } - .Container { + .container { overflow-y: hidden; - &.Scrollable { + &.scrollable { overflow-y: auto; } } - .DialogHeader { - background: var(--dialog-bg); - box-shadow: 0 2px 8px rgba(0, 0, 0, 0); - border-bottom: 1px solid rgba(0, 0, 0, 0); - display: flex; - align-items: center; - gap: $unit-2x; - justify-content: space-between; - padding: $unit-4x ($unit * $multiplier); - position: sticky; - top: 0; - z-index: 10; - - &.Short { - padding-top: $unit-3x; - padding-bottom: $unit-3x; - } - - .left { - display: flex; - flex-direction: column; - flex-grow: 1; - gap: $unit; - - p { - font-size: $font-small; - line-height: 1.25; - } - } - - .DialogImage { - border-radius: $input-corner; - width: $unit-10x; - } - } - - .DialogClose { - background: transparent; - border: none; - - &:hover { - cursor: pointer; - - svg { - fill: $error; - } - } - - svg { - fill: $grey-50; - float: right; - height: 24px; - width: 24px; - } - } - - .DialogTitle { - color: var(--text-primary); - font-size: $font-xlarge; - - h1 { - color: var(--text-primary); - font-size: $font-xlarge; - font-weight: $medium; - text-align: left; - } - } - - .DialogTop { - display: flex; - flex-direction: column; - flex-grow: 1; - gap: calc($unit / 2); - - .SubTitle { - color: var(--text-secondary); - font-size: $font-small; - font-weight: $medium; - } - } - .DialogDescription { color: var(--text-secondary); flex-grow: 1; } - .DialogFooter { - align-items: flex-end; - background: var(--dialog-bg); - bottom: 0; - box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.16); - border-top: 1px solid rgba(0, 0, 0, 0.24); - display: flex; - flex-direction: row; - justify-content: space-between; - padding: ($unit * 1.5) ($unit * $multiplier) $unit-3x; - position: sticky; - - .Buttons { - display: flex; - gap: $unit; - - &.Span { - width: 100%; - - .Button { - width: 100%; - } - } - - &.Spaced { - justify-content: space-between; - } - } - } - - .actions { - display: flex; - justify-content: flex-end; - width: 100%; - } - .Fields { display: flex; flex-direction: column; diff --git a/components/common/DialogContent/index.tsx b/components/common/DialogContent/index.tsx index 92ce3b78..55c14c64 100644 --- a/components/common/DialogContent/index.tsx +++ b/components/common/DialogContent/index.tsx @@ -24,7 +24,7 @@ const DialogContent = React.forwardRef(function Dialog( ) { // Classes const classes = classNames(props.className, { - DialogContent: true, + [styles.dialogContent]: true, }) // Handlers @@ -89,10 +89,15 @@ const DialogContent = React.forwardRef(function Dialog( const calculateFooterShadow = debounce(() => { const boxShadowBase = '0 -2px 8px' - const scrollable = document.querySelector('.Scrollable') + const scrollable = document.querySelector(`.${styles.scrollValue}`) const footer = props.footerref if (footer && footer.current) { + console.log( + scrollable, + scrollable?.clientHeight, + scrollable?.scrollHeight + ) if (scrollable && scrollable.clientHeight >= scrollable.scrollHeight) { footer.current.style.boxShadow = `${boxShadowBase} rgba(0, 0, 0, 0)` footer.current.style.borderTopColor = `rgba(0, 0, 0, 0)` @@ -124,7 +129,7 @@ const DialogContent = React.forwardRef(function Dialog( return ( - + (function Dialog( >
diff --git a/components/common/DialogFooter/index.module.scss b/components/common/DialogFooter/index.module.scss new file mode 100644 index 00000000..3f468f92 --- /dev/null +++ b/components/common/DialogFooter/index.module.scss @@ -0,0 +1,20 @@ +.footer { + $multiplier: 4; + + align-items: flex-end; + background: var(--dialog-bg); + bottom: 0; + box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.16); + border-top: 1px solid rgba(0, 0, 0, 0.24); + display: flex; + flex-direction: row; + justify-content: space-between; + padding: ($unit * 1.5) ($unit * $multiplier) $unit-3x; + position: sticky; + + .left, + .right { + display: flex; + gap: $unit; + } +} diff --git a/components/common/DialogFooter/index.tsx b/components/common/DialogFooter/index.tsx new file mode 100644 index 00000000..1c524aa9 --- /dev/null +++ b/components/common/DialogFooter/index.tsx @@ -0,0 +1,39 @@ +import React, { PropsWithChildren } from 'react' +import classNames from 'classnames' +import * as DialogPrimitive from '@radix-ui/react-dialog' +import styles from './index.module.scss' + +interface Props extends DialogPrimitive.DialogProps { + leftElements?: React.ReactNode[] + rightElements?: React.ReactNode[] + image?: { + alt: string + src: string + } +} + +export const DialogFooter = React.forwardRef( + function dialogFooter( + { + leftElements, + rightElements, + image, + children, + ...props + }: PropsWithChildren, + forwardedRef + ) { + const classes = classNames({ + [styles.footer]: true, + }) + + return ( +
+
{leftElements}
+
{rightElements}
+
+ ) + } +) + +export default DialogFooter diff --git a/components/common/DialogHeader/index.module.scss b/components/common/DialogHeader/index.module.scss new file mode 100644 index 00000000..2f273d63 --- /dev/null +++ b/components/common/DialogHeader/index.module.scss @@ -0,0 +1,82 @@ +.header { + $multiplier: 4; + + background: var(--dialog-bg); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0); + border-bottom: 1px solid rgba(0, 0, 0, 0); + display: flex; + align-items: center; + gap: $unit-2x; + justify-content: space-between; + padding: $unit-4x ($unit * $multiplier); + position: sticky; + top: 0; + z-index: 10; + + &.short { + padding-top: $unit-3x; + padding-bottom: $unit-3x; + } + + .top { + display: flex; + flex-direction: column; + flex-grow: 1; + gap: calc($unit / 2); + } + + .left { + display: flex; + flex-direction: column; + flex-grow: 1; + gap: $unit; + + p { + font-size: $font-small; + line-height: 1.25; + } + } + + .title { + color: var(--text-primary); + font-size: $font-xlarge; + + h1 { + color: var(--text-primary); + font-size: $font-xlarge; + font-weight: $medium; + text-align: left; + } + } + + .subtitle { + color: var(--text-secondary); + font-size: $font-small; + font-weight: $medium; + } + + .image { + border-radius: $input-corner; + width: $unit-10x; + } + + .close { + background: transparent; + border: none; + + &:hover { + cursor: pointer; + + svg { + fill: $error; + } + } + + svg { + fill: $grey-50; + float: right; + height: 24px; + width: 24px; + } + } +} diff --git a/components/common/DialogHeader/index.tsx b/components/common/DialogHeader/index.tsx new file mode 100644 index 00000000..d4dec5c6 --- /dev/null +++ b/components/common/DialogHeader/index.tsx @@ -0,0 +1,42 @@ +import React, { PropsWithChildren } from 'react' +import classNames from 'classnames' +import * as DialogPrimitive from '@radix-ui/react-dialog' +import CrossIcon from '~public/icons/Cross.svg' +import styles from './index.module.scss' + +interface Props extends DialogPrimitive.DialogProps { + title: string + subtitle?: string + image?: { + alt: string + src: string + } +} + +export const DialogHeader = React.forwardRef( + function dialogHeader( + { title, subtitle, image, children, ...props }: PropsWithChildren, + forwardedRef + ) { + const classes = classNames({ + [styles.header]: true, + }) + + return ( +
+ {image && ( + {image.alt} + )} +
+ {subtitle &&
{subtitle}
} +
{title}
+
+ + + +
+ ) + } +) + +export default DialogHeader