Skip to content
This repository was archived by the owner on Sep 20, 2024. It is now read-only.

Commit fb153dc

Browse files
committed
feat: block scroll on mount
1 parent 8a9106c commit fb153dc

File tree

6 files changed

+42
-38
lines changed

6 files changed

+42
-38
lines changed

packages/c-focus-lock/src/c-focus-lock.ts

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,9 @@
1414
* and my suspicion is that it is happening inside the library
1515
*/
1616

17-
import {
18-
h,
19-
defineComponent,
20-
PropType,
21-
computed,
22-
cloneVNode,
23-
VNode,
24-
watch,
25-
} from 'vue'
26-
import { chakra } from '@chakra-ui/vue-system'
27-
import { focus, FocusableElement, __DEV__ } from '@chakra-ui/utils'
17+
import { defineComponent, PropType, computed, cloneVNode, VNode } from 'vue'
18+
import { focus, FocusableElement, warn, __DEV__ } from '@chakra-ui/utils'
2819
import { UseFocusLockOptions, useFocusLock } from './use-focus-lock'
29-
import { useRef } from '@chakra-ui/vue-utils'
3020
import { FocusTarget } from 'focus-trap'
3121

3222
type RefProp = () => HTMLElement | string | object | undefined
@@ -122,9 +112,12 @@ export const CFocusLock = defineComponent({
122112
const [firstChild] = slots.default?.({}) as VNode[]
123113

124114
if (!firstChild) {
125-
console.warn(
126-
`[chakra-ui:focus-lock]: Focus lock component expects at least and only one child element.`
127-
)
115+
warn([
116+
{
117+
condition: __DEV__,
118+
message: `[chakra-ui:focus-lock]: Focus lock component expects at least and only one child element.`,
119+
},
120+
])
128121
return
129122
}
130123

packages/c-focus-lock/tests/c-focus-lock.test.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,15 @@ afterEach(() => {
2424
const renderComponent = (props?: any) => {
2525
const base = {
2626
components: {
27-
CPortal,
27+
// CPortal,
2828
CFocusLock,
2929
},
3030
template: `
31-
<c-portal>
3231
<div :ref="lock" data-testid="focus-lock-container">
3332
<input data-testid="input" />
3433
<input />
3534
<input />
3635
</div>
37-
</c-portal>
3836
`,
3937
setup() {
4038
const { lock } = useFocusLock()

packages/c-modal/examples/simple-modal.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<c-button color-scheme="blue" @click="isOpen = true">Open modal</c-button>
1010
<c-button ref="finalFocus" ml="3">Other button</c-button>
1111
<!-- eslint-disable-next-line -->
12-
<c-modal v-model:is-open="isOpen" motion-preset="slideInRight" :initial-focus-ref="'#initialFocus'" :final-focus-ref="() => $refs.finalFocus">
12+
<c-modal v-model="isOpen" :initial-focus-ref="'#initialFocus'" :blockScrollOnMount="false" :final-focus-ref="() => $refs.finalFocus">
1313
<c-modal-overlay />
1414
<c-modal-content>
1515
<c-modal-header>Modal header</c-modal-header>

packages/c-modal/src/c-modal.ts

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export interface CModalProps extends UnwrapRef<UseModalOptions>, ModalOptions {
6767
*
6868
* @default true
6969
*/
70-
isOpen: boolean
70+
modelValue: boolean
7171
/**
7272
* If `false`, focus lock will be disabled completely.
7373
*
@@ -151,8 +151,8 @@ export { ModalContextProvider, useModalContext }
151151
export const CModal = defineComponent({
152152
name: 'CModal',
153153
props: {
154-
isOpen: {
155-
type: Boolean as PropType<CModalProps['isOpen']>,
154+
modelValue: {
155+
type: Boolean as PropType<CModalProps['modelValue']>,
156156
default: false,
157157
},
158158
id: String as PropType<CModalProps['id']>,
@@ -203,10 +203,10 @@ export const CModal = defineComponent({
203203
default: 'slideInBottom',
204204
},
205205
},
206-
emits: ['update:is-open', 'escape', 'close'],
206+
emits: ['update:modelValue', 'escape', 'close'],
207207
setup(props, { slots, attrs, emit }) {
208208
const closeModal = () => {
209-
emit('update:is-open', false)
209+
emit('update:modelValue', false)
210210
}
211211

212212
const handleEscape = (event: KeyboardEvent) => {
@@ -234,7 +234,7 @@ export const CModal = defineComponent({
234234
return () =>
235235
h(CPortal, () => [
236236
h(CMotion, { type: 'fade' }, () => [
237-
props.isOpen && h(chakra('span'), () => slots?.default?.()),
237+
props.modelValue && h(chakra('span'), () => slots?.default?.()),
238238
]),
239239
])
240240
},
@@ -249,9 +249,12 @@ export const CModalContent = defineComponent({
249249
inheritAttrs: false,
250250
emits: ['click', 'mousedown', 'keydown'],
251251
setup(_, { attrs, slots, emit }) {
252-
const { dialogContainerProps, dialogProps, isOpen, motionPreset } = unref(
253-
useModalContext()
254-
)
252+
const {
253+
dialogContainerProps,
254+
dialogProps,
255+
modelValue,
256+
motionPreset,
257+
} = unref(useModalContext())
255258
const styles = useStyles()
256259
const transitionId = 'modal-content'
257260

@@ -264,7 +267,7 @@ export const CModalContent = defineComponent({
264267
})
265268
}
266269

267-
watch(isOpen, (newVal) => {
270+
watch(modelValue, (newVal) => {
268271
if (!newVal) {
269272
leave(() => null)
270273
}
@@ -297,7 +300,7 @@ export const CModalContent = defineComponent({
297300
}),
298301
dialogContainerProps.value({ emit }),
299302
() => [
300-
isOpen.value &&
303+
modelValue.value &&
301304
withDirectives(
302305
h(
303306
chakra('section', {

packages/c-modal/src/use-modal.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import {
22
computed,
33
getCurrentInstance,
4-
nextTick,
54
onBeforeMount,
65
onBeforeUnmount,
76
ref,
@@ -23,7 +22,7 @@ export interface UseModalOptions {
2322
/**
2423
* If `true`, the modal will be open.
2524
*/
26-
isOpen: Ref<boolean>
25+
modelValue: Ref<boolean>
2726
/**
2827
* The `id` of the modal
2928
*/
@@ -33,6 +32,11 @@ export interface UseModalOptions {
3332
* @default true
3433
*/
3534
closeOnOverlayClick?: Ref<boolean>
35+
/**
36+
* If `true`, the body will not be scollable when mounted
37+
* @default true
38+
*/
39+
blockScrollOnMount?: Ref<boolean>
3640
/**
3741
* The initial element to be focused when the focus lock is opened
3842
*/
@@ -75,13 +79,14 @@ export interface UseModalOptions {
7579
export function useModal(options: UseModalOptions) {
7680
const { handleEscape, closeModal } = options
7781
const {
78-
isOpen,
82+
modelValue,
7983
id,
8084
closeOnOverlayClick,
8185
closeOnEsc,
8286
initialFocusRef,
8387
finalFocusRef,
8488
useInert,
89+
blockScrollOnMount,
8590
} = toRefs(options)
8691

8792
const instance = getCurrentInstance()
@@ -137,7 +142,7 @@ export function useModal(options: UseModalOptions) {
137142
`chakra-modal--body`
138143
)
139144

140-
const { lastFocusedSelector } = useReturnFocusSelector(isOpen)
145+
const { lastFocusedSelector } = useReturnFocusSelector(modelValue)
141146

142147
const hasHeader = ref(false)
143148
const hasBody = ref(false)
@@ -188,7 +193,9 @@ export function useModal(options: UseModalOptions) {
188193
immediate: true,
189194
})
190195

191-
const { scrollLockRef } = useBodyScrollLock(isOpen)
196+
const { scrollLockRef } = useBodyScrollLock(
197+
blockScrollOnMount?.value ? modelValue : ref(false)
198+
)
192199

193200
/**
194201
* This watcher is being used to track
@@ -254,7 +261,7 @@ export function useModal(options: UseModalOptions) {
254261
() => ({ emit }) => ({
255262
ref: overlayRef as any,
256263
onClick: (event: MouseEvent) => {
257-
instance?.emit('update:is-open', !isOpen.value)
264+
instance?.emit('update:modelValue', !modelValue.value)
258265
instance?.emit('close')
259266
handleOverlayClick(event)
260267
},
@@ -272,11 +279,13 @@ export function useModal(options: UseModalOptions) {
272279
* `aria-hidden` attributes handling
273280
* @see useAriaHidden
274281
*/
275-
const shouldHide = computed(() => (isOpen.value && useInert?.value) || false)
282+
const shouldHide = computed(
283+
() => (modelValue.value && useInert?.value) || false
284+
)
276285
useAriaHidden(dialogRefEl, shouldHide)
277286

278287
return {
279-
isOpen,
288+
modelValue,
280289
headerId,
281290
bodyId,
282291
dialogRef,

packages/theme/src/foundations/breakpoints.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const breakpoints = createBreakpoints({
88
md: '48em',
99
lg: '62em',
1010
xl: '80em',
11+
'2xl': '96em',
1112
})
1213

1314
export default breakpoints

0 commit comments

Comments
 (0)