Skip to content

Commit 741856b

Browse files
committed
feat: add right sidebar mini-mode with quick action buttons
- Add three-state right sidebar toggle: expanded → mini (48px) → hidden → expanded - Add rightMiniMode ref and state management to PageLayout - Add right-sidebar-mini slot with centered icon buttons for note/arrow actions - Show FilePlus (create page), ArrowUpDown (swap), and Copy (link) buttons in mini mode - Update PageLayout tests to verify mini-mode toggle behavior - Mark UI polish task 5.3 as DONE
1 parent f5f5a31 commit 741856b

4 files changed

Lines changed: 90 additions & 5 deletions

File tree

new-deepnotes/apps/web/src/features/pages/PageEditorView.vue

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import PageStateScreens from "./screens/PageStateScreens.vue";
3939
import { usePageStatus } from "./usePageStatus";
4040
import { useUserPageLists } from "./useUserPageLists";
4141
import { cursorColorForUserId } from "./page-awareness-utils";
42+
import { FilePlus, ArrowUpDown, Copy } from "lucide-vue-next";
4243
4344
import type { SnapshotRow } from "./page-snapshot-list";
4445
@@ -623,6 +624,61 @@ onMounted(() => {
623624
</div>
624625
</template>
625626

627+
<!-- === Right sidebar mini mode === -->
628+
<template #right-sidebar-mini>
629+
<div class="flex flex-col items-center gap-2">
630+
<!-- Note mini actions -->
631+
<template v-if="selectedNoteId">
632+
<Button
633+
variant="ghost"
634+
size="icon"
635+
class="h-8 w-8"
636+
title="Create new page"
637+
:disabled="cryptoError !== null"
638+
@click="handleCreateNewPage"
639+
>
640+
<FilePlus class="h-4 w-4" />
641+
</Button>
642+
<Button
643+
variant="ghost"
644+
size="icon"
645+
class="h-8 w-8"
646+
title="Swap head and body"
647+
:disabled="cryptoError !== null"
648+
@click="handleSwapHeadBody"
649+
>
650+
<ArrowUpDown class="h-4 w-4" />
651+
</Button>
652+
</template>
653+
654+
<!-- Arrow mini actions -->
655+
<template v-if="selectedArrowId">
656+
<Button
657+
variant="ghost"
658+
size="icon"
659+
class="h-8 w-8"
660+
title="Swap arrowheads"
661+
:disabled="cryptoError !== null"
662+
@click="handleSwapArrowheads"
663+
>
664+
<ArrowUpDown class="h-4 w-4" />
665+
</Button>
666+
</template>
667+
668+
<!-- Common: copy link -->
669+
<Button
670+
v-if="selectedNoteId || selectedArrowId"
671+
variant="ghost"
672+
size="icon"
673+
class="h-8 w-8"
674+
title="Copy link"
675+
@click="selectedNoteId ? handleCopyNoteLink() : handleCopyArrowLink()"
676+
>
677+
<Copy class="h-4 w-4" />
678+
</Button>
679+
</div>
680+
</template>
681+
626682
<!-- === Floating overlay === -->
627683
<template #floating-overlay>
628684
<!-- Bottom-right info -->

new-deepnotes/apps/web/src/layouts/PageLayout.test.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,24 @@ describe("PageLayout", () => {
6868
expect(style).not.toContain("display: none");
6969
});
7070

71-
it("hides right sidebar when toggled off", async () => {
71+
it("switches right sidebar to mini mode on first toggle", async () => {
7272
wrapper = mount(PageLayout);
7373
const toolbar = wrapper.findComponent({ name: "MainToolbarMock" });
7474
await toolbar.vm.$emit("toggle-right");
7575
await wrapper.vm.$nextTick();
7676
const aside = wrapper.findAll("aside");
77+
const style = aside[1]!.attributes("style") ?? "";
78+
expect(style).not.toContain("display: none");
79+
expect(style).toContain("48px");
80+
});
81+
82+
it("hides right sidebar on second toggle", async () => {
83+
wrapper = mount(PageLayout);
84+
const toolbar = wrapper.findComponent({ name: "MainToolbarMock" });
85+
await toolbar.vm.$emit("toggle-right");
86+
await toolbar.vm.$emit("toggle-right");
87+
await wrapper.vm.$nextTick();
88+
const aside = wrapper.findAll("aside");
7789
expect(aside[1]!.attributes("style")).toContain("display: none");
7890
});
7991

new-deepnotes/apps/web/src/layouts/PageLayout.vue

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,25 @@ import MainToolbar from "@/features/spatial/MainToolbar.vue";
66
// --- sidebar state ---
77
const leftExpanded = ref(true);
88
const rightExpanded = ref(true);
9+
const rightMiniMode = ref(false);
910
const leftWidth = ref(240);
1011
1112
function toggleLeft() {
1213
leftExpanded.value = !leftExpanded.value;
1314
}
1415
function toggleRight() {
15-
rightExpanded.value = !rightExpanded.value;
16+
if (rightExpanded.value && !rightMiniMode.value) {
17+
// expanded -> mini
18+
rightMiniMode.value = true;
19+
} else if (rightExpanded.value && rightMiniMode.value) {
20+
// mini -> hidden
21+
rightExpanded.value = false;
22+
rightMiniMode.value = false;
23+
} else {
24+
// hidden -> expanded
25+
rightExpanded.value = true;
26+
rightMiniMode.value = false;
27+
}
1628
}
1729
function resetLeftWidth() {
1830
leftWidth.value = 240;
@@ -22,6 +34,7 @@ function resetLeftWidth() {
2234
provide("pageLayout", {
2335
leftExpanded,
2436
rightExpanded,
37+
rightMiniMode,
2538
leftWidth,
2639
toggleLeft,
2740
toggleRight,
@@ -103,9 +116,13 @@ function onResizePointerUp(e: PointerEvent) {
103116
<aside
104117
v-show="rightExpanded"
105118
class="border-border/40 bg-muted/30 flex flex-col overflow-y-auto border-l"
106-
:style="{ width: '300px', minWidth: '300px' }"
119+
:class="rightMiniMode ? 'items-center' : ''"
120+
:style="{ width: rightMiniMode ? '48px' : '300px', minWidth: rightMiniMode ? '48px' : '300px' }"
107121
>
108-
<div class="p-2">
122+
<div v-if="rightMiniMode" class="flex flex-col items-center gap-1 py-2">
123+
<slot name="right-sidebar-mini" />
124+
</div>
125+
<div v-else class="p-2">
109126
<slot name="right-sidebar" />
110127
</div>
111128
</aside>

new-deepnotes/docs/UI_POLISH_PROGRESS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@ Tracks execution of `UI_POLISH_PLAN.md` (areas around the main section in the pa
1414
| **5.1** | Right sidebar: styled selects, height control, arrow head selects | **DONE** | `NotePropertiesCard.vue`, `ArrowPropertiesCard.vue`, `PageEditorView.vue` |
1515
| **5.1b** | Right sidebar: consolidate page-level cards, add missing controls (swap, timestamps, copy link, local collapsing, anchors) | **DONE** | `NotePropertiesCard.vue`, `ArrowPropertiesCard.vue`, `PageEditorView.vue` |
1616
| **5.2** | Right sidebar: "Create new page" functionality | `PARTIAL` | `NotePropertiesCard.vue` — UI added, crypto stubbed |
17-
| **5.3** | Right sidebar: mini-mode (48px collapsed strip) | `NOT STARTED` | `PageLayout.vue` |
17+
| **5.3** | Right sidebar: mini-mode (48px collapsed strip) | **DONE** | `PageLayout.vue`, `PageEditorView.vue` |
1818
| **7** | Keyboard shortcut parity (high-impact missing shortcuts) | `NOT STARTED` | `useSpatialKeyboard.ts` |

0 commit comments

Comments
 (0)