forked from Mirrors/gomuks
web/modal: add boxing to modal utility
This commit is contained in:
parent
303ea43834
commit
f4be132313
6 changed files with 48 additions and 54 deletions
|
@ -8,6 +8,21 @@ div.overlay {
|
|||
&.dimmed {
|
||||
background-color: var(--dimmed-overlay-background-color);
|
||||
}
|
||||
|
||||
&.modal > div.modal-box {
|
||||
background-color: var(--background-color);
|
||||
border-radius: 1rem;
|
||||
padding: 1rem;
|
||||
|
||||
max-width: min(80rem, 80vw);
|
||||
max-height: min(80rem, 80vh);
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
|
||||
> div.modal-box-inner {
|
||||
overflow: scroll;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div.lightbox {
|
||||
|
|
|
@ -18,7 +18,9 @@ import React, { JSX, createContext, useCallback, useLayoutEffect, useReducer, us
|
|||
export interface ModalState {
|
||||
content: JSX.Element
|
||||
dimmed?: boolean
|
||||
wrapperClass?: string
|
||||
boxed?: boolean
|
||||
boxClass?: string
|
||||
innerBoxClass?: string
|
||||
onClose?: () => void
|
||||
}
|
||||
|
||||
|
@ -52,18 +54,28 @@ export const ModalWrapper = ({ children }: { children: React.ReactNode }) => {
|
|||
wrapperRef.current.focus()
|
||||
}
|
||||
}, [state])
|
||||
return <ModalContext value={setState}>
|
||||
{children}
|
||||
{state && <div
|
||||
className={`overlay ${state.wrapperClass ?? "modal"} ${state.dimmed ? "dimmed" : ""}`}
|
||||
let modal: JSX.Element | null = null
|
||||
if (state) {
|
||||
let content = <ModalCloseContext value={onClickWrapper}>{state.content}</ModalCloseContext>
|
||||
if (state.boxed) {
|
||||
content = <div className={`modal-box ${state.boxClass ?? ""}`}>
|
||||
<div className={`modal-box-inner ${state.innerBoxClass ?? ""}`}>
|
||||
{content}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
modal = <div
|
||||
className={`overlay modal ${state.dimmed ? "dimmed" : ""}`}
|
||||
onClick={onClickWrapper}
|
||||
onKeyDown={onKeyWrapper}
|
||||
tabIndex={-1}
|
||||
ref={wrapperRef}
|
||||
>
|
||||
<ModalCloseContext value={onClickWrapper}>
|
||||
{state.content}
|
||||
</ModalCloseContext>
|
||||
</div>}
|
||||
{content}
|
||||
</div>
|
||||
}
|
||||
return <ModalContext value={setState}>
|
||||
{children}
|
||||
{modal}
|
||||
</ModalContext>
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ const ConfirmWithMessageModal = ({
|
|||
const onChangeReason = useCallback((evt: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setReason(evt.target.value)
|
||||
}, [])
|
||||
return <div className="confirm-message-modal">
|
||||
return <>
|
||||
<h3>{title}</h3>
|
||||
<div className="timeline-event-container">
|
||||
<TimelineEvent evt={evt} prevEvt={null} disableMenu={true} />
|
||||
|
@ -53,7 +53,7 @@ const ConfirmWithMessageModal = ({
|
|||
<button onClick={closeModal}>Cancel</button>
|
||||
<button onClick={onConfirmWrapped}>{confirmButton}</button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
|
||||
export default ConfirmWithMessageModal
|
||||
|
|
|
@ -19,8 +19,8 @@ import { MemDBEvent, PowerLevelEventContent } from "@/api/types"
|
|||
import ClientContext from "../../ClientContext.ts"
|
||||
import { ModalCloseContext, ModalContext } from "../../modal/Modal.tsx"
|
||||
import { RoomContext, RoomContextData } from "../../roomview/roomcontext.ts"
|
||||
import JSONView from "../../util/JSONView.tsx"
|
||||
import ConfirmWithMessageModal from "./ConfirmWithMessageModal.tsx"
|
||||
import ViewSourceModal from "./ViewSourceModal.tsx"
|
||||
import ViewSourceIcon from "@/icons/code.svg?react"
|
||||
import DeleteIcon from "@/icons/delete.svg?react"
|
||||
import PinIcon from "@/icons/pin.svg?react"
|
||||
|
@ -39,11 +39,17 @@ const EventExtraMenu = ({ evt, room, style }: EventExtraMenuProps) => {
|
|||
const closeModal = use(ModalCloseContext)
|
||||
const openModal = use(ModalContext)
|
||||
const onClickViewSource = useCallback(() => {
|
||||
openModal({ dimmed: true, content: <ViewSourceModal evt={evt}/> })
|
||||
openModal({
|
||||
dimmed: true,
|
||||
boxed: true,
|
||||
content: <JSONView data={evt} />,
|
||||
})
|
||||
}, [evt, openModal])
|
||||
const onClickReport = useCallback(() => {
|
||||
openModal({
|
||||
dimmed: true,
|
||||
boxed: true,
|
||||
innerBoxClass: "confirm-message-modal",
|
||||
content: <RoomContext value={new RoomContextData(room)}>
|
||||
<ConfirmWithMessageModal
|
||||
evt={evt}
|
||||
|
@ -62,6 +68,8 @@ const EventExtraMenu = ({ evt, room, style }: EventExtraMenuProps) => {
|
|||
const onClickRedact = useCallback(() => {
|
||||
openModal({
|
||||
dimmed: true,
|
||||
boxed: true,
|
||||
innerBoxClass: "confirm-message-modal",
|
||||
content: <RoomContext value={new RoomContextData(room)}>
|
||||
<ConfirmWithMessageModal
|
||||
evt={evt}
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
// gomuks - A Matrix client written in Go.
|
||||
// Copyright (C) 2024 Tulir Asokan
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
import { MemDBEvent } from "@/api/types"
|
||||
import JSONView from "../../util/JSONView.tsx"
|
||||
|
||||
interface ViewSourceModalProps {
|
||||
evt: MemDBEvent
|
||||
}
|
||||
|
||||
const ViewSourceModal = ({ evt }: ViewSourceModalProps) => {
|
||||
return <div className="view-source-modal">
|
||||
<JSONView data={evt} />
|
||||
</div>
|
||||
}
|
||||
|
||||
export default ViewSourceModal
|
|
@ -45,21 +45,9 @@ div.event-context-menu-extra {
|
|||
}
|
||||
}
|
||||
|
||||
div.view-source-modal {
|
||||
max-width: min(80rem, 80vw);
|
||||
max-height: min(80rem, 80vh);
|
||||
overflow: auto;
|
||||
background-color: var(--background-color);
|
||||
border-radius: 1rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
div.confirm-message-modal {
|
||||
width: min(40rem, 80vw);
|
||||
max-height: min(40rem, 80vh);
|
||||
background-color: var(--background-color);
|
||||
border-radius: 1rem;
|
||||
padding: 1rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: .5rem;
|
||||
|
|
Loading…
Add table
Reference in a new issue