Skip to content

Commit

Permalink
feat: smart separators
Browse files Browse the repository at this point in the history
  • Loading branch information
holtwick committed Apr 25, 2024
1 parent 3f5f847 commit 5add083
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 60 deletions.
3 changes: 1 addition & 2 deletions lib/basic/oui-resizeable.styl
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@

.oui-resizeable {
position: relative;
box-sizing: border-box;

.oui-resizeable-separator {
box-sizing: border-box;
position: static;

&._left {
left: var(--resizeable-border-size, 0);
Expand Down
71 changes: 22 additions & 49 deletions lib/basic/oui-resizeable.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
<script lang="ts" setup>
import { useLocalStorage } from '@vueuse/core'
import { computed, onMounted, ref } from 'vue'
import type { LoggerInterface } from 'zeed'
import { Logger } from 'zeed'
import { px } from './lib'
import { ref } from 'vue'
import OuiSeparator from './oui-separator.vue'
import './oui-resizeable.styl'
// import './oui-resizeable.styl'
const props = withDefaults(defineProps<{
name: string
Expand All @@ -17,53 +14,29 @@ const props = withDefaults(defineProps<{
}>(), {
})
// const modelSize = defineModel<number>({ required: false, default: props.size })
const log: LoggerInterface = Logger('oui-resizeable')
const paneSize = useLocalStorage(`oui.resizeable.${props.name}`, props.size)
function setSize(value: number) {
paneSize.value = Math.max(props.minSize, Math.min(props.maxSize, value))
}
setSize(paneSize.value)
const root = ref()
const borderSize = ref(0)
const style = computed(() => {
if (props.side === 'top' || props.side === 'bottom') {
return {
'height': px(paneSize.value),
'--resizeable-border-size': borderSize.value,
}
}
else {
return {
'width': px(paneSize.value),
'--resizeable-border-size': borderSize.value,
}
}
})
onMounted(() => {
const borderSize = Number.parseFloat(window.getComputedStyle(root.value).borderLeftWidth)
})
const style = ref()
</script>

<template>
<div ref="root" :style="style" class="oui-resizeable">
<OuiSeparator
v-model="paneSize"
:side="side"
:min-size="minSize"
:max-size="maxSize"
class="oui-resizeable-separator"
/>
name={{ name }} size={{ paneSize }}
<slot />
</div>
<template v-if="side === 'right' || side === 'bottom'">
<div :style="style" class="oui-resizeable" v-bind="$attrs">
<slot />
</div>
</template>
<OuiSeparator
v-model="paneSize"
v-model:style-value="style"
:side="side"
:min-size="minSize"
:max-size="maxSize"
style="position: relative;"
class="oui-resizeable-separator"
/>
<template v-if="side === 'left' || side === 'top'">
<div :style="style" class="oui-resizeable" v-bind="$attrs">
<slot />
</div>
</template>
</template>
24 changes: 21 additions & 3 deletions lib/basic/oui-separator.styl
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
@require "../../stylus/index.styl";

.oui-separator {
position: relative;
background: var(--separator, transparent);

&._absolute {
position: absolute;
}

&:hover {
background: var(--separator-hover, var(--fg));
}
Expand All @@ -12,7 +17,6 @@
}

&._left, &._right {
position: absolute;
width: 1px;
height: 100%;
cursor: unquote("col-resize");
Expand All @@ -30,11 +34,9 @@
}

&._top, &._bottom {
position: absolute;
height: 1px;
width: 100%;
cursor: unquote("row-resize");
sepHandleSize = px(5);

&:after {
position: absolute;
Expand All @@ -47,4 +49,20 @@
z-index: -z-index-floating;
}
}

&._left {
left: var(--separator-shift, 0);
}

&._right {
right: var(--separator-shift, 0);
}

&._top {
top: var(--separator-shift, 0);
}

&._bottom {
bottom: var(--separator-shift, 0);
}
}
17 changes: 17 additions & 0 deletions lib/basic/oui-separator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,38 @@
import { ref } from 'vue'
import type { OuiDraggableEvent } from './_types'
import OuiDraggable from './oui-draggable.vue'
import { px } from './lib'
import './oui-separator.styl'
const props = withDefaults(defineProps<{
side: 'top' | 'left' | 'right' | 'bottom'
minSize: number
maxSize: number
absolute?: boolean
}>(), {
absolute: false,
})
const _active = ref(false)
const modelSize = defineModel<number>({ required: true })
const modelStyle = defineModel<any>('styleValue', { required: false })
function updateStyle() {
modelStyle.value = {
[props.side === 'top' || props.side === 'bottom'
? 'height'
: 'width'
]: px(modelSize.value),
}
}
updateStyle()
function setSize(value: number) {
modelSize.value = Math.max(props.minSize, Math.min(props.maxSize, value))
updateStyle()
}
let startSize = 0
Expand Down Expand Up @@ -50,6 +66,7 @@ function doHandleMoveEnd(e: OuiDraggableEvent) {
:class="{
[`_${side}`]: true,
_active,
_absolute: absolute,
}"
@move-start="doHandleMoveStart"
@move-end="doHandleMoveEnd"
Expand Down
7 changes: 6 additions & 1 deletion lib/basic/oui-tableview.styl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@
overflow-x: auto; // this does not work together with sticky headers
border-collapse: collapse;
position: relative;
--separator-handle: transparent;

.oui-separator {
// --separator: red;
// --separator-handle: green;
position: absolute;
}

._tableview {
&_row {
Expand Down
6 changes: 5 additions & 1 deletion lib/basic/oui-tableview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,11 @@ function doSelect(pos: number) {
side="right"
:min-size="columns[i].minWidth ?? 80"
:max-size="columns[i].maxWidth ?? 300"
:style="`left: ${px(arraySum(widths.slice(0, i + 1)) - 2)}`"
data-test="hello"
:style="{
color: 'green',
left: px(arraySum(widths.slice(0, i + 1)) - 1),
}"
/>
</template>
</div>
Expand Down
16 changes: 13 additions & 3 deletions src/app-resizeable.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts" setup>
import { reactive } from 'vue'
import { OuiObject, OuiResizeable } from '@/lib'
import { OuiCheckbox, OuiObject, OuiResizeable } from '@/lib'
import './app-resizeable.styl'
Expand All @@ -12,6 +12,7 @@ const state = reactive({
selected: undefined,
fillLast: true,
scrollToEnd: false,
showSepHandle: false,
})
const minSize = 100
Expand All @@ -21,7 +22,15 @@ const size = 200

<template>
<h2>Resizeable</h2>
<div class="app-resizeable" style="--separator-handle: rgba(255,0,0,0.25)">
<p>
<OuiCheckbox v-model="state.showSepHandle" switch>
showSepHandle
</OuiCheckbox>
</p>
<div
class="app-resizeable"
:style="state.showSepHandle && '--separator-handle: rgba(255,0,0,0.25)'"
>
<OuiResizeable side="bottom" :min-size="minSize" :max-size="maxSize" :size="size" class="top" name="top">
Top
</OuiResizeable>
Expand All @@ -39,6 +48,7 @@ const size = 200
<OuiResizeable side="top" :min-size="minSize" :max-size="maxSize" :size="size" class="bottom" name="bottom">
Bottom
</OuiResizeable>

<OuiObject :value="state" />
</div>
<OuiObject :value="state" />
</template>
6 changes: 5 additions & 1 deletion src/app-tableview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const state = reactive({
selected: undefined,
fillLast: true,
scrollToEnd: false,
showSepHandle: false,
})
const columns: OuiTableColumn[] = [
Expand Down Expand Up @@ -62,8 +63,11 @@ const x = ref(0)
<OuiCheckbox v-model="state.scrollToEnd" switch>
scrollToEnd
</OuiCheckbox>
<OuiCheckbox v-model="state.showSepHandle" switch>
showSepHandle
</OuiCheckbox>
</p>
<div style="--separator-handle: rgba(255,0,0,0.25)">
<div :style="state.showSepHandle && '--separator-handle: rgba(255,0,0,0.25)'">
<OuiTableview
v-model="state.selected"
v-model:sort="state.sort"
Expand Down

0 comments on commit 5add083

Please sign in to comment.