Skip to content

Commit

Permalink
feat: add scrollBody options
Browse files Browse the repository at this point in the history
  • Loading branch information
zernonia committed Oct 9, 2023
1 parent ef7d188 commit 7aeb2d0
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 11 deletions.
1 change: 1 addition & 0 deletions packages/radix-vue/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
"@vueuse/core": "^10.4.1",
"@vueuse/shared": "^10.4.1",
"aria-hidden": "^1.2.3",
"defu": "^6.1.2",
"dts-bundle": "^0.7.3",
"jsdom": "^22.1.0",
"typescript": "^5.1.3",
Expand Down
12 changes: 8 additions & 4 deletions packages/radix-vue/src/ConfigProvider/ConfigProvider.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
<script lang="ts">
import { createContext } from '@/shared'
import type { Direction } from '@/shared/types'
import type { Direction, ScrollBodyOption } from '@/shared/types'
import { type Ref, toRefs } from 'vue'
interface ConfigProviderContextValue {
dir: Ref<Direction>
dir?: Ref<Direction>
scrollBody?: Ref<boolean | ScrollBodyOption>
}
export const [injectConfigProviderContext, provideConfigProviderContext]
Expand All @@ -15,19 +16,22 @@ export interface ConfigProviderProps {
* The global reading direction of your application. This will be inherited by all primitives.
* @defaultValue 'ltr'
*/
dir: Direction
dir?: Direction
scrollBody?: boolean | ScrollBodyOption
}
</script>

<script setup lang="ts">
const props = withDefaults(defineProps<ConfigProviderProps>(), {
dir: 'ltr',
scrollBody: true,
})
const { dir } = toRefs(props)
const { dir, scrollBody } = toRefs(props)
provideConfigProviderContext({
dir,
scrollBody,
})
</script>

Expand Down
7 changes: 6 additions & 1 deletion packages/radix-vue/src/shared/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,9 @@ type DataOrientation = 'vertical' | 'horizontal'
type Direction = 'ltr' | 'rtl'
type Type = 'single' | 'multiple'

export type { DataOrientation, Direction, Type }
type ScrollBodyOption = {
padding?: boolean | number
margin?: boolean | number
}

export type { DataOrientation, Direction, Type, ScrollBodyOption }
30 changes: 25 additions & 5 deletions packages/radix-vue/src/shared/useBodyScrollLock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,16 @@ import {
} from '@vueuse/core'
import { isClient } from '@vueuse/shared'
import { computed, nextTick, onBeforeUnmount, ref } from 'vue'
import { defu } from 'defu'
import { injectConfigProviderContext } from '@/ConfigProvider/ConfigProvider.vue'

const useBodyLockStackCount = createGlobalState(() => ref(0))

export function useBodyScrollLock(initialState?: boolean | undefined) {
const context = injectConfigProviderContext({
scrollBody: ref(true),
})

const stack = useBodyLockStackCount()
const locked = useScrollLock(defaultDocument?.body, false)

Expand All @@ -22,11 +28,23 @@ export function useBodyScrollLock(initialState?: boolean | undefined) {

if (newLocked) {
const verticalScrollbarWidth
= window.innerWidth - document.documentElement.clientWidth
= window.innerWidth - document.documentElement.clientWidth

const defaultConfig = { padding: verticalScrollbarWidth, margin: 0 }

const config = context.scrollBody?.value
? typeof context.scrollBody.value === 'object'
? defu({
padding: context.scrollBody.value.padding === true ? verticalScrollbarWidth : context.scrollBody.value.padding,
margin: context.scrollBody.value.margin === true ? verticalScrollbarWidth : context.scrollBody.value.margin,
}, defaultConfig)
: defaultConfig
: ({ padding: 0, margin: 0 })

if (verticalScrollbarWidth > 0) {
document.body.style.paddingRight = `${verticalScrollbarWidth}px`
document.head.style.setProperty('--scrollbar-width', `${verticalScrollbarWidth}px`)
document.body.style.paddingRight = `${config.padding}px`
document.body.style.marginRight = `${config.margin}px`
document.body.style.setProperty('--scrollbar-width', `${verticalScrollbarWidth}px`)
}

// let dismissibleLayer set previous pointerEvent first
Expand All @@ -37,8 +55,9 @@ export function useBodyScrollLock(initialState?: boolean | undefined) {
}
else {
document.body.style.paddingRight = ''
document.body.style.marginRight = ''
document.body.style.pointerEvents = ''
document.head.style.removeProperty('--scrollbar-width')
document.body.style.removeProperty('--scrollbar-width')
locked.value = false
}
},
Expand All @@ -55,8 +74,9 @@ export function useBodyScrollLock(initialState?: boolean | undefined) {
stack.value--
if (stack.value === 0) {
document.body.style.paddingRight = ''
document.body.style.marginRight = ''
document.body.style.pointerEvents = ''
document.head.style.removeProperty('--scrollbar-width')
document.body.style.removeProperty('--scrollbar-width')
}
})

Expand Down
2 changes: 1 addition & 1 deletion packages/radix-vue/src/shared/useDirection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ export function useDirection(dir?: Ref<Direction | undefined>) {
const context = injectConfigProviderContext({
dir: ref('ltr'),
})
return computed(() => dir?.value || context.dir.value || 'ltr')
return computed(() => dir?.value || context.dir?.value || 'ltr')
}

0 comments on commit 7aeb2d0

Please sign in to comment.