Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

fix(tabs): Fix the issue where multiple clicks on mobile-first tabs do not take effect #3669

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

Merged
zzcr merged 2 commits into dev from fix/tabs-20250828
Aug 29, 2025
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/design/aurora/src/dropdown-item/index.ts
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export default {

dispatch('TinyDropdown', 'selected-index', [dataStore.currentIndex])

emit('click', dataStore.itemData, event)
dispatch('TinyDropdownMenu', 'menu-item-click', [
dataStore.itemData,
vm,
Expand All @@ -47,6 +48,7 @@ export default {
emit('item-click', [props.itemData, vm, props.disabled])
}

emit('click', props.itemData, event)
dispatch('TinyDropdown', 'menu-item-click', [props.itemData, vm, props.disabled])
dispatch('TinyDropdown', 'is-disabled', [props.disabled])
dispatch('TinyDropdown', 'selected-index', [state.currentIndex])
Expand Down
5 changes: 4 additions & 1 deletion packages/renderless/src/tabs-mf/index.ts
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,10 @@ export const wheelListener = ({ vm, api, tabs, state }) =>

export const getBoundRect = (vm) => () => vm.$el.getBoundingClientRect()

export const handleClickDropdownItem = (tabs) => (name) => tabs.clickMore(name)
export const handleClickDropdownItem = (tabs) => (navItem, event) => {
tabs.$emit('click', navItem, event)
tabs.clickMore(navItem.name)
}
Comment on lines +291 to +294
Copy link

@coderabbitai coderabbitai bot Aug 28, 2025

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Align behavior with tab-nav clicks; validate input and skip disabled

Keep event order consistent with handleNavItemClick (emit after activation), and avoid acting on invalid/disabled items.

Apply this diff:

-export const handleClickDropdownItem = (tabs) => (navItem, event) => {
- tabs.$emit('click', navItem, event)
- tabs.clickMore(navItem.name)
-}
+export const handleClickDropdownItem = (tabs) => (navItem, event) => {
+ if (!navItem || !navItem.name || navItem.disabled) return
+ tabs.clickMore(navItem.name)
+ tabs.$emit('click', navItem, event)
+}
📝 Committable suggestion

!!️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const handleClickDropdownItem = (tabs) => (navItem, event) => {
tabs.$emit('click', navItem, event)
tabs.clickMore(navItem.name)
}
export const handleClickDropdownItem = (tabs) => (navItem, event) => {
if (!navItem || !navItem.name || navItem.disabled) return
tabs.clickMore(navItem.name)
tabs.$emit('click', navItem, event)
}
🤖 Prompt for AI Agents
In packages/renderless/src/tabs-mf/index.ts around lines 291 to 294, the
dropdown click handler currently emits before activation and doesn't validate
input or skip disabled items; update handleClickDropdownItem to first check that
navItem exists and is not disabled (and has a valid name), then call
tabs.clickMore(navItem.name) to activate the tab, and only after successful
activation call tabs.$emit('click', navItem, event); return early if validation
fails to avoid acting on invalid/disabled items.


export const scrollToLeft = (tabs) => () => {
tabs.scrollTo(tabs.state.navs[0].name)
Expand Down
2 changes: 1 addition & 1 deletion packages/vue/src/dropdown-item/src/mobile-first.vue
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import { props, setup, defineComponent } from '@opentiny/vue-common'
import { renderless, api } from '@opentiny/vue-renderless/dropdown-item/mf'

export default defineComponent({
emits: ['update:modelValue', 'change', 'closed', 'open', 'opened', 'close', 'confirm', 'reset'],
emits: ['update:modelValue', 'change', 'closed', 'open', 'opened', 'close', 'confirm', 'reset', 'click'],
props: [...props, 'disabled', 'icon', 'itemData', 'selected', 'label', 'level', 'currentIndex', 'tooltipContent'],
setup(props, context): any {
return setup({ props, context, renderless, api })
Expand Down
10 changes: 6 additions & 4 deletions packages/vue/src/tabs/src/mobile-first/tab-bar.vue
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export default defineComponent({
state.moreList.length
? h('div', { class: 'hidden sm:inline-block w-11 h-11 sm:h-10 text-sm cursor-pointer' }, [
h('span', { class: 'inline-flex w-full h-full flex-col justify-center items-center' }, [
h(Dropdown, { on: { 'item-click': handleClickDropdownItem }, props: { showIcon: false } }, [
h(Dropdown, { props: { showIcon: false } }, [
h('span', {}, [h(IconPopup(), { class: 'fill-color-icon-focus text-base' })]),
h(
DropdownMenu,
Expand All @@ -90,9 +90,11 @@ export default defineComponent({
props: { popperClass: 'max-h-[theme(spacing.80)] overflow-x-hidden overflow-y-auto' }
},
state.moreOptions.map((opt: NavItem) =>
h(DropdownItem, { key: key(opt), props: { itemData: opt.name } }, [
opt.slotTitle ? opt.slotTitle() : opt.title
])
h(
DropdownItem,
{ key: key(opt), on: { click: handleClickDropdownItem }, props: { itemData: opt } },
[opt.slotTitle ? opt.slotTitle() : opt.title]
)
Comment on lines +93 to +97
Copy link

@coderabbitai coderabbitai bot Aug 28, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue

Pass disabled state and use stable keys

  • Without passing disabled, disabled items won’t render/behave correctly.
  • Randomized keys cause unnecessary remounts. Use a stable key (e.g., name).

Apply this diff:

- h(
- DropdownItem,
- { key: key(opt), on: { click: handleClickDropdownItem }, props: { itemData: opt } },
- [opt.slotTitle ? opt.slotTitle() : opt.title]
- )
+ h(
+ DropdownItem,
+ {
+ key: opt.name,
+ on: { click: handleClickDropdownItem },
+ props: { itemData: opt, disabled: !!opt.disabled }
+ },
+ [opt.slotTitle ? opt.slotTitle() : opt.title]
+ )
📝 Committable suggestion

!!️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
h(
DropdownItem,
{ key: key(opt), on: { click: handleClickDropdownItem }, props: { itemData: opt } },
[opt.slotTitle ? opt.slotTitle() : opt.title]
)
h(
DropdownItem,
{
key: opt.name,
on: { click: handleClickDropdownItem },
props: { itemData: opt, disabled: !!opt.disabled }
},
[opt.slotTitle ? opt.slotTitle() : opt.title]
)
🤖 Prompt for AI Agents
packages/vue/src/tabs/src/mobile-first/tab-bar.vue around lines 93 to 97: the
DropdownItem is not receiving the disabled state and is using an unstable key
which causes unnecessary remounts; update the element to pass the disabled flag
from the option (e.g., props: { itemData: opt, disabled: opt.disabled }) and
replace the randomized key with a stable unique identifier from the option
(e.g., key: opt.name or opt.value), ensuring click handlers respect the disabled
state if needed.

)
)
])
Expand Down
Loading

AltStyle によって変換されたページ (->オリジナル) /