Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve internal demo mode #3143

Merged
merged 5 commits into from Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
34 changes: 22 additions & 12 deletions packages/@headlessui-react/src/components/combobox/combobox.tsx
Expand Up @@ -110,6 +110,8 @@ interface StateDefinition<T> {
options: { id: string; dataRef: ComboboxOptionDataRef<T> }[]
activeOptionIndex: number | null
activationTrigger: ActivationTrigger

__demoMode: boolean
}

enum ActionTypes {
Expand Down Expand Up @@ -190,7 +192,12 @@ let reducers: {
if (state.dataRef.current?.disabled) return state
if (state.comboboxState === ComboboxState.Closed) return state

return { ...state, activeOptionIndex: null, comboboxState: ComboboxState.Closed }
return {
...state,
activeOptionIndex: null,
comboboxState: ComboboxState.Closed,
__demoMode: false,
}
},
[ActionTypes.OpenCombobox](state) {
if (state.dataRef.current?.disabled) return state
Expand All @@ -204,11 +211,12 @@ let reducers: {
...state,
activeOptionIndex: idx,
comboboxState: ComboboxState.Open,
__demoMode: false,
}
}
}

return { ...state, comboboxState: ComboboxState.Open }
return { ...state, comboboxState: ComboboxState.Open, __demoMode: false }
},
[ActionTypes.GoToOption](state, action) {
if (state.dataRef.current?.disabled) return state
Expand Down Expand Up @@ -249,6 +257,7 @@ let reducers: {
...state,
activeOptionIndex,
activationTrigger,
__demoMode: false,
}
}

Expand Down Expand Up @@ -290,6 +299,7 @@ let reducers: {
...adjustedState,
activeOptionIndex,
activationTrigger,
__demoMode: false,
}
},
[ActionTypes.RegisterOption]: (state, action) => {
Expand Down Expand Up @@ -635,6 +645,7 @@ function ComboboxFn<TValue, TTag extends ElementType = typeof DEFAULT_COMBOBOX_T
: null,
activeOptionIndex: null,
activationTrigger: ActivationTrigger.Other,
__demoMode,
} as StateDefinition<TValue>)

let defaultToFirstOption = useRef(false)
Expand Down Expand Up @@ -1583,7 +1594,10 @@ function OptionsFn<TTag extends ElementType = typeof DEFAULT_OPTIONS_TAG>(
useOnDisappear(data.inputRef, actions.closeCombobox, visible)

// Enable scroll locking when the combobox is visible, and `modal` is enabled
useScrollLock(ownerDocument, modal && data.comboboxState === ComboboxState.Open)
useScrollLock(
ownerDocument,
data.__demoMode ? false : modal && data.comboboxState === ComboboxState.Open
)

// Mark other elements as inert when the combobox is visible, and `modal` is enabled
useInertOthers(
Expand All @@ -1594,7 +1608,7 @@ function OptionsFn<TTag extends ElementType = typeof DEFAULT_OPTIONS_TAG>(
data.optionsRef.current,
]),
},
modal && data.comboboxState === ComboboxState.Open
data.__demoMode ? false : modal && data.comboboxState === ComboboxState.Open
)

useIsoMorphicEffect(() => {
Expand Down Expand Up @@ -1753,25 +1767,21 @@ function OptionFn<

let enableScrollIntoView = useRef(data.virtual || data.__demoMode ? false : true)
useIsoMorphicEffect(() => {
if (!data.virtual) return
if (!data.__demoMode) return
Comment on lines -1756 to -1757
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These conditions were incorrect. We don't want to scroll into view when virtual mode is used or when demo mode is used.

let d = disposables()
d.requestAnimationFrame(() => {
if (data.virtual) return
if (data.__demoMode) return
return disposables().requestAnimationFrame(() => {
enableScrollIntoView.current = true
})
return d.dispose
}, [data.virtual, data.__demoMode])

useIsoMorphicEffect(() => {
if (!enableScrollIntoView.current) return
if (data.comboboxState !== ComboboxState.Open) return
if (!active) return
if (data.activationTrigger === ActivationTrigger.Pointer) return
let d = disposables()
d.requestAnimationFrame(() => {
return disposables().requestAnimationFrame(() => {
internalOptionRef.current?.scrollIntoView?.({ block: 'nearest' })
})
return d.dispose
}, [
internalOptionRef,
active,
Expand Down
10 changes: 7 additions & 3 deletions packages/@headlessui-react/src/components/dialog/dialog.tsx
Expand Up @@ -224,7 +224,7 @@ function DialogFn<TTag extends ElementType = typeof DEFAULT_DIALOG_TAG>(
let setTitleId = useEvent((id: string | null) => dispatch({ type: ActionTypes.SetTitleId, id }))

let ready = useServerHandoffComplete()
let enabled = ready ? (__demoMode ? false : dialogState === DialogStates.Open) : false
let enabled = ready ? dialogState === DialogStates.Open : false
let hasNestedDialogs = nestedDialogCount > 1 // 1 is the current dialog
let hasParentDialog = useContext(DialogContext) !== null
let [portals, PortalWrapper] = useNestedPortals()
Expand Down Expand Up @@ -281,7 +281,7 @@ function DialogFn<TTag extends ElementType = typeof DEFAULT_DIALOG_TAG>(
null,
]),
},
inertEnabled
__demoMode ? false : inertEnabled
)

// Close Dialog on outside click
Expand Down Expand Up @@ -321,7 +321,7 @@ function DialogFn<TTag extends ElementType = typeof DEFAULT_DIALOG_TAG>(
if (hasParentDialog) return false
return true
})()
useScrollLock(ownerDocument, scrollLockEnabled, resolveRootContainers)
useScrollLock(ownerDocument, __demoMode ? false : scrollLockEnabled, resolveRootContainers)

// Ensure we close the dialog as soon as the dialog itself becomes hidden
useOnDisappear(internalDialogRef, close, dialogState === DialogStates.Open)
Expand Down Expand Up @@ -367,6 +367,10 @@ function DialogFn<TTag extends ElementType = typeof DEFAULT_DIALOG_TAG>(
focusTrapFeatures &= ~FocusTrapFeatures.InitialFocus
}

if (__demoMode) {
focusTrapFeatures = FocusTrapFeatures.None
}

return (
<StackProvider
type="Dialog"
Expand Down
27 changes: 22 additions & 5 deletions packages/@headlessui-react/src/components/listbox/listbox.tsx
Expand Up @@ -106,6 +106,8 @@ interface StateDefinition<T> {
searchQuery: string
activeOptionIndex: number | null
activationTrigger: ActivationTrigger

__demoMode: boolean
}

enum ActionTypes {
Expand Down Expand Up @@ -172,7 +174,12 @@ let reducers: {
[ActionTypes.CloseListbox](state) {
if (state.dataRef.current.disabled) return state
if (state.listboxState === ListboxStates.Closed) return state
return { ...state, activeOptionIndex: null, listboxState: ListboxStates.Closed }
return {
...state,
activeOptionIndex: null,
listboxState: ListboxStates.Closed,
__demoMode: false,
}
},
[ActionTypes.OpenListbox](state) {
if (state.dataRef.current.disabled) return state
Expand All @@ -187,7 +194,7 @@ let reducers: {
activeOptionIndex = optionIdx
}

return { ...state, listboxState: ListboxStates.Open, activeOptionIndex }
return { ...state, listboxState: ListboxStates.Open, activeOptionIndex, __demoMode: false }
},
[ActionTypes.GoToOption](state, action) {
if (state.dataRef.current.disabled) return state
Expand All @@ -197,6 +204,7 @@ let reducers: {
...state,
searchQuery: '',
activationTrigger: action.trigger ?? ActivationTrigger.Other,
__demoMode: false,
}

// Optimization:
Expand Down Expand Up @@ -460,6 +468,8 @@ export type ListboxProps<
form?: string
name?: string
multiple?: boolean

__demoMode?: boolean
}
>

Expand All @@ -480,6 +490,7 @@ function ListboxFn<
disabled = providedDisabled || false,
horizontal = false,
multiple = false,
__demoMode = false,
...theirProps
} = props
const orientation = horizontal ? 'horizontal' : 'vertical'
Expand All @@ -493,12 +504,13 @@ function ListboxFn<

let [state, dispatch] = useReducer(stateReducer, {
dataRef: createRef(),
listboxState: ListboxStates.Closed,
listboxState: __demoMode ? ListboxStates.Open : ListboxStates.Closed,
options: [],
searchQuery: '',
activeOptionIndex: null,
activationTrigger: ActivationTrigger.Other,
optionsVisible: false,
__demoMode,
} as StateDefinition<TType>)

let optionsPropsRef = useRef<_Data['optionsPropsRef']['current']>({ static: false, hold: false })
Expand Down Expand Up @@ -914,12 +926,15 @@ function OptionsFn<TTag extends ElementType = typeof DEFAULT_OPTIONS_TAG>(
useOnDisappear(data.buttonRef, actions.closeListbox, visible)

// Enable scroll locking when the listbox is visible, and `modal` is enabled
useScrollLock(ownerDocument, modal && data.listboxState === ListboxStates.Open)
useScrollLock(
ownerDocument,
data.__demoMode ? false : modal && data.listboxState === ListboxStates.Open
)

// Mark other elements as inert when the listbox is visible, and `modal` is enabled
useInertOthers(
{ allowed: useEvent(() => [data.buttonRef.current, data.optionsRef.current]) },
modal && data.listboxState === ListboxStates.Open
data.__demoMode ? false : modal && data.listboxState === ListboxStates.Open
)

let initialOption = useRef<number | null>(null)
Expand Down Expand Up @@ -1181,6 +1196,7 @@ function OptionFn<
})

useIsoMorphicEffect(() => {
if (data.__demoMode) return
if (data.listboxState !== ListboxStates.Open) return
if (!active) return
if (data.activationTrigger === ActivationTrigger.Pointer) return
Expand All @@ -1192,6 +1208,7 @@ function OptionFn<
}, [
internalOptionRef,
active,
data.__demoMode,
data.listboxState,
data.activationTrigger,
/* We also want to trigger this when the position of the active item changes so that we can re-trigger the scrollIntoView */ data.activeOptionIndex,
Expand Down
8 changes: 6 additions & 2 deletions packages/@headlessui-react/src/components/menu/menu.tsx
Expand Up @@ -177,6 +177,7 @@ let reducers: {
...state,
searchQuery: '',
activationTrigger: action.trigger ?? ActivationTrigger.Other,
__demoMode: false,
}

// Optimization:
Expand Down Expand Up @@ -626,12 +627,15 @@ function ItemsFn<TTag extends ElementType = typeof DEFAULT_ITEMS_TAG>(
useOnDisappear(state.buttonRef, () => dispatch({ type: ActionTypes.CloseMenu }), visible)

// Enable scroll locking when the menu is visible, and `modal` is enabled
useScrollLock(ownerDocument, modal && state.menuState === MenuStates.Open)
useScrollLock(
ownerDocument,
state.__demoMode ? false : modal && state.menuState === MenuStates.Open
)

// Mark other elements as inert when the menu is visible, and `modal` is enabled
useInertOthers(
{ allowed: useEvent(() => [state.buttonRef.current, state.itemsRef.current]) },
modal && state.menuState === MenuStates.Open
state.__demoMode ? false : modal && state.menuState === MenuStates.Open
)

// We keep track whether the button moved or not, we only check this when the menu state becomes
Expand Down
17 changes: 6 additions & 11 deletions packages/@headlessui-react/src/components/popover/popover.tsx
Expand Up @@ -81,7 +81,6 @@ enum PopoverStates {
}

interface StateDefinition {
__demoMode: boolean
popoverState: PopoverStates

buttons: MutableRefObject<Symbol[]>
Expand All @@ -93,6 +92,8 @@ interface StateDefinition {

beforePanelSentinel: MutableRefObject<HTMLButtonElement | null>
afterPanelSentinel: MutableRefObject<HTMLButtonElement | null>

__demoMode: boolean
}

enum ActionTypes {
Expand Down Expand Up @@ -120,24 +121,18 @@ let reducers: {
) => StateDefinition
} = {
[ActionTypes.TogglePopover]: (state) => {
let nextState = {
return {
...state,
popoverState: match(state.popoverState, {
[PopoverStates.Open]: PopoverStates.Closed,
[PopoverStates.Closed]: PopoverStates.Open,
}),
__demoMode: false,
}

/* We can turn off demo mode once we re-open the `Popover` */
if (nextState.popoverState === PopoverStates.Open) {
nextState.__demoMode = false
}

return nextState
Comment on lines -130 to -136
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can always turn off demo mode 👍

},
[ActionTypes.ClosePopover](state) {
if (state.popoverState === PopoverStates.Closed) return state
return { ...state, popoverState: PopoverStates.Closed }
return { ...state, popoverState: PopoverStates.Closed, __demoMode: false }
},
[ActionTypes.SetButton](state, action) {
if (state.button === action.button) return state
Expand Down Expand Up @@ -863,7 +858,7 @@ function PanelFn<TTag extends ElementType = typeof DEFAULT_PANEL_TAG>(
useOnDisappear(state.button, () => dispatch({ type: ActionTypes.ClosePopover }), visible)

// Enable scroll locking when the popover is visible, and `modal` is enabled
useScrollLock(ownerDocument, modal && visible)
useScrollLock(ownerDocument, state.__demoMode ? false : modal && visible)

let handleKeyDown = useEvent((event: ReactKeyboardEvent<HTMLButtonElement>) => {
switch (event.key) {
Expand Down