Skip to content

Commit 52ce48d

Browse files
committed
handle stacked top position
1 parent aad0cde commit 52ce48d

File tree

5 files changed

+26
-25
lines changed

5 files changed

+26
-25
lines changed
Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
11
<script setup lang="ts">
2-
import { useElementBounding, useWindowSize } from "@vueuse/core";
3-
import { computed, reactive, ref, watch } from "vue";
2+
import { useElementBounding, useEventListener, useWindowSize } from "@vueuse/core";
3+
import { computed, reactive, ref, watch, watchEffect } from "vue";
44
5-
defineProps<{
6-
stuck?: boolean,
7-
}>();
5+
defineProps<{}>();
86
9-
const emit = defineEmits(['update:stuck']);
107
const el = ref<HTMLElement>();
11-
// const content = computed<HTMLElement>(() => el.value?.querySelector('[data-sticky-content]'));
128
const containerRect = reactive(useElementBounding(() => el.value?.parentElement, { updateTiming: 'next-frame' }));
139
const selfRect = reactive(useElementBounding(el, { updateTiming: 'next-frame' }));
14-
// const contentRect = reactive(useElementBounding(content, { updateTiming: 'next-frame' }));
1510
const topbarSafeRect = reactive(useElementBounding(() => document.querySelector('[data-topbar-sticky-safe-area]') as HTMLElement, { updateTiming: 'next-frame' }));
1611
const stuck = computed(() => {
1712
const style = el.value ? window.getComputedStyle(el.value) : null;
@@ -21,34 +16,40 @@
2116
&& bottom >= 0
2217
&& top <= parseFloat(style.top);
2318
});
24-
const isOverflowing = ref(false);
2519
const isOverflowingViewport = ref(false);
2620
const { height: innerHeight } = useWindowSize();
2721
watch([containerRect, innerHeight], () => {
2822
const style = window.getComputedStyle(el.value);
2923
isOverflowingViewport.value = (parseFloat(style.top) + containerRect.height) > innerHeight.value;
3024
});
31-
watch(stuck, () => {
32-
emit('update:stuck', stuck.value);
25+
26+
// Stacked top
27+
const stackedTop = ref(0);
28+
const parentStickyTopEl = computed(() => el.value?.closest('[data-sticky-top-container]')?.querySelector('[data-sticky-top]') as HTMLElement);
29+
const parentStickyTopRect = reactive(useElementBounding(() => parentStickyTopEl.value, { updateTiming: 'next-frame' }));
30+
function updateStackedTop() {
31+
const parentStickyStyle = parentStickyTopEl.value ? window.getComputedStyle(parentStickyTopEl.value) : null;
32+
stackedTop.value = parentStickyTopEl.value && parentStickyStyle.position === 'sticky'
33+
? parentStickyTopRect.height + parseFloat(parentStickyStyle.top || '0')
34+
: topbarSafeRect.height;
35+
}
36+
watchEffect(() => {
37+
updateStackedTop();
38+
});
39+
useEventListener(window, 'resize', () => {
40+
updateStackedTop();
3341
});
34-
// watch([stuck, contentRect], () => {
35-
// if(content.value) {
36-
// const topBarSafeArea = (document.querySelector('[data-topbar-sticky-safe-area]') as HTMLElement);
37-
// topBarSafeArea.style.minWidth = stuck.value ? `${contentRect.width}px` : 'auto';
38-
// }
39-
// });
4042
</script>
4143

4244
<template>
4345
<div :style="{
44-
'--top-bar-height': `${topbarSafeRect.height}px`,
45-
// '--sticky-safe-left-offset': stuck ? `${Math.max(topbarSafeRect.left - selfRect.left, 0)}px` : '0px',
46-
// '--sticky-safe-right-offset': stuck ? `${Math.max(selfRect.right - topbarSafeRect.right - parseInt(window.getComputedStyle(el).paddingRight), 0)}px` : '0px',
46+
'--stacked-top': `${stackedTop}px`
4747
}"
4848
:data-stuck="stuck ? true : null"
4949
:data-overflowing-viewport="isOverflowingViewport ? true : null"
50+
data-sticky-top
5051
ref="el"
5152
>
52-
<slot v-bind="{ stuck, largerThanTopbar: selfRect.height > topbarSafeRect.height, isOverflowing }" />
53+
<slot v-bind="{ stuck, largerThanTopbar: selfRect.height > topbarSafeRect.height }" />
5354
</div>
5455
</template>

resources/js/components/ui/RootCard.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<div class="@container">
99
<div :class="[noPadding ? 'px-0' : '']">
1010
<div class="@container/root-card mx-auto px-0 max-w-[87rem]">
11-
<Card class="relative rounded-none border-x-0 *:px-4 @3xl:*:px-6 @[87rem]:border-x @[87rem]:rounded-lg">
11+
<Card class="relative rounded-none border-x-0 *:px-4 @3xl:*:px-6 @[87rem]:border-x @[87rem]:rounded-lg" data-sticky-top-container>
1212
<slot />
1313
</Card>
1414
</div>

resources/js/form/components/Form.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@
131131
<component :is="inline ? 'div' : RootCard">
132132
<component :is="inline ? 'div' : RootCardHeader"
133133
:class="[
134-
form.locales?.length ? 'data-[overflowing-viewport]:sticky' : '',
134+
form.locales?.length || form.layout.tabs.length > 1 ? 'data-[overflowing-viewport]:sticky' : '',
135135
]"
136136
>
137137
<div class="flex flex-wrap justify-end items-start gap-x-4 gap-y-4">

resources/js/form/components/FormFieldLayout.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
:is="stickyLabel ? StickyTop : 'div'"
6464
class="group"
6565
:class="[{
66-
'top-[calc(var(--top-bar-height)+.625rem)] [[role=dialog]_&]:top-2.5 z-[5] lg:sticky': stickyLabel,
66+
'top-[calc(var(--stacked-top)+.625rem)] [[role=dialog]_&]:top-2.5 z-[5] lg:sticky': stickyLabel,
6767
'hidden @md/field-container:block @3xl/root-card:@md/field-container:block': !hasLabelRow,
6868
}]"
6969
v-slot="{ stuck = false } = {}"

resources/js/form/components/fields/editor/Editor.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@
161161
}"
162162
>
163163
<template v-if="editor && field.toolbar">
164-
<StickyTop class="sticky top-[--top-bar-height] [[role=dialog]_&]:top-0 p-1.5 border-b data-[stuck]:z-10 data-[stuck]:bg-background">
164+
<StickyTop class="sticky top-[--stacked-top] [[role=dialog]_&]:top-0 p-1.5 border-b data-[stuck]:z-10 data-[stuck]:bg-background">
165165
<div class="flex gap-x-1 gap-y-0 flex-wrap" ref="header">
166166
<template v-for="button in props.field.toolbar">
167167
<template v-if="button === 'link'">

0 commit comments

Comments
 (0)