Skip to content

Commit e88dae5

Browse files
authored
Merge pull request #1 from FreecellRaid/shiqi
feat: resizable sidebar and auto-sizing identity panel columns
2 parents ee56667 + eb80615 commit e88dae5

4 files changed

Lines changed: 321 additions & 35 deletions

File tree

src/assets/styles/style.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ body,
206206
.panel-block-list {
207207
flex: 1;
208208
min-height: 0;
209-
overflow-y: auto;
209+
overflow: auto;
210210
}
211211

212212
.expand-icon {

src/components/layout/SidebarLeft.vue

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,11 @@
165165
</div>
166166
</nav>
167167

168-
<aside v-if="uiStore.leftVisible" class="side-panel">
168+
<aside
169+
v-if="uiStore.leftVisible"
170+
class="side-panel"
171+
:style="{ width: uiStore.leftPanelWidth + 'px' }"
172+
>
169173
<div class="panel-content">
170174
<div
171175
v-if="uiStore.activeLeftPanel === 'chunks'"
@@ -199,6 +203,12 @@
199203
</div>
200204
</div>
201205
</aside>
206+
207+
<div
208+
v-if="uiStore.leftVisible"
209+
class="resize-handle"
210+
@mousedown="startResize"
211+
/>
202212
</div>
203213
</template>
204214

@@ -215,7 +225,7 @@ import {
215225
} from '@lucide/vue';
216226
import { ref, onMounted, onUnmounted, watch } from 'vue';
217227
import { useStyleStore } from '@/stores/styleStore';
218-
import { useUiStore } from '@/stores/uiStore';
228+
import { useUiStore, PANEL_MIN_WIDTH, PANEL_MAX_WIDTH } from '@/stores/uiStore';
219229
import ChunkListPanel from '@/components/panels/ChunkListPanel.vue';
220230
import IdentityPanel from '@/components/panels/IdentityPanel.vue';
221231
import RuleEditorPanel from '@/components/panels/RuleEditorPanel.vue';
@@ -228,6 +238,34 @@ const showSettings = ref(false);
228238
const closeSettings = () => {
229239
showSettings.value = false;
230240
};
241+
242+
function startResize(e: MouseEvent) {
243+
e.preventDefault();
244+
const startX = e.clientX;
245+
const startWidth = uiStore.leftPanelWidth;
246+
247+
function onMouseMove(ev: MouseEvent) {
248+
const delta = ev.clientX - startX;
249+
const newWidth = Math.min(
250+
PANEL_MAX_WIDTH,
251+
Math.max(PANEL_MIN_WIDTH, startWidth + delta),
252+
);
253+
uiStore.leftPanelWidth = newWidth;
254+
}
255+
256+
function onMouseUp() {
257+
document.removeEventListener('mousemove', onMouseMove);
258+
document.removeEventListener('mouseup', onMouseUp);
259+
document.body.style.cursor = '';
260+
document.body.style.userSelect = '';
261+
}
262+
263+
document.body.style.cursor = 'col-resize';
264+
document.body.style.userSelect = 'none';
265+
document.addEventListener('mousemove', onMouseMove);
266+
document.addEventListener('mouseup', onMouseUp);
267+
}
268+
231269
onMounted(() => {
232270
window.addEventListener('click', closeSettings);
233271
});
@@ -255,9 +293,8 @@ watch(
255293
.sidebar-left-container {
256294
display: flex;
257295
height: 100%;
258-
width: 280px;
259-
transition: width 0.2s ease;
260296
background-color: var(--bg-sidebar);
297+
position: relative;
261298
}
262299
263300
.sidebar-left-container.is-collapsed {
@@ -317,12 +354,27 @@ watch(
317354
318355
/* 内容面板样式 */
319356
.side-panel {
320-
width: 232px;
321357
background-color: var(--bg-sidebar);
322358
display: flex;
323359
flex-direction: column;
324360
min-width: 0;
325361
min-height: 0;
362+
flex-shrink: 0;
363+
}
364+
365+
.resize-handle {
366+
position: absolute;
367+
top: 0;
368+
right: -2px;
369+
width: 4px;
370+
height: 100%;
371+
cursor: col-resize;
372+
z-index: 10;
373+
}
374+
375+
.resize-handle:hover,
376+
.resize-handle:active {
377+
background-color: var(--active-accent);
326378
}
327379
328380
.panel-content {

0 commit comments

Comments
 (0)