Skip to content

Commit 5db6edf

Browse files
committed
ui(pages): make left sidebar sections resizable
1 parent e9fb494 commit 5db6edf

File tree

7 files changed

+159
-32
lines changed

7 files changed

+159
-32
lines changed

apps/client/src/boot/ui.client.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,11 @@ export default boot(({ store }) => {
2727
internals.localStorage.getItem('recentPagesExpanded') !== 'false';
2828
uiStore(store).selectedPagesExpanded =
2929
internals.localStorage.getItem('selectedPagesExpanded') === 'true';
30+
31+
uiStore(store).currentPathWeight =
32+
parseFloat(internals.localStorage.getItem('currentPathWeight')!) || 1;
33+
uiStore(store).recentPagesWeight =
34+
parseFloat(internals.localStorage.getItem('recentPagesWeight')!) || 1;
35+
uiStore(store).selectedPagesWeight =
36+
parseFloat(internals.localStorage.getItem('selectedPagesWeight')!) || 1;
3037
});

apps/client/src/layouts/PagesLayout/LeftSidebar/CurrentPath.vue

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,11 @@
3636
</q-toolbar>
3737

3838
<q-list
39-
style="
40-
height: 0;
41-
overflow-x: hidden;
42-
overflow-y: auto;
43-
transition: all 0.2s;
44-
"
45-
:style="{ flex: uiStore().currentPathExpanded ? '1' : '0' }"
39+
ref="listRef"
40+
style="height: 0; overflow-x: hidden; overflow-y: auto"
41+
:style="{
42+
flex: uiStore().currentPathExpanded ? uiStore().currentPathWeight : '0',
43+
}"
4644
>
4745
<PageItem
4846
v-for="pageId in internals.pages.react.pathPageIds"
@@ -54,8 +52,57 @@
5452
class="current-path"
5553
/>
5654
</q-list>
55+
56+
<div
57+
v-if="
58+
uiStore().currentPathExpanded &&
59+
(uiStore().recentPagesExpanded || uiStore().selectedPagesExpanded)
60+
"
61+
style="position: relative"
62+
>
63+
<div
64+
style="
65+
position: absolute;
66+
left: 0;
67+
top: -12px;
68+
right: 0;
69+
bottom: -12px;
70+
cursor: ns-resize;
71+
z-index: 2147483647;
72+
"
73+
@pointerdown="resizeSection"
74+
></div>
75+
</div>
76+
77+
<q-separator style="background-color: rgba(255, 255, 255, 0.15) !important" />
5778
</template>
5879

5980
<script setup lang="ts">
60-
import { negateProp } from '@stdlib/misc';
81+
import { listenPointerEvents, map, negateProp } from '@stdlib/misc';
82+
import type { ComponentPublicInstance } from 'vue';
83+
84+
const listRef = ref<ComponentPublicInstance>();
85+
86+
function resizeSection(downEvent: PointerEvent) {
87+
listenPointerEvents(downEvent, {
88+
move(moveEvent) {
89+
const clientRect = listRef.value!.$el.getBoundingClientRect();
90+
91+
const othersHeight = uiStore().height - clientRect.height - 32 * 3 - 2;
92+
93+
const othersWeight =
94+
(uiStore().recentPagesExpanded ? uiStore().recentPagesWeight : 0) +
95+
(uiStore().selectedPagesExpanded ? uiStore().selectedPagesWeight : 0);
96+
97+
const myNewHeight = moveEvent.clientY - clientRect.y;
98+
99+
const myNewWeight = map(myNewHeight, 0, othersHeight, 0, othersWeight);
100+
101+
uiStore().recentPagesWeight -= myNewWeight - uiStore().currentPathWeight;
102+
uiStore().currentPathWeight = myNewWeight;
103+
104+
uiStore().normalizeWeights();
105+
},
106+
});
107+
}
61108
</script>

apps/client/src/layouts/PagesLayout/LeftSidebar/LeftSidebar.vue

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,8 @@
2626

2727
<CurrentPath />
2828

29-
<q-separator
30-
style="background-color: rgba(255, 255, 255, 0.15) !important"
31-
/>
32-
3329
<RecentPages />
3430

35-
<q-separator
36-
style="background-color: rgba(255, 255, 255, 0.15) !important"
37-
/>
38-
3931
<SelectedPages />
4032
</q-drawer>
4133
</template>

apps/client/src/layouts/PagesLayout/LeftSidebar/RecentPages.vue

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,11 @@
3636
</q-toolbar>
3737

3838
<q-list
39-
style="
40-
height: 0;
41-
overflow-x: hidden;
42-
overflow-y: auto;
43-
transition: all 0.2s;
44-
"
45-
:style="{ flex: uiStore().recentPagesExpanded ? '1' : '0' }"
39+
ref="listRef"
40+
style="height: 0; overflow-x: hidden; overflow-y: auto"
41+
:style="{
42+
flex: uiStore().recentPagesExpanded ? uiStore().recentPagesWeight : '0',
43+
}"
4644
>
4745
<div
4846
v-for="pageId in internals.pages.react.recentPageIds"
@@ -68,12 +66,59 @@
6866
/>
6967
</div>
7068
</q-list>
69+
70+
<div
71+
style="position: relative"
72+
v-if="uiStore().recentPagesExpanded && uiStore().selectedPagesExpanded"
73+
>
74+
<div
75+
style="
76+
position: absolute;
77+
left: 0;
78+
top: -12px;
79+
right: 0;
80+
bottom: -12px;
81+
cursor: ns-resize;
82+
z-index: 2147483647;
83+
"
84+
@pointerdown="resizeSection"
85+
></div>
86+
</div>
87+
88+
<q-separator style="background-color: rgba(255, 255, 255, 0.15) !important" />
7189
</template>
7290

7391
<script setup lang="ts">
74-
import { negateProp } from '@stdlib/misc';
92+
import { listenPointerEvents, map, negateProp } from '@stdlib/misc';
7593
import { pull } from 'lodash';
7694
import { handleError } from 'src/code/utils/misc';
95+
import type { ComponentPublicInstance } from 'vue';
96+
97+
const listRef = ref<ComponentPublicInstance>();
98+
99+
function resizeSection(downEvent: PointerEvent) {
100+
listenPointerEvents(downEvent, {
101+
move(moveEvent) {
102+
const clientRect = listRef.value!.$el.getBoundingClientRect();
103+
104+
const othersHeight = uiStore().height - clientRect.height - 32 * 3 - 2;
105+
106+
const othersWeight =
107+
(uiStore().currentPathExpanded ? uiStore().currentPathWeight : 0) +
108+
(uiStore().selectedPagesExpanded ? uiStore().selectedPagesWeight : 0);
109+
110+
const myNewHeight = moveEvent.clientY - clientRect.y;
111+
112+
const myNewWeight = map(myNewHeight, 0, othersHeight, 0, othersWeight);
113+
114+
uiStore().selectedPagesWeight -=
115+
myNewWeight - uiStore().recentPagesWeight;
116+
uiStore().recentPagesWeight = myNewWeight;
117+
118+
uiStore().normalizeWeights();
119+
},
120+
});
121+
}
77122
78123
async function removeRecentPage(pageId: string) {
79124
try {

apps/client/src/layouts/PagesLayout/LeftSidebar/SelectedPages.vue

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,12 @@
9393
</q-toolbar>
9494

9595
<q-list
96-
style="
97-
height: 0;
98-
overflow-x: hidden;
99-
overflow-y: auto;
100-
transition: all 0.2s;
101-
"
102-
:style="{ flex: uiStore().selectedPagesExpanded ? '1' : '0' }"
96+
style="height: 0; overflow-x: hidden; overflow-y: auto"
97+
:style="{
98+
flex: uiStore().selectedPagesExpanded
99+
? uiStore().selectedPagesWeight
100+
: '0',
101+
}"
103102
>
104103
<q-item v-if="pageSelectionStore().selectedPages.size === 0">
105104
<q-item-section>

apps/client/src/stores/ui.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { negateProp } from '@stdlib/misc';
1+
import { minmax, negateProp } from '@stdlib/misc';
22
import { defineStore } from 'pinia';
33

44
function trackProp<State>(state: State, prop: Extract<keyof State, string>) {
@@ -23,6 +23,10 @@ export const useUIStore = defineStore('ui', () => {
2323
recentPagesExpanded: true,
2424
selectedPagesExpanded: false,
2525

26+
currentPathWeight: 1,
27+
recentPagesWeight: 1,
28+
selectedPagesWeight: 1,
29+
2630
headerHeight: 0,
2731

2832
width: 0,
@@ -38,6 +42,10 @@ export const useUIStore = defineStore('ui', () => {
3842
trackProp(state, 'recentPagesExpanded');
3943
trackProp(state, 'selectedPagesExpanded');
4044

45+
trackProp(state, 'currentPathWeight');
46+
trackProp(state, 'recentPagesWeight');
47+
trackProp(state, 'selectedPagesWeight');
48+
4149
return {
4250
...toRefs(state),
4351

@@ -59,6 +67,25 @@ export const useUIStore = defineStore('ui', () => {
5967
resetLeftSidebarWidth() {
6068
state.leftSidebarWidth = 240;
6169
},
70+
71+
normalizeWeights() {
72+
const min = minmax(
73+
Math.min(
74+
state.currentPathWeight,
75+
state.recentPagesWeight,
76+
state.selectedPagesWeight,
77+
),
78+
1e-10,
79+
1e10,
80+
);
81+
82+
state.currentPathWeight =
83+
minmax(state.currentPathWeight / min, 1e-10, 1e10) || 1;
84+
state.recentPagesWeight =
85+
minmax(state.recentPagesWeight / min, 1e-10, 1e10) || 1;
86+
state.selectedPagesWeight =
87+
minmax(state.selectedPagesWeight / min, 1e-10, 1e10) || 1;
88+
},
6289
};
6390
});
6491

packages/@stdlib/misc/src/math.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@ export function lerp(a: number, b: number, t: number) {
22
return a + (b - a) * t;
33
}
44

5+
export function map(
6+
value: number,
7+
inMin: number,
8+
inMax: number,
9+
outMin: number,
10+
outMax: number,
11+
) {
12+
return lerp(outMin, outMax, (value - inMin) / (inMax - inMin));
13+
}
14+
515
export function minmax(value: number, min: number, max: number) {
616
return Math.min(Math.max(value, min), max);
717
}

0 commit comments

Comments
 (0)