diff --git a/packages/@headlessui-react/src/components/tabs/tabs.tsx b/packages/@headlessui-react/src/components/tabs/tabs.tsx index 4bdd1d3b1e..c5595325f5 100644 --- a/packages/@headlessui-react/src/components/tabs/tabs.tsx +++ b/packages/@headlessui-react/src/components/tabs/tabs.tsx @@ -11,6 +11,7 @@ import React, { // Types ElementType, MutableRefObject, + MouseEvent as ReactMouseEvent, KeyboardEvent as ReactKeyboardEvent, Dispatch, ContextType, @@ -354,11 +355,19 @@ let TabRoot = forwardRefWithAs(function Tab) => { + event.preventDefault() + }, []) + let slot = useMemo(() => ({ selected }), [selected]) let propsWeControl = { ref: tabRef, onKeyDown: handleKeyDown, onFocus: activation === 'manual' ? handleFocus : handleSelection, + onMouseDown: handleMouseDown, onClick: handleSelection, id, role: 'tab', diff --git a/packages/@headlessui-vue/src/components/tabs/tabs.ts b/packages/@headlessui-vue/src/components/tabs/tabs.ts index b01e779a34..9d67058df2 100644 --- a/packages/@headlessui-vue/src/components/tabs/tabs.ts +++ b/packages/@headlessui-vue/src/components/tabs/tabs.ts @@ -245,6 +245,13 @@ export let Tab = defineComponent({ api.setSelectedIndex(myIndex.value) } + // This is important because we want to only focus the tab when it gets focus + // OR it finished the click event (mouseup). However, if you perform a `click`, + // then you will first get the `focus` and then get the `click` event. + function handleMouseDown(event: MouseEvent) { + event.preventDefault() + } + let type = useResolveButtonType( computed(() => ({ as: props.as, type: attrs.type })), tabRef @@ -256,6 +263,7 @@ export let Tab = defineComponent({ ref: tabRef, onKeydown: handleKeyDown, onFocus: api.activation.value === 'manual' ? handleFocus : handleSelection, + onMousedown: handleMouseDown, onClick: handleSelection, id, role: 'tab',