Implement shadow on DialogHeader in static modals

This commit is contained in:
Justin Edmund 2023-01-21 03:42:29 -08:00
parent 16ed034b16
commit baeaf4f73d
8 changed files with 108 additions and 35 deletions

View file

@ -29,19 +29,10 @@ const AboutModal = () => {
</DialogTrigger>
<DialogContent
className="About"
title={t('menu.about')}
onOpenAutoFocus={(event) => event.preventDefault()}
onEscapeKeyDown={() => {}}
>
<div className="DialogHeader">
<DialogTitle className="DialogTitle">{t('menu.about')}</DialogTitle>
<DialogClose className="DialogClose" asChild>
<span>
<CrossIcon />
</span>
</DialogClose>
</div>
<div>
<div className="sections">
<section>
<p>

View file

@ -1,6 +1,5 @@
.Changelog.DialogContent {
gap: 0;
padding-bottom: $unit-4x;
& > div:not(.DialogHeader) {
padding: 0 $unit-4x;
@ -30,6 +29,11 @@
display: grid;
grid-template-rows: 1fr auto;
gap: $unit;
& > h4 {
font-weight: $medium;
font-size: $font-regular;
}
}
.items {
@ -66,6 +70,7 @@
li {
margin-bottom: $unit-half;
font-size: $font-regular;
}
}
}

View file

@ -26,20 +26,10 @@ const ChangelogModal = () => {
</DialogTrigger>
<DialogContent
className="Changelog"
title={t('menu.changelog')}
onOpenAutoFocus={(event) => event.preventDefault()}
onEscapeKeyDown={() => {}}
>
<div className="DialogHeader">
<DialogTitle className="DialogTitle">
{t('menu.changelog')}
</DialogTitle>
<DialogClose className="DialogClose" asChild>
<span>
<CrossIcon />
</span>
</DialogClose>
</div>
<div className="updates">
<section className="version" data-version="1.0">
<div className="top">

View file

@ -81,17 +81,45 @@ const CharacterModal = ({
// UI state
const [open, setOpen] = useState(false)
const [scrolled, setScrolled] = useState(false)
const [formValid, setFormValid] = useState(false)
// Classes
const headerClasses = classNames({
DialogHeader: true,
Short: true,
Scrolled: scrolled,
})
// Callbacks and Hooks
const onScroll = useCallback((event: Event) => {
// const dialogContent = event.target as HTMLDivElement
// const { scrollTop } = dialogContent
// if (scrollTop > 150) {
// console.log(scrollTop, scrollTop % 5)
// if (scrollTop > 20) setScrolled(true)
// else setScrolled(false)
// console.log('scrollTop', scrollTop)
// }
}, [])
useEffect(() => {
setOpen(modalOpen)
}, [modalOpen])
useEffect(() => {
//add eventlistener to window
// const dialogContent = document.querySelector('.DialogContent')
// if (dialogContent) {
// dialogContent.addEventListener('scroll', onScroll, { passive: true })
// // remove event on unmount to prevent a memory leak with the cleanup
// return () => {
// // what does passive do?
// dialogContent.removeEventListener('scroll', onScroll)
// }
// }
}, [])
// Character properties: Perpetuity
const [perpetuity, setPerpetuity] = useState(false)

View file

@ -49,8 +49,14 @@
width: 100%;
}
.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;

View file

@ -1,15 +1,20 @@
import React from 'react'
import React, { useEffect } from 'react'
import * as DialogPrimitive from '@radix-ui/react-dialog'
import classNames from 'classnames'
import './index.scss'
import { DialogClose, DialogTitle } from '~components/Dialog'
import Overlay from '~components/Overlay'
import CrossIcon from '~public/icons/Cross.svg'
import './index.scss'
interface Props
extends React.DetailedHTMLProps<
React.DialogHTMLAttributes<HTMLDivElement>,
HTMLDivElement
> {
header?: React.ReactNode
title?: string
onEscapeKeyDown: (event: KeyboardEvent) => void
onOpenAutoFocus: (event: Event) => void
}
@ -18,10 +23,60 @@ const DialogContent = React.forwardRef<HTMLDivElement, Props>(function dialog(
{ children, ...props },
forwardedRef
) {
// Classes
const classes = classNames(props.className, {
DialogContent: true,
})
// Refs
const headerRef = React.createRef<HTMLDivElement>()
const containerRef = React.createRef<HTMLDivElement>()
// Elements
const genericHeader = (
<div className="DialogHeader" ref={headerRef}>
<DialogTitle className="DialogTitle">
{props.title ? props.title : ''}
</DialogTitle>
<DialogClose className="DialogClose" asChild>
<span>
<CrossIcon />
</span>
</DialogClose>
</div>
)
// Handlers
function handleScroll(event: React.UIEvent<HTMLDivElement, UIEvent>) {
const headerElement = headerRef.current
const scrollTop = event.currentTarget?.scrollTop
const boxShadowBase = '0 2px 8px'
const maxValue = 50
if (headerElement && scrollTop >= 0) {
const input = scrollTop > maxValue ? maxValue : scrollTop
const boxShadowOpacity = mapRange(input, 0, maxValue, 0.0, 0.16)
const borderOpacity = mapRange(input, 0, maxValue, 0.0, 0.24)
console.log(
`Scroll top: ${scrollTop}, interpolated opacity: ${boxShadowOpacity}`
)
headerElement.style.boxShadow = `${boxShadowBase} rgba(0, 0, 0, ${boxShadowOpacity})`
headerElement.style.borderBottomColor = `rgba(0, 0, 0, ${borderOpacity})`
}
}
function mapRange(
value: number,
low1: number,
high1: number,
low2: number,
high2: number
) {
return low2 + ((high2 - low2) * (value - low1)) / (high1 - low1)
}
return (
<DialogPrimitive.Portal>
<dialog className="Dialog">
@ -32,7 +87,14 @@ const DialogContent = React.forwardRef<HTMLDivElement, Props>(function dialog(
onEscapeKeyDown={props.onEscapeKeyDown}
ref={forwardedRef}
>
{children}
{props.title ? genericHeader : ''}
<div
className="Scrollable"
ref={containerRef}
onScroll={handleScroll}
>
{children}
</div>
</DialogPrimitive.Content>
</dialog>
<Overlay visible={true} open={true} />

View file

@ -27,18 +27,10 @@ const RoadmapModal = () => {
</DialogTrigger>
<DialogContent
className="Roadmap"
title={t('title')}
onOpenAutoFocus={(event) => event.preventDefault()}
onEscapeKeyDown={() => {}}
>
<div className="DialogHeader">
<DialogTitle className="DialogTitle">{t('title')}</DialogTitle>
<DialogClose className="DialogClose" asChild>
<span>
<CrossIcon />
</span>
</DialogClose>
</div>
<div>
<section className="notes">
<p>{t('blurb')}</p>

View file

@ -346,7 +346,6 @@ const WeaponModal = ({
}
return (
// TODO: Refactor into Dialog component
<Dialog open={open} onOpenChange={handleOpenChange}>
<DialogTrigger asChild>{children}</DialogTrigger>
<DialogContent