Skip to content

Commit

Permalink
feat(ui/sticky): add disabled,css-mode props
Browse files Browse the repository at this point in the history
affects: @varlet/ui
  • Loading branch information
haoziqaq committed Sep 17, 2021
1 parent 646d326 commit 5dbfbca
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 19 deletions.
42 changes: 27 additions & 15 deletions packages/varlet-ui/src/sticky/Sticky.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,24 @@
<div
class="var-sticky"
ref="stickyEl"
:class="[cssMode ? 'var-sticky--css-mode' : null]"
:class="[enableCSSMode ? 'var-sticky--css-mode' : null]"
:style="{
zIndex: toNumber(zIndex),
top: !isFixed ? `${offsetTop}px` : null,
width: isFixed ? fixedWidth : null,
height: isFixed ? fixedHeight : null,
top: enableCSSMode ? `${offsetTop}px` : null,
width: enableFixedMode ? fixedWidth : null,
height: enableFixedMode ? fixedHeight : null,
}"
>
<div
class="var-sticky__wrapper"
ref="wrapperEl"
:style="{
zIndex: toNumber(zIndex),
position: isFixed ? 'fixed' : null,
width: isFixed ? fixedWrapperWidth : null,
height: isFixed ? fixedWrapperHeight : null,
left: isFixed ? fixedLeft : null,
top: isFixed ? fixedTop : null,
position: enableFixedMode ? 'fixed' : null,
width: enableFixedMode ? fixedWrapperWidth : null,
height: enableFixedMode ? fixedWrapperHeight : null,
left: enableFixedMode ? fixedLeft : null,
top: enableFixedMode ? fixedTop : null,
}"
>
<slot />
Expand All @@ -28,7 +28,7 @@
</template>

<script lang="ts">
import { defineComponent, ref, onMounted, onUnmounted, onActivated, onDeactivated, computed } from 'vue'
import { defineComponent, ref, onMounted, onUnmounted, onActivated, onDeactivated, computed, watch } from 'vue'
import { props } from './props'
import { getParentScroller, toPxNum } from '../utils/elements'
import { toNumber } from '../utils/shared'
Expand All @@ -41,8 +41,7 @@ export default defineComponent({
const stickyEl: Ref<HTMLElement | null> = ref(null)
const wrapperEl: Ref<HTMLElement | null> = ref(null)
let isSupportCSSSticky: boolean
const isSupportCSSSticky: Ref<boolean> = ref(false)
const isFixed: Ref<boolean> = ref(false)
const fixedTop: Ref<string> = ref('0px')
const fixedLeft: Ref<string> = ref('0px')
Expand All @@ -51,11 +50,21 @@ export default defineComponent({
const fixedWrapperWidth: Ref<string> = ref('auto')
const fixedWrapperHeight: Ref<string> = ref('auto')
const enableCSSMode: ComputedRef<boolean> = computed(
() => !props.disabled && props.cssMode && isSupportCSSSticky.value
)
const enableFixedMode: ComputedRef<boolean> = computed(() => !props.disabled && isFixed.value)
const offsetTop: ComputedRef<number> = computed(() => toPxNum(props.offsetTop))
let scroller: HTMLElement | Window = window
const handleScroll = () => {
const { onScroll, cssMode, disabled } = props
if (disabled) {
return
}
let scrollerTop = 0
if (scroller !== window) {
Expand All @@ -67,10 +76,9 @@ export default defineComponent({
const sticky = stickyEl.value as HTMLElement
const { top: stickyTop, left: stickyLeft } = sticky.getBoundingClientRect()
const currentOffsetTop = stickyTop - scrollerTop
const { onScroll, cssMode } = props
if (currentOffsetTop <= offsetTop.value) {
if (!isSupportCSSSticky || !cssMode) {
if (!isSupportCSSSticky.value || !cssMode) {
fixedWidth.value = `${sticky.offsetWidth}px`
fixedHeight.value = `${sticky.offsetHeight}px`
fixedTop.value = `${scrollerTop + offsetTop.value}px`
Expand Down Expand Up @@ -100,12 +108,14 @@ export default defineComponent({
window.removeEventListener('scroll', handleScroll)
}
watch(() => props.disabled, handleScroll)
onActivated(addScrollListener)
onDeactivated(removeScrollListener)
onMounted(() => {
isSupportCSSSticky = ['sticky', '-webkit-sticky'].includes(
isSupportCSSSticky.value = ['sticky', '-webkit-sticky'].includes(
window.getComputedStyle(stickyEl.value as HTMLElement).position
)
addScrollListener()
Expand All @@ -124,6 +134,8 @@ export default defineComponent({
fixedHeight,
fixedWrapperWidth,
fixedWrapperHeight,
enableCSSMode,
enableFixedMode,
toNumber,
}
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,41 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`test sticky disabled with css sticky position 1`] = `
"<div class=\\"var-sticky\\" style=\\"z-index: 10;\\">
<div class=\\"var-sticky__wrapper\\" style=\\"z-index: 10;\\">sticky content</div>
</div>"
`;
exports[`test sticky disabled with css sticky position 2`] = `
"<div class=\\"var-sticky\\" style=\\"z-index: 10;\\">
<div class=\\"var-sticky__wrapper\\" style=\\"z-index: 10;\\">sticky content</div>
</div>"
`;
exports[`test sticky disabled without css sticky position 1`] = `
"<div class=\\"var-sticky\\" style=\\"z-index: 10;\\">
<div class=\\"var-sticky__wrapper\\" style=\\"z-index: 10;\\">sticky content</div>
</div>"
`;
exports[`test sticky disabled without css sticky position 2`] = `
"<div class=\\"var-sticky\\" style=\\"z-index: 10;\\">
<div class=\\"var-sticky__wrapper\\" style=\\"z-index: 10;\\">sticky content</div>
</div>"
`;
exports[`test sticky example 1`] = `
"<div class=\\"example\\">
<div class=\\"app-type\\">基本使用</div>
<div class=\\"var-sticky\\" style=\\"z-index: 10; top: 50px;\\">
<div class=\\"var-sticky\\" style=\\"z-index: 10;\\">
<div class=\\"var-sticky__wrapper\\" style=\\"z-index: 10;\\"><button class=\\"var-button var--box var-button--normal var--inline-flex var-button--primary var-elevation--1\\">
<!--v-if-->
<div class=\\"var-button__content\\">基本使用</div>
</button></div>
</div>
<div class=\\"app-type\\">局部吸顶</div>
<div class=\\"scroller\\">
<div class=\\"var-sticky\\" style=\\"z-index: 10; top: 0px;\\">
<div class=\\"var-sticky\\" style=\\"z-index: 10;\\">
<div class=\\"var-sticky__wrapper\\" style=\\"z-index: 10;\\"><button class=\\"var-button var--box var-button--normal var--inline-flex var-button--success var-elevation--1\\">
<!--v-if-->
<div class=\\"var-button__content\\">局部吸顶</div>
Expand All @@ -35,7 +59,7 @@ exports[`test sticky scrolling with css sticky position 2`] = `
`;
exports[`test sticky scrolling without css sticky position 1`] = `
"<div class=\\"var-sticky\\" style=\\"z-index: 10; top: 100px;\\">
"<div class=\\"var-sticky\\" style=\\"z-index: 10;\\">
<div class=\\"var-sticky__wrapper\\" style=\\"z-index: 10;\\">sticky content</div>
</div>"
`;
Expand All @@ -47,7 +71,7 @@ exports[`test sticky scrolling without css sticky position 2`] = `
`;
exports[`test sticky z-index 1`] = `
"<div class=\\"var-sticky\\" style=\\"z-index: 100; top: 0px;\\">
"<div class=\\"var-sticky\\" style=\\"z-index: 100;\\">
<div class=\\"var-sticky__wrapper\\" style=\\"z-index: 100;\\"></div>
</div>"
`;
68 changes: 68 additions & 0 deletions packages/varlet-ui/src/sticky/__tests__/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,71 @@ test('test sticky scrolling without css sticky position', async () => {
mockGetBoundingClientRect.mockRestore()
wrapper.unmount()
})

test('test sticky disabled with css sticky position', async () => {
const mockGetComputedStyle = jest
.spyOn(window, 'getComputedStyle')
.mockReturnValue({ position: 'sticky' })

const wrapper = mount(VarSticky, {
props: {
offsetTop: 100,
cssMode: true,
disabled: true
},
slots: {
default: () => 'sticky content',
},
attachTo: document.body,
})

const mockGetBoundingClientRect = jest
.spyOn(wrapper.element, 'getBoundingClientRect')
.mockReturnValue({ top: 200 })
await trigger(window, 'scroll')
expect(wrapper.html()).toMatchSnapshot()

jest.spyOn(wrapper.element, 'getBoundingClientRect').mockReturnValue({
top: 100,
})
await trigger(window, 'scroll')
expect(wrapper.html()).toMatchSnapshot()

mockGetComputedStyle.mockRestore()
mockGetBoundingClientRect.mockRestore()
wrapper.unmount()
})

test('test sticky disabled without css sticky position', async () => {
const mockGetComputedStyle = jest
.spyOn(window, 'getComputedStyle')
.mockReturnValue({ position: 'relative' })

const wrapper = mount(VarSticky, {
props: {
offsetTop: 100,
disabled: true
},
slots: {
default: () => 'sticky content',
},
attachTo: document.body,
})

const mockGetBoundingClientRect = jest
.spyOn(wrapper.element, 'getBoundingClientRect')
.mockReturnValue({ top: 200 })

await trigger(window, 'scroll')
expect(wrapper.html()).toMatchSnapshot()

jest
.spyOn(wrapper.element, 'getBoundingClientRect')
.mockReturnValue({ top: 100 })
await trigger(window, 'scroll')
expect(wrapper.html()).toMatchSnapshot()

mockGetComputedStyle.mockRestore()
mockGetBoundingClientRect.mockRestore()
wrapper.unmount()
})
1 change: 1 addition & 0 deletions packages/varlet-ui/src/sticky/docs/en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ createApp().use(Sticky)
| `offset-top` | Sticky offset top | _string \| number_ | `0` |
| `z-index` | Sticky z-index | _string \| number_ | `0` |
| `css-mode` | Enable native `css sticky` mode | _boolean_ | `false` |
| `disabled` | Disable sticky, when set to `true`, the element will return to the document flow | _boolean_ | `false` |

### Events

Expand Down
1 change: 1 addition & 0 deletions packages/varlet-ui/src/sticky/docs/zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ createApp().use(Sticky)
| `offset-top` | 吸顶距离 | _string \| number_ | `0` |
| `z-index` | 吸顶时的层级 | _string \| number_ | `0` |
| `css-mode` | 开启原生`css sticky`模式 | _boolean_ | `false` |
| `disabled` | 禁用吸顶, 设置为`true`时, 元素会回到文档流中 | _boolean_ | `false` |

### 事件

Expand Down
4 changes: 4 additions & 0 deletions packages/varlet-ui/src/sticky/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ export const props = {
type: Boolean,
default: false,
},
disabled: {
type: Boolean,
default: false,
},
onScroll: {
type: Function as PropType<(offsetTop: number, isFixed: boolean) => void>,
},
Expand Down

0 comments on commit 5dbfbca

Please sign in to comment.