feat(revisions): display sidebar in full-height

This commit is contained in:
Elian Doran
2026-04-18 16:48:54 +03:00
parent f22eaee4e2
commit 01c57fc8db
4 changed files with 87 additions and 46 deletions

View File

@@ -1158,6 +1158,33 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href
margin: 0 12px;
}
.modal-content-with-sidebar {
flex-direction: row !important;
}
.modal-content-with-sidebar > .modal-sidebar {
display: flex;
flex-direction: column;
border-right: 1px solid var(--main-border-color);
overflow: auto;
flex-shrink: 0;
}
.modal-content-with-sidebar > .modal-main {
display: flex;
flex-direction: column;
flex-grow: 1;
min-width: 0;
min-height: 0;
overflow: hidden;
}
.modal-content-with-sidebar > .modal-main > .modal-body {
overflow: auto;
flex-grow: 1;
min-height: 0;
}
.ck-mentions .ck-button {
font-size: var(--detail-font-size) !important;
padding: 5px;

View File

@@ -103,12 +103,17 @@ body.desktop .revisions-dialog {
opacity: 0.6;
}
.modal-content {
height: 80vh;
}
.revision-content-wrapper {
flex-grow: 1;
margin-inline: 20px;
padding-inline: 20px;
display: flex;
flex-direction: column;
min-width: 0;
overflow: auto;
}
.revision-toolbar-separator {

View File

@@ -67,7 +67,6 @@ export default function RevisionsDialog() {
size="xl"
title={t("revisions.note_revisions")}
helpPageId="vZWERwf8U3nx"
bodyStyle={{ display: "flex", height: "80vh" }}
header={note && (
<RevisionsMenu
note={note}
@@ -82,6 +81,18 @@ export default function RevisionsDialog() {
hasRevisions={!!revisions?.length}
/>
)}
sidebar={
<RevisionsList
revisions={revisions ?? []}
onSelect={(revisionId) => {
const correspondingRevision = (revisions ?? []).find((r) => r.revisionId === revisionId);
if (correspondingRevision) {
setCurrentRevision(correspondingRevision);
}
}}
currentRevision={currentRevision}
/>
}
onHidden={() => {
setShown(false);
setShowDiff(false);
@@ -91,17 +102,6 @@ export default function RevisionsDialog() {
}}
show={shown}
>
<RevisionsList
revisions={revisions ?? []}
onSelect={(revisionId) => {
const correspondingRevision = (revisions ?? []).find((r) => r.revisionId === revisionId);
if (correspondingRevision) {
setCurrentRevision(correspondingRevision);
}
}}
currentRevision={currentRevision}
/>
<div className="revision-content-wrapper">
<RevisionPreview
noteContent={noteContent}

View File

@@ -77,9 +77,15 @@ export interface ModalProps {
* If true, the modal will not focus itself after becoming visible.
*/
noFocus?: boolean;
/**
* Content to display as a full-height sidebar on the left side of the modal.
* When set, the modal layout switches to a horizontal split with the sidebar
* spanning the entire height alongside the header, body and footer.
*/
sidebar?: ComponentChildren;
}
export default function Modal({ children, className, size, title, customTitleBarButtons: titleBarButtons, header, footer, footerStyle, footerAlignment, onShown, onSubmit, helpPageId, minWidth, maxWidth, zIndex, scrollable, onHidden, modalRef: externalModalRef, formRef, bodyStyle, show, stackable, keepInDom, noFocus }: ModalProps) {
export default function Modal({ children, className, size, title, customTitleBarButtons: titleBarButtons, header, footer, footerStyle, footerAlignment, onShown, onSubmit, helpPageId, minWidth, maxWidth, zIndex, scrollable, onHidden, modalRef: externalModalRef, formRef, bodyStyle, show, stackable, keepInDom, noFocus, sidebar }: ModalProps) {
const modalRef = useSyncedRef<HTMLDivElement>(externalModalRef);
const modalInstanceRef = useRef<BootstrapModal>();
const elementToFocus = useRef<Element | null>();
@@ -144,41 +150,44 @@ export default function Modal({ children, className, size, title, customTitleBar
return (
<div className={`modal fade mx-auto ${className}`} tabIndex={-1} style={dialogStyle} role="dialog" ref={modalRef}>
{(show || keepInDom) && <div className={`modal-dialog modal-${size} ${scrollable ? "modal-dialog-scrollable" : ""}`} style={documentStyle} role="document">
<div className="modal-content">
<div className="modal-header">
{!title || typeof title === "string" ? (
<h5 className="modal-title">{title ?? <>&nbsp;</>}</h5>
<div className={clsx("modal-content", sidebar && "modal-content-with-sidebar")}>
{sidebar && <div className="modal-sidebar">{sidebar}</div>}
<div className="modal-main">
<div className="modal-header">
{!title || typeof title === "string" ? (
<h5 className="modal-title">{title ?? <>&nbsp;</>}</h5>
) : (
title
)}
{header}
{helpPageId && (
<button className="help-button" type="button" data-in-app-help={helpPageId} title={t("modal.help_title")}>?</button>
)}
{titleBarButtons?.filter((b) => b !== null).map((titleBarButton) => (
<button type="button"
className={clsx("custom-title-bar-button bx", titleBarButton.iconClassName)}
title={titleBarButton.title}
onClick={titleBarButton.onClick} />
))}
<button type="button" className="btn-close" data-bs-dismiss="modal" aria-label={t("modal.close")} />
</div>
{onSubmit ? (
<form ref={formRef} onSubmit={(e) => {
e.preventDefault();
onSubmit();
}}>
<ModalInner footer={footer} bodyStyle={bodyStyle} footerStyle={footerStyle} footerAlignment={footerAlignment}>{children}</ModalInner>
</form>
) : (
title
<ModalInner footer={footer} bodyStyle={bodyStyle} footerStyle={footerStyle} footerAlignment={footerAlignment}>
{children}
</ModalInner>
)}
{header}
{helpPageId && (
<button className="help-button" type="button" data-in-app-help={helpPageId} title={t("modal.help_title")}>?</button>
)}
{titleBarButtons?.filter((b) => b !== null).map((titleBarButton) => (
<button type="button"
className={clsx("custom-title-bar-button bx", titleBarButton.iconClassName)}
title={titleBarButton.title}
onClick={titleBarButton.onClick} />
))}
<button type="button" className="btn-close" data-bs-dismiss="modal" aria-label={t("modal.close")} />
</div>
{onSubmit ? (
<form ref={formRef} onSubmit={(e) => {
e.preventDefault();
onSubmit();
}}>
<ModalInner footer={footer} bodyStyle={bodyStyle} footerStyle={footerStyle} footerAlignment={footerAlignment}>{children}</ModalInner>
</form>
) : (
<ModalInner footer={footer} bodyStyle={bodyStyle} footerStyle={footerStyle} footerAlignment={footerAlignment}>
{children}
</ModalInner>
)}
</div>
</div>}
</div>