Fix dialog styles

This commit is contained in:
Justin Edmund 2023-06-23 19:13:57 -07:00
parent 4c5fb3c28d
commit bf051376d0
6 changed files with 197 additions and 126 deletions

View file

@ -1,4 +1,4 @@
.Dialog { .dialog {
position: fixed; position: fixed;
box-sizing: border-box; box-sizing: border-box;
background: none; background: none;
@ -13,7 +13,7 @@
color: inherit; color: inherit;
z-index: 10; z-index: 10;
.DialogContent { .dialogContent {
$multiplier: 4; $multiplier: 4;
// animation: $duration-modal-open cubic-bezier(0.16, 1, 0.3, 1) 0s 1 normal // animation: $duration-modal-open cubic-bezier(0.16, 1, 0.3, 1) 0s 1 normal
@ -59,136 +59,19 @@
width: 100%; width: 100%;
} }
.Container { .container {
overflow-y: hidden; overflow-y: hidden;
&.Scrollable { &.scrollable {
overflow-y: auto; 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 { .DialogDescription {
color: var(--text-secondary); color: var(--text-secondary);
flex-grow: 1; 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 { .Fields {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View file

@ -24,7 +24,7 @@ const DialogContent = React.forwardRef<HTMLDivElement, Props>(function Dialog(
) { ) {
// Classes // Classes
const classes = classNames(props.className, { const classes = classNames(props.className, {
DialogContent: true, [styles.dialogContent]: true,
}) })
// Handlers // Handlers
@ -89,10 +89,15 @@ const DialogContent = React.forwardRef<HTMLDivElement, Props>(function Dialog(
const calculateFooterShadow = debounce(() => { const calculateFooterShadow = debounce(() => {
const boxShadowBase = '0 -2px 8px' const boxShadowBase = '0 -2px 8px'
const scrollable = document.querySelector('.Scrollable') const scrollable = document.querySelector(`.${styles.scrollValue}`)
const footer = props.footerref const footer = props.footerref
if (footer && footer.current) { if (footer && footer.current) {
console.log(
scrollable,
scrollable?.clientHeight,
scrollable?.scrollHeight
)
if (scrollable && scrollable.clientHeight >= scrollable.scrollHeight) { if (scrollable && scrollable.clientHeight >= scrollable.scrollHeight) {
footer.current.style.boxShadow = `${boxShadowBase} rgba(0, 0, 0, 0)` footer.current.style.boxShadow = `${boxShadowBase} rgba(0, 0, 0, 0)`
footer.current.style.borderTopColor = `rgba(0, 0, 0, 0)` footer.current.style.borderTopColor = `rgba(0, 0, 0, 0)`
@ -124,7 +129,7 @@ const DialogContent = React.forwardRef<HTMLDivElement, Props>(function Dialog(
return ( return (
<DialogPrimitive.Portal> <DialogPrimitive.Portal>
<dialog className="Dialog"> <dialog className={styles.dialog}>
<DialogPrimitive.Content <DialogPrimitive.Content
{...props} {...props}
className={classes} className={classes}
@ -134,8 +139,8 @@ const DialogContent = React.forwardRef<HTMLDivElement, Props>(function Dialog(
> >
<div <div
className={classNames({ className={classNames({
Container: true, [styles.container]: true,
Scrollable: scrollable, [styles.scrollable]: scrollable,
})} })}
onScroll={handleScroll} onScroll={handleScroll}
> >

View file

@ -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;
}
}

View file

@ -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<HTMLDivElement, Props>(
function dialogFooter(
{
leftElements,
rightElements,
image,
children,
...props
}: PropsWithChildren<Props>,
forwardedRef
) {
const classes = classNames({
[styles.footer]: true,
})
return (
<footer {...props} className={classes} ref={forwardedRef}>
<div className={styles.left}>{leftElements}</div>
<div className={styles.right}>{rightElements}</div>
</footer>
)
}
)
export default DialogFooter

View file

@ -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;
}
}
}

View file

@ -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<HTMLDivElement, Props>(
function dialogHeader(
{ title, subtitle, image, children, ...props }: PropsWithChildren<Props>,
forwardedRef
) {
const classes = classNames({
[styles.header]: true,
})
return (
<header {...props} className={classes} ref={forwardedRef}>
{image && (
<img alt={image.alt} className={styles.image} src={image.src} />
)}
<div className={styles.top}>
{subtitle && <div className={styles.subtitle}>{subtitle}</div>}
<div className={styles.title}>{title}</div>
</div>
<DialogPrimitive.Close className={styles.close}>
<CrossIcon />
</DialogPrimitive.Close>
</header>
)
}
)
export default DialogHeader