feat(Button): add externalIcon prop#6706
Conversation
Icon position didn't handle default slot (w/o `label`prop) Also removed test class `truncate`
Icon position didn't handle default slot (w/o `label`prop) Also removed test class `truncate`
…feat/button-external-icon
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (2)
📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughThis change adds an Estimated code review effort: 2 (Simple) | ~12 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/runtime/components/Button.vue (1)
162-163: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueMinor: inconsistent array wrapping for
classparameter.The new
externalIconContainerandexternalIconslots wrapprops.ui?.*in array brackets, while existing slots (leadingIcon,trailingIcon) pass the value directly. Both work, but matching the existing style keeps the template consistent.♻️ Suggested consistency fix
- <div v-if="props.target === '_blank' && props.externalIcon !== false" data-slot="externalIconContainer" :class="ui.externalIconContainer({ class: [props.ui?.externalIconContainer], active })"> - <UIcon :name="typeof props.externalIcon === 'string' ? props.externalIcon : appConfig.ui.icons.external" data-slot="externalIcon" :class="ui.externalIcon({ class: [props.ui?.externalIcon], active })" /> + <div v-if="props.target === '_blank' && props.externalIcon !== false" data-slot="externalIconContainer" :class="ui.externalIconContainer({ class: props.ui?.externalIconContainer, active })"> + <UIcon :name="typeof props.externalIcon === 'string' ? props.externalIcon : appConfig.ui.icons.external" data-slot="externalIcon" :class="ui.externalIcon({ class: props.ui?.externalIcon, active })" />🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/runtime/components/Button.vue` around lines 162 - 163, The Button template has inconsistent class binding style for the new external icon slots. Update the `externalIconContainer` and `externalIcon` bindings in `Button.vue` to match the existing `leadingIcon` and `trailingIcon` pattern by passing `props.ui?.externalIconContainer` and `props.ui?.externalIcon` directly through the `ui.*({ class: ... })` calls in the same way as the other icon slots.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@test/components/Button.spec.ts`:
- Around line 27-29: The Button spec has a duplicate case because the “with
externalIcon” scenario omits the prop and behaves the same as `externalIcon:
false`. Update the first test case in `Button.spec.ts` to pass `externalIcon:
true` so the `Button`/link rendering path is actually exercised, and keep the
existing `externalIcon: false` and custom icon cases to cover the other
behaviors.
---
Nitpick comments:
In `@src/runtime/components/Button.vue`:
- Around line 162-163: The Button template has inconsistent class binding style
for the new external icon slots. Update the `externalIconContainer` and
`externalIcon` bindings in `Button.vue` to match the existing `leadingIcon` and
`trailingIcon` pattern by passing `props.ui?.externalIconContainer` and
`props.ui?.externalIcon` directly through the `ui.*({ class: ... })` calls in
the same way as the other icon slots.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: c6816011-8063-492f-992c-a98150eb0e5d
⛔ Files ignored due to path filters (80)
test/components/__snapshots__/Alert-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Alert.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/AuthForm-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/AuthForm.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Banner-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Banner.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Button-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Button.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Calendar-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Calendar.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Carousel-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Carousel.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/ChatPromptSubmit-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/ChatPromptSubmit.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/ChatTool-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/ChatTool.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/CommandPalette-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/CommandPalette.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/DashboardNavbar-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/DashboardNavbar.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/DashboardSearch-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/DashboardSearch.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/DashboardSearchButton-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/DashboardSearchButton.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/DashboardSidebar-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/DashboardSidebar.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/DashboardSidebarCollapse-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/DashboardSidebarCollapse.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/DashboardSidebarToggle-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/DashboardSidebarToggle.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Drawer-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Drawer.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/EditorDragHandle-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/EditorDragHandle.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/EditorToolbar-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/EditorToolbar.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Empty-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Empty.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Error-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Error.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/FieldGroup-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/FieldGroup.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/FileUpload-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/FileUpload.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Header-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Header.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/InputMenu-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/InputMenu.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/InputNumber-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/InputNumber.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Modal-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Modal.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/PageCTA-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/PageCTA.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/PageHeader-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/PageHeader.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/PageHero-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/PageHero.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/PageSection-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/PageSection.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Pagination-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Pagination.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/PricingPlan-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/PricingPlan.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/PricingTable-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/PricingTable.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/SelectMenu-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/SelectMenu.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Sidebar-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Sidebar.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Slideover-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Slideover.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Table-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Table.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Theme-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Theme.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Toast-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/Toast.spec.ts.snapis excluded by!**/*.snaptest/components/content/__snapshots__/ContentSearch.spec.ts.snapis excluded by!**/*.snaptest/components/content/__snapshots__/ContentSearchButton.spec.ts.snapis excluded by!**/*.snap
📒 Files selected for processing (5)
docs/content/docs/2.components/button.mdplaygrounds/nuxt/app/pages/components/button.vuesrc/runtime/components/Button.vuesrc/theme/button.tstest/components/Button.spec.ts
commit: |
|
I didn't add the I found it better to make it available only to |
🔗 Linked issue
Resolves #4501
❓ Type of change
📚 Description
Added
externalconprop toButton(similar toNavigationMenu. By default (and by design, I guess), it's disabled, and only enabled iftarget="_blank"andexternalIconistrueor references anyIcon.In order to have the same "superscript" effect as
NavigationItem, I also added theexternalIconandexternalIconContainerslots toButton.Change is not required per say, but can be useful for some people.
I also added examples in the docs but I'm not sure it is that useful. However, the feature that
externalIconcan be anyIconisn't documented inNavigationMenu.P.S.: please, keep in mind that this is my first contribution and PR, so don't hesitate to point out what's wrong, missing or too much; I'm completely open to feedbacks.
📝 Checklist