Skip to content

Commit 89c7cf5

Browse files
refactor: unify sidebar layout and section headers (#708)
* refactor: unify sidebar section headers * refactor: align math sidebar with tree spacing * refactor: standardize tools sidebar items * refactor: standardize section header height and remove spacing hacks * refactor: make SidebarHeader flexible with sectionTitle prop and action slot * refactor: add headerGap prop and leftHeader slot to TwoColumn * refactor: add headerGap prop to ThreeColumn * refactor: adopt header-gap CSS variable and sectionTitle in sidebars * refactor: move math sheet header to leftHeader slot * refactor: use leftHeader slot in Devtools view
1 parent d9f486b commit 89c7cf5

12 files changed

Lines changed: 261 additions & 184 deletions

File tree

src/renderer/components/layout/ThreeColumn.vue

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ const props = withDefaults(
88
showList: boolean
99
sidebarWidth?: number
1010
listWidth?: number
11+
headerGap?: number
1112
}>(),
1213
{
1314
sidebarWidth: LAYOUT_DEFAULTS.sidebar.width,
1415
listWidth: LAYOUT_DEFAULTS.list.width,
16+
headerGap: 0,
1517
},
1618
)
1719
@@ -94,7 +96,12 @@ const isResizing = computed(
9496
:style="{ width: `${internalSidebarWidth}px` }"
9597
class="shrink-0 overflow-hidden"
9698
>
97-
<slot name="sidebar" />
99+
<div
100+
class="h-full"
101+
:style="{ '--header-gap': `${props.headerGap}px` }"
102+
>
103+
<slot name="sidebar" />
104+
</div>
98105
</div>
99106
<div
100107
v-if="showSidebar"

src/renderer/components/layout/TwoColumn.vue

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ interface Props {
99
rightSize?: string
1010
showBack?: boolean
1111
topSpace?: number
12+
headerGap?: number
1213
}
1314
1415
interface Emits {
@@ -20,6 +21,7 @@ const props = withDefaults(defineProps<Props>(), {
2021
rightSize: '1fr',
2122
showBack: true,
2223
topSpace: 0,
24+
headerGap: 0,
2325
})
2426
2527
const emit = defineEmits<Emits>()
@@ -31,6 +33,7 @@ const gridTemplateColumns = computed(() => {
3133
const leftHeaderStyle = computed(() => {
3234
return {
3335
paddingTop: `calc(var(--content-top-offset) + ${props.topSpace}px)`,
36+
paddingBottom: `${props.headerGap}px`,
3437
}
3538
})
3639
</script>
@@ -41,22 +44,24 @@ const leftHeaderStyle = computed(() => {
4144
:style="{ gridTemplateColumns }"
4245
>
4346
<div class="grid h-full min-h-0 grid-rows-[auto_1fr] overflow-hidden">
44-
<div
45-
class="flex items-center justify-between gap-2 overflow-hidden px-2 pb-2"
46-
:style="leftHeaderStyle"
47-
>
48-
<div class="truncate font-bold">
49-
{{ title }}
50-
</div>
51-
<UiActionButton
52-
v-if="showBack"
53-
:tooltip="i18n.t('button.back')"
54-
class="shrink-0"
55-
@click="() => emit('back')"
47+
<slot name="leftHeader">
48+
<div
49+
class="flex items-center justify-between gap-2 px-2"
50+
:style="leftHeaderStyle"
5651
>
57-
<ArrowLeft class="h-4 w-4" />
58-
</UiActionButton>
59-
</div>
52+
<div class="min-w-0 truncate px-1 leading-5 font-bold select-none">
53+
{{ title }}
54+
</div>
55+
<UiActionButton
56+
v-if="showBack"
57+
:tooltip="i18n.t('button.back')"
58+
class="shrink-0"
59+
@click="() => emit('back')"
60+
>
61+
<ArrowLeft class="h-4 w-4" />
62+
</UiActionButton>
63+
</div>
64+
</slot>
6065
<div class="h-full min-h-0 overflow-auto">
6166
<slot name="left" />
6267
</div>

src/renderer/components/math-notebook/SheetList.vue

Lines changed: 52 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as ContextMenu from '@/components/ui/shadcn/context-menu'
33
import { useApp, useMathNotebook } from '@/composables'
44
import { i18n } from '@/electron'
55
import { format } from 'date-fns'
6-
import { FileText, Plus } from 'lucide-vue-next'
6+
import { FileText } from 'lucide-vue-next'
77
88
const { isCompactListMode } = useApp()
99
const {
@@ -49,87 +49,73 @@ function finishRename(id: string) {
4949
function cancelRename() {
5050
editingId.value = null
5151
}
52+
53+
defineExpose({
54+
handleCreateSheet,
55+
})
5256
</script>
5357

5458
<template>
5559
<div class="flex h-full flex-col overflow-hidden">
56-
<div class="_mt-1 flex items-center justify-between px-2 pb-2 select-none">
57-
<UiText
58-
as="div"
59-
variant="caption"
60-
weight="bold"
61-
uppercase
62-
>
63-
{{ i18n.t("spaces.math.sheetList") }}
64-
</UiText>
65-
<UiActionButton
66-
:tooltip="i18n.t('spaces.math.newSheet')"
67-
@click="handleCreateSheet"
68-
>
69-
<Plus class="h-4 w-4" />
70-
</UiActionButton>
71-
</div>
72-
7360
<div class="scrollbar min-h-0 flex-1 overflow-y-auto px-2">
7461
<ContextMenu.ContextMenu
7562
v-for="sheet in sheets"
7663
:key="sheet.id"
7764
>
7865
<ContextMenu.ContextMenuTrigger as-child>
79-
<div
80-
class="group mb-0.5 flex cursor-default items-center gap-2 rounded-md px-2 py-1.5 transition-colors duration-75"
81-
:class="
82-
activeSheetId === sheet.id
83-
? 'bg-accent text-accent-foreground'
84-
: 'hover:bg-accent-hover'
85-
"
66+
<SidebarItem
67+
class="group mb-0.5 cursor-default transition-colors duration-75"
68+
:class="activeSheetId === sheet.id ? 'text-accent-foreground' : ''"
69+
:selected="activeSheetId === sheet.id"
8670
@click="selectSheet(sheet.id)"
8771
@dblclick="startRename(sheet.id, sheet.name)"
8872
>
89-
<FileText
90-
class="h-3.5 w-3.5 shrink-0 transition-colors"
91-
:class="
92-
activeSheetId === sheet.id
93-
? 'text-accent-foreground'
94-
: 'text-muted-foreground'
95-
"
96-
:stroke-width="1.5"
97-
/>
98-
<div class="min-w-0 flex-1">
99-
<input
100-
v-if="editingId === sheet.id"
101-
v-model="editingName"
102-
class="sheet-rename-input w-full bg-transparent text-[13px] outline-none"
103-
@blur="finishRename(sheet.id)"
104-
@keydown.enter="finishRename(sheet.id)"
105-
@keydown.escape="cancelRename"
106-
@click.stop
107-
>
108-
<template v-else>
109-
<div
110-
:class="isCompactListMode ? 'flex items-center gap-2' : ''"
73+
<div class="flex items-center gap-2 px-2 py-0.5">
74+
<FileText
75+
class="h-3.5 w-3.5 shrink-0 transition-colors"
76+
:class="
77+
activeSheetId === sheet.id
78+
? 'text-accent-foreground'
79+
: 'text-muted-foreground'
80+
"
81+
:stroke-width="1.5"
82+
/>
83+
<div class="min-w-0 flex-1">
84+
<input
85+
v-if="editingId === sheet.id"
86+
v-model="editingName"
87+
class="sheet-rename-input w-full bg-transparent text-[13px] outline-none"
88+
@blur="finishRename(sheet.id)"
89+
@keydown.enter="finishRename(sheet.id)"
90+
@keydown.escape="cancelRename"
91+
@click.stop
11192
>
112-
<UiText
113-
as="div"
114-
variant="sm"
115-
class="truncate leading-tight"
116-
:class="isCompactListMode ? 'flex-1' : ''"
117-
>
118-
{{ sheet.name }}
119-
</UiText>
120-
<UiText
121-
as="div"
122-
variant="caption"
123-
class="leading-tight transition-colors"
124-
:class="isCompactListMode ? 'shrink-0' : ''"
125-
muted
93+
<template v-else>
94+
<div
95+
:class="isCompactListMode ? 'flex items-center gap-2' : ''"
12696
>
127-
{{ format(new Date(sheet.updatedAt), "dd.MM.yyyy") }}
128-
</UiText>
129-
</div>
130-
</template>
97+
<UiText
98+
as="div"
99+
variant="sm"
100+
class="truncate leading-tight"
101+
:class="isCompactListMode ? 'flex-1' : ''"
102+
>
103+
{{ sheet.name }}
104+
</UiText>
105+
<UiText
106+
as="div"
107+
variant="caption"
108+
class="leading-tight transition-colors"
109+
:class="isCompactListMode ? 'shrink-0' : ''"
110+
muted
111+
>
112+
{{ format(new Date(sheet.updatedAt), "dd.MM.yyyy") }}
113+
</UiText>
114+
</div>
115+
</template>
116+
</div>
131117
</div>
132-
</div>
118+
</SidebarItem>
133119
</ContextMenu.ContextMenuTrigger>
134120

135121
<ContextMenu.ContextMenuContent>

src/renderer/components/notes/NotesSidebar.vue

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,15 @@ nextTick(() => {
2121
<template>
2222
<div
2323
data-notes-sidebar
24-
class="flex h-full flex-col px-1 pt-[var(--content-top-offset)]"
24+
class="flex h-full flex-col px-1"
25+
style="
26+
padding-top: calc(var(--content-top-offset) + var(--header-gap, 0px));
27+
"
2528
>
26-
<SidebarHeader :title="i18n.t('notes.plural')" />
29+
<SidebarHeader
30+
:title="i18n.t('notes.plural')"
31+
:section-title="i18n.t('common.library')"
32+
/>
2733
<NotesSidebarLibrary />
2834
<NotesSidebarFolders />
2935
</div>

src/renderer/components/notes/NotesSidebarFolders.vue

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -176,22 +176,16 @@ function onCancelEdit() {
176176
</script>
177177

178178
<template>
179-
<div class="mt-1 flex items-center justify-between py-1 pl-1 select-none">
180-
<UiText
181-
as="div"
182-
variant="caption"
183-
weight="bold"
184-
uppercase
185-
>
186-
{{ i18n.t("common.folders") }}
187-
</UiText>
188-
<UiActionButton
189-
:tooltip="i18n.t('action.new.folder')"
190-
@click="createNoteFolderAndSelect()"
191-
>
192-
<Plus class="h-4 w-4" />
193-
</UiActionButton>
194-
</div>
179+
<SidebarSectionHeader :title="i18n.t('common.folders')">
180+
<template #action>
181+
<UiActionButton
182+
:tooltip="i18n.t('action.new.folder')"
183+
@click="createNoteFolderAndSelect()"
184+
>
185+
<Plus class="h-4 w-4" />
186+
</UiActionButton>
187+
</template>
188+
</SidebarSectionHeader>
195189
<div class="flex min-h-0 flex-1 flex-col">
196190
<div class="min-h-0 flex-1">
197191
<div class="min-h-0 flex-1 overflow-y-auto">
@@ -255,16 +249,7 @@ function onCancelEdit() {
255249
class="shrink-0 overflow-hidden"
256250
>
257251
<div class="flex h-full min-h-0 flex-col">
258-
<div class="flex items-center justify-between py-1 pl-1 select-none">
259-
<UiText
260-
as="div"
261-
variant="caption"
262-
weight="bold"
263-
uppercase
264-
>
265-
{{ i18n.t("common.tags") }}
266-
</UiText>
267-
</div>
252+
<SidebarSectionHeader :title="i18n.t('common.tags')" />
268253
<div class="min-h-0 flex-1 px-1 pb-1">
269254
<NotesSidebarTags />
270255
</div>
Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,27 @@
11
<script setup lang="ts">
2-
import { i18n } from '@/electron'
3-
42
interface Props {
53
title: string
4+
sectionTitle?: string
65
}
76
87
defineProps<Props>()
98
</script>
109

1110
<template>
1211
<div class="px-1">
13-
<div class="truncate px-1 pb-2 leading-5 font-bold select-none">
12+
<div class="truncate px-1 leading-5 font-bold select-none">
1413
{{ title }}
1514
</div>
16-
<UiText
17-
as="div"
18-
variant="caption"
19-
weight="bold"
20-
uppercase
21-
class="flex gap-1 pb-1 pl-1 select-none"
15+
<SidebarSectionHeader
16+
v-if="sectionTitle"
17+
:title="sectionTitle"
2218
>
23-
{{ i18n.t("common.library") }}
24-
</UiText>
19+
<template
20+
v-if="$slots.action"
21+
#action
22+
>
23+
<slot name="action" />
24+
</template>
25+
</SidebarSectionHeader>
2526
</div>
2627
</template>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<script setup lang="ts">
2+
interface Props {
3+
selected?: boolean
4+
focused?: boolean
5+
hoverable?: boolean
6+
}
7+
8+
withDefaults(defineProps<Props>(), {
9+
selected: false,
10+
focused: false,
11+
hoverable: true,
12+
})
13+
</script>
14+
15+
<template>
16+
<div
17+
data-sidebar-item
18+
:data-selected="selected ? 'true' : undefined"
19+
:data-focused="focused ? 'true' : undefined"
20+
class="data-[selected=true]:bg-accent data-[focused=true]:bg-primary! data-[focused=true]:text-primary-foreground rounded-md"
21+
:class="{
22+
'hover:bg-accent-hover': hoverable && !selected && !focused,
23+
}"
24+
>
25+
<slot />
26+
</div>
27+
</template>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<script setup lang="ts">
2+
interface Props {
3+
title: string
4+
}
5+
6+
defineProps<Props>()
7+
</script>
8+
9+
<template>
10+
<div class="flex h-9 items-center justify-between py-1 pl-1 select-none">
11+
<UiText
12+
as="div"
13+
variant="caption"
14+
weight="bold"
15+
uppercase
16+
>
17+
{{ title }}
18+
</UiText>
19+
<slot name="action" />
20+
</div>
21+
</template>

0 commit comments

Comments
 (0)