Skip to content

Tag Group component - #271

Merged
ealmloff merged 17 commits into
DioxusLabs:mainfrom
ddudenin:main
Jun 28, 2026
Merged

ealmloff merged 17 commits into
DioxusLabs:mainfrom
ddudenin:main

Conversation

@ddudenin

@ddudenin ddudenin commented May 16, 2026 •

Copy link
Copy Markdown
Contributor

Plan

  • Implement new component.
  • Support selection mode.
  • Support removable state.
  • Pass tests.
    • Compilation.
    • Check, clippy tests.
    • Doc comments.
    • Playwright.

References

https://react-aria.adobe.com/TagGroup#content
https://ant.design/components/tag

@ddudenin

Copy link
Copy Markdown
Contributor Author

@ealmloff I implemented this component for my own needs and thought it might be useful in Dioxus, so I created this MR.

I'd also like to point out that the source code includes list_data, which is the closest analog to useListData from React-Aria, with full test coverage of all calls. In my opinion, it could be useful in the future. It's not currently used anywhere in the project, so if it's no longer needed, it could simply be removed from the source code.

Comment thread primitives/src/list_data.rs Outdated
Comment thread primitives/src/tag_group.rs Outdated
@ddudenin

Copy link
Copy Markdown
Contributor Author

@ealmloff I made an implementation similar to the select/combobox components, and removed the list_data from the project

@ealmloff ealmloff left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for working on this, its a lot closer, but there are still a few tweaks left.

I also have some questions about interactions. When you hit backspace it currently deletes all the selected tags:

Screen.Recording.2026-05-21.at.12.50.18.PM.mov

I would expect to delete the tag I was focused on instead. Do other component libraries have this behavior?

After you delete an item with backspace you also lose the ability to focus the group with tab:

Screen.Recording.2026-05-21.at.12.50.18.PM.mov

Comment thread primitives/src/tag_group.rs Outdated
Comment thread primitives/src/tag_group.rs Outdated
Comment thread primitives/src/tag_group.rs Outdated
Comment thread primitives/src/tag_group.rs
Comment thread primitives/src/tag_group.rs Outdated
Comment thread primitives/src/tag_group.rs Outdated
Comment thread primitives/src/tag_group.rs Outdated
Comment thread primitives/src/tag_group.rs
@ddudenin

Copy link
Copy Markdown
Contributor Author

@ealmloff I can speak with certainty regarding Aria: it removes all selected items. This is evident in their example, where they use a list_data; the closure receives a set of keys to be deleted.

If you provide a definitive decision to remove only the focused element, I will adjust the logic accordingly.

@ealmloff

ealmloff commented May 21, 2026 •

Copy link
Copy Markdown
Member

It looks like react-aria implements something similar but only if the focused item is selected which seems reasonable: https://react-aria.adobe.com/TagGroup/useTagGroup.html#remove-tags

Additionally, when selection is enabled, all selected items will be deleted when pressing the backspace key on a selected tag.

@ddudenin
ddudenin force-pushed the main branch 2 times, most recently from 2d2897d to 2fcdece Compare May 22, 2026 10:44
@ddudenin

Copy link
Copy Markdown
Contributor Author

@ealmloff I made changes based on all the comments and updated the logic for deleting elements depending on focus and selection state (as per the example above) and fixed the focus after deleting an element.

@ealmloff

Copy link
Copy Markdown
Member

Thanks! It looks like there are some issues with the new playwright tests for the tag group component?

@ddudenin

Copy link
Copy Markdown
Contributor Author

Yes, I completely forgot to correct them, for some reason I thought the error wasn't in the tags :)

Fixed the tests

@ddudenin
ddudenin requested a review from ealmloff May 29, 2026 16:58
@github-actions

Copy link
Copy Markdown

@ealmloff
ealmloff merged commit bf007c1 into DioxusLabs:main Jun 28, 2026
13 checks passed
MentalGear pushed a commit to MentalGear/dioxus-components that referenced this pull request Sep 19, 2026
… bug

User report on the live site: "Tag group looks a bit deflated - maybe more
padding, or do they look like this in the original?" Compared byte-for-byte
against upstream PR DioxusLabs#271 (git show bf007c1:preview/src/components/tag_group/style.css,
merged 2026-06-29), with class names adapted to the current dx- naming, by
injecting it into the live :8080 demo via page.addStyleTag alongside the
current build: both measure identically in light and dark (20px tag height,
2px block / 12px inline padding, 12px font-size, 4px gap, 9999px radius).

That exonerates the 2026-09-04 token migration (fb4ed5f, backlog row 31b) by
measurement, not just reasoning: an automated audit resolved every
var(--dx-*) substitution across all 41 component stylesheets that commit
touched back to its defined token value (normalizing rem<->px and s<->ms
so unit-only rewrites aren't mistaken for value changes) and found zero
rendered-value mismatches anywhere, tag_group included. The migration is
value-preserving exactly as its own commit message and row 31b claim -- see
this lane's report for the full per-file reconciliation.

So upstream genuinely shipped tags this compact from day one; per the task's
own fallback, improved it modestly toward shadcn's Badge/Toggle sizing
instead of reverting: .dx-tag-group-tag's font-size var(--dx-text-xs) ->
var(--dx-text-sm), padding-block 0.125rem -> var(--dx-space-1) (matching
the already-correct var(--dx-space-3) inline padding), plus
box-sizing: border-box and min-height: var(--dx-space-7) so the ~28px floor
is deterministic rather than riding on font-metric rounding. Measured
before/after with the same injected-stylesheet methodology: 20px -> 28px
tall, 2px -> 4px block padding, unchanged in both themes.

New playwright/tag_group.spec.ts "Geometry" test reproduces this red/green
live: fails against the current :8080 build (20px < 28px expected) and
passes when the fixed CSS is served over the same page via a temporary
page.route interception (13/13 tests green, including the existing axe
scan -- no accessibility regression from the larger tag). All four
check-*.sh gates and `stylelint "src/**/*.css"` pass clean.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011ZN6X5bVAFJwJa9qknoW78
(cherry picked from commit f1ddc921d236902477d85d77ae1981dc90432f4d)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants