Skip to content

Conversation

@yooouuri
Copy link
Contributor

πŸ”— Linked issue

❓ Type of change

  • πŸ“– Documentation (updates to the documentation or readme)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • πŸ‘Œ Enhancement (improving an existing functionality)
  • ✨ New feature (a non-breaking change that adds functionality)
  • 🧹 Chore (updates to the build process or auxiliary tools and libraries)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

πŸ“š Description

Screen.Recording.2026-01-27.at.12.19.32.mov

Currently, when there is no data but being fetched and you open the InputMenu for example the ComboboxEmpty displays and then after the data is displayed.

πŸ“ Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

@github-actions github-actions bot added the v4 #4488 label Jan 27, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 27, 2026

πŸ“ Walkthrough

Walkthrough

This change adds loading state handling to input menu and select menu components. Two example files bind the loading prop to their fetch status when pending. The core InputMenu and SelectMenu components are updated to conditionally hide their empty state during loading by adding v-if="!props.loading" guards to the ComboboxEmpty element.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~5 minutes

πŸš₯ Pre-merge checks | βœ… 3
βœ… Passed checks (3 passed)
Check name Status Explanation
Title check βœ… Passed The title accurately describes the main change: preventing ComboboxEmpty display when loading is true, which matches the core modifications in InputMenu and SelectMenu components.
Description check βœ… Passed The description is related to the changeset, explaining the problem being solved (ComboboxEmpty displaying during loading) and noting that documentation was updated.
Docstring Coverage βœ… Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 27, 2026

npm i https://pkg.pr.new/@nuxt/ui@5956

commit: d0a7a4c

@benjamincanac
Copy link
Member

Would you mind sharing the code to reproduce this use-case?

@yooouuri
Copy link
Contributor Author

yooouuri commented Jan 28, 2026

@benjamincanac

A little bit of context:

We have many SelectMenu/InputMenu's on our pages, but we only want to fetch data when they are openend.

<script setup lang="ts">
const { data: users, status, execute } = await useAsyncData(
  async () => {
    await new Promise(resolve => setTimeout(resolve, 1000))

    return $fetch('https://jsonplaceholder.typicode.com/users')
  },
  {
    immediate: false,
    transform: (data: any) => {
      return data?.map(user => ({ id: user.id, label: user.name, avatar: { src: `https://i.pravatar.cc/120?img=${user.id}` } }))
    },
    lazy: true
  }
)

const open = ref(false)

watch(open, (value) => {
  if (value) {
    execute()
  }
})
</script>

<template>
  <USelectMenu v-model:open="open" :items="users" class="w-48" :loading="status === 'pending'" placeholder="Select user" />
</template>

With this MR:

Screen.Recording.2026-01-28.at.10.39.27.mov

And without

Screen.Recording.2026-01-28.at.10.40.41.mov

Maybe even disable the search, when there are no items and loading is true?

@benjamincanac
Copy link
Member

I'm not sure removing the ComboboxEmpty on loading is the right way, this solution displays a double border which doesn't look nice. How about using the empty slot to display a loader instead?

<script setup lang="ts">
const { data: users, status, execute } = await useAsyncData(
  async () => {
    await new Promise(resolve => setTimeout(resolve, 1000))

    return $fetch('https://jsonplaceholder.typicode.com/users')
  },
  {
    immediate: false,
    transform: (data: any) => {
      return data?.map(user => ({ id: user.id, label: user.name, avatar: { src: `https://i.pravatar.cc/120?img=${user.id}` } }))
    },
    lazy: true
  }
)

const open = ref(false)

watch(open, (value) => {
  if (value) {
    execute()
  }
})
</script>

<template>
  <USelectMenu
    v-model:open="open"
    :items="users"
    class="w-48"
    placeholder="Select user"
    :ui="{ empty: 'flex justify-center' }"
  >
    <template #empty>
      <UIcon v-if="status === 'pending'" name="i-lucide-loader-circle" class="animate-spin size-5" />
    </template>
  </USelectMenu>
</template>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v4 #4488

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants