From 3203601de5ec3661d6fa4af38871d1e423c5673d Mon Sep 17 00:00:00 2001 From: Darragh Van Tichelen Date: Sun, 20 Oct 2024 20:59:56 +0200 Subject: [PATCH] feat(Notes): Add ability to pop-out notes --- CHANGELOG.md | 5 + client/src/core/components/WindowPortal.vue | 109 ++++++++++++++++++++ client/src/core/components/modals/Modal.vue | 89 ++++++++++++---- client/src/game/systems/modals/index.ts | 4 + client/src/game/systems/modals/state.ts | 3 + client/src/game/ui/notes/NoteDialog.vue | 41 +++++++- 6 files changed, 226 insertions(+), 25 deletions(-) create mode 100644 client/src/core/components/WindowPortal.vue diff --git a/CHANGELOG.md b/CHANGELOG.md index 57361994d..4ead41ef2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,11 @@ tech changes will usually be stripped from release notes for the public ## Unreleased +### Added + +- Notes: + - Notes can now be popped out to a separate window + ### Changed - Dashboard: diff --git a/client/src/core/components/WindowPortal.vue b/client/src/core/components/WindowPortal.vue new file mode 100644 index 000000000..70051cf61 --- /dev/null +++ b/client/src/core/components/WindowPortal.vue @@ -0,0 +1,109 @@ + + + diff --git a/client/src/core/components/modals/Modal.vue b/client/src/core/components/modals/Modal.vue index 81bfe9af7..eed4c3614 100644 --- a/client/src/core/components/modals/Modal.vue +++ b/client/src/core/components/modals/Modal.vue @@ -1,10 +1,22 @@ @@ -182,15 +228,18 @@ function dragOver(_event: DragEvent): void { transition: opacity 0.3s ease; } -.modal-container { - pointer-events: auto; - position: absolute; - width: auto; - height: auto; - border-radius: 2px; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33); - font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", - sans-serif; +/* Use a layer to ensure components can override these styles when passing an extraClass */ +@layer base-modals { + .modal-container { + pointer-events: auto; + position: absolute; + width: auto; + height: auto; + border-radius: 2px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33); + font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", + sans-serif; + } } .modal-enter { diff --git a/client/src/game/systems/modals/index.ts b/client/src/game/systems/modals/index.ts index 12bc3848d..dae0fcad4 100644 --- a/client/src/game/systems/modals/index.ts +++ b/client/src/game/systems/modals/index.ts @@ -37,6 +37,10 @@ class ModalSystem implements System { } focus(index: ModalIndex): void { + // Interactin with popped modals (i.e. diferent windows) + // is funky and it doesn't make much sense anyway, so just skip them + if ($.poppedModals.has(index)) return; + $.openModals.add(index); if (raw.modalOrder.at(-1) === index) return; const orderId = raw.modalOrder.findIndex((m) => m === index); diff --git a/client/src/game/systems/modals/state.ts b/client/src/game/systems/modals/state.ts index fa4fa6e09..597481805 100644 --- a/client/src/game/systems/modals/state.ts +++ b/client/src/game/systems/modals/state.ts @@ -15,6 +15,8 @@ interface ReactiveModalState { modalOrder: ModalIndex[]; // Dynamically injected modals extraModals: IndexedModal[]; + // Popped out modals + poppedModals: Set; } const state = buildState( @@ -22,6 +24,7 @@ const state = buildState( openModals: new Set(), modalOrder: [], extraModals: [], + poppedModals: new Set(), }, { fixedModals: [], diff --git a/client/src/game/ui/notes/NoteDialog.vue b/client/src/game/ui/notes/NoteDialog.vue index 015590bd1..ec6b768d5 100644 --- a/client/src/game/ui/notes/NoteDialog.vue +++ b/client/src/game/ui/notes/NoteDialog.vue @@ -110,10 +110,34 @@ function close(): void { function setText(event: Event, sync: boolean): void { noteSystem.setText(props.uuid, (event.target as HTMLTextAreaElement).value, sync, !sync); } + +const isWindowed = ref(false); +const previousWindowState = { width: "", height: "" }; +function windowToggle(windowed: boolean): void { + isWindowed.value = windowed; + if (windowed) { + previousWindowState.width = modal.value!.container.style.width; + previousWindowState.height = modal.value!.container.style.height; + modal.value!.container.style.width = "auto"; + modal.value!.container.style.height = "auto"; + } else { + modal.value!.container.style.width = previousWindowState.width; + modal.value!.container.style.height = previousWindowState.height; + } +}