Skip to content

feat: Support Firefox native tab groups API (issue #5212)#5361

Open
repparw wants to merge 11 commits into
tridactyl:masterfrom
repparw:feat/native-tab-groups
Open

feat: Support Firefox native tab groups API (issue #5212)#5361
repparw wants to merge 11 commits into
tridactyl:masterfrom
repparw:feat/native-tab-groups

Conversation

@repparw
Copy link
Copy Markdown
Contributor

@repparw repparw commented Mar 17, 2026

Summary

Integrates Firefox's built-in tab groups (FF 137+) as the backend for Tridactyl's tab group commands.

Closes #5212

Changes

  • manifest.json: Added "tabGroups" permission
  • package.json: Updated @types/firefox-webext-browser to v143.0.0
  • src/lib/tab_groups.ts: Core implementation with native API support, error handling, colors, and migration
  • src/excmds.ts: Updated commands to use native groups, added color and migration support
  • src/lib/tab_groups.test.ts: New unit tests (9 tests) for feature detection

Key Benefits

  • ✅ Groups persist across browser restarts
  • ✅ Groups can sync via Firefox Sync
  • ✅ Native group colors and titles supported (blue, red, yellow, green, pink, purple, cyan, orange, grey)
  • ✅ Automatic show/hide via group collapse/expand
  • ✅ Backward compatible with legacy session-based storage
  • ✅ Error handling with graceful fallback to legacy storage
  • ✅ Feature detection caching for performance

New Commands

:tgroupcreate <name> [color]  - Create a new native tab group (with optional color)
:tgroupmigrate               - Migrate legacy groups to native groups
:tgroupcolors                - List available colors
:tgroupswitch <name>         - Switch to a tab group
:tgroupclose                 - Close current tab group

Migration

Users upgrading from older Firefox versions (pre-137) can migrate their existing tab groups to native groups using:

:tgroupmigrate

This converts groups stored in browser.sessions to native Firefox groups. The migration:

  • Preserves all group names and tab assignments
  • Requires Firefox 137+ for native tab groups API
  • Falls back to legacy implementation on older versions

Usage Examples

:tgroupcreate work           # Create a group named "work"
:tgroupcreate personal blue  # Create a blue group named "personal"
:tgroupmigrate               # Migrate legacy groups to native
:tgroupcolors                # List available colors

Testing

  • ✅ All 606 unit tests pass
  • ✅ Build successful
  • ✅ Feature detection tested
  • ✅ Error handling tested with fallbacks

Notes

  • Requires Firefox 137+ for native tab groups API
  • Falls back to legacy implementation on older Firefox versions
  • Feature detection via hasNativeTabGroups() checks for browser.tabs.group
  • Two-step group creation (create then rename) is the documented API approach

@repparw
Copy link
Copy Markdown
Contributor Author

repparw commented Mar 17, 2026

Can't test locally right now, but if someone has time, I think it should be mostly done?

@bovine3dom
Copy link
Copy Markdown
Member

thanks for this :)

do you know what's causing the formatting changes? it makes it really hard to see what has changed and what is just some whitespace

generally I'd be happier if PRs were kept <100 lines of changes so i have some chance to review them. i get that this is a big feature but i suspect bits of it could be terser or split into multiple smaller commits.

also, aren't the tests basically pointless? they're just checking if functions are functions. which typescript will already be checking 🤔

@repparw repparw force-pushed the feat/native-tab-groups branch 2 times, most recently from 86058f0 to 1713f53 Compare March 17, 2026 23:14
@repparw
Copy link
Copy Markdown
Contributor Author

repparw commented Mar 17, 2026

yeah I think I had a write on save formatter in my nvim config enabled, I'll check that.

re tests: fair, I'll remove that lmao

@repparw repparw force-pushed the feat/native-tab-groups branch 4 times, most recently from e085f32 to b2907bb Compare March 18, 2026 00:03
@repparw
Copy link
Copy Markdown
Contributor Author

repparw commented Mar 18, 2026

the excmds formatting changes seem to be from a change in prettier on the pre-commit hook I think, can recreate by running prettier src/excmds.ts -w on master

@repparw repparw marked this pull request as ready for review March 18, 2026 00:14
Copilot AI review requested due to automatic review settings March 18, 2026 00:14
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds support for Firefox’s native tab groups API (tabGroups / tabs.group) alongside the existing legacy tab-group implementation backed by browser.sessions.

Changes:

  • Add tabGroups permission and update WebExtension type definitions to include native tab group APIs.
  • Extend src/lib/tab_groups.ts with native tab group detection, color normalization, native implementations of group operations, and a migration helper.
  • Update tab-group ex-commands to support native groups (including color support, migration, and listing supported colors).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 7 comments.

File Description
src/manifest.json Adds the tabGroups permission required for native tab group APIs.
src/lib/tab_groups.ts Implements native tab group support, color handling, and legacy→native migration logic.
src/excmds.ts Adds/updates tab group commands to use native tab groups when available (create/switch/migrate/colors).
package.json Bumps @types/firefox-webext-browser to a newer version for updated WebExtension typings.
Comments suppressed due to low confidence (1)

src/manifest.json:145

  • Adding the tabGroups permission to the required permissions list may prevent installation on Firefox versions that don’t recognize this permission (the code/docs here mention native tab groups being Firefox 137+ while strict_min_version is still 91.1.0). Consider either bumping strict_min_version accordingly or moving tabGroups into optional_permissions and requesting it only when the native API is available.
        "tabGroups",
        "webNavigation",
        "webRequest",
        "webRequestBlocking",
        "proxy",
        "<all_urls>"
    ],
    "applications": {
        "gecko": {
            "id": "tridactyl.vim.betas@cmcaine.co.uk",
            "strict_min_version": "91.1.0"
        }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/lib/tab_groups.ts Outdated
Comment thread src/lib/tab_groups.ts
Comment thread src/lib/tab_groups.ts Outdated
Comment thread src/lib/tab_groups.ts
Comment thread src/lib/tab_groups.ts Outdated
Comment thread src/lib/tab_groups.ts Outdated
Comment thread package.json
@bovine3dom bovine3dom force-pushed the feat/native-tab-groups branch from 3ce06d4 to 1a8fc9e Compare March 19, 2026 15:13
repparw and others added 5 commits March 19, 2026 16:16
- Add native tab groups support (Firefox 137+)
- Feature detection with caching
- Error handling with fallback
- Color support via :tgroupcreate <name> <color>
- :tgroupmigrate and :tgroupcolors commands
- Updated @types/firefox-webext-browser to v143.0.0
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
- Use tab's window instead of activeWindowId for setTabTgroup
- Await async calls in try/catch for proper error handling
- Add Array.isArray check for type safety in migration
- Optimize migration: query tabs once and parallelize tab value fetches
Add tabGroups to optional_permissions to avoid installation issues
on Firefox versions < 137 that don't recognize this permission.
Also update yarn.lock for @types/firefox-webext-browser.
@bovine3dom bovine3dom force-pushed the feat/native-tab-groups branch from 1a8fc9e to 6ccc47b Compare March 19, 2026 15:17
Copy link
Copy Markdown
Member

@bovine3dom bovine3dom left a comment

Choose a reason for hiding this comment

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

rebased on master with prettier changes to reduce noise

i dunno how i feel about the optional permission. it means that it won't stop people from updating, but in practice i don't know how many people will enable it

i couldn't personally work out how to do so so couldn't even test the new paths 🙃

Comment thread src/manifest.json Outdated
"<all_urls>"
],
"optional_permissions": [
"tabGroups"
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.

if users don't allow this they will fall back to our current groups

we probably need to provide some upgrade wizard that allows them to enable the permission (iirc we can only do it on user actions, i.e. they need to click a button somewhere or use a browser bind. not an excmd) and then migrate their existing groups

which is lame but them's the rules

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think it's in optional because the required minimum version was very low. (like around 90?)
We could put it with the other permissions and bump minimum req version to 137... I don't think anyone is just not updating their browser anyways?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

"To use this API, an extension must request the "tabGroups" permission in its manifest.json file. The "tabGroups" permission is not shown to users in permission prompts."

If I understand correctly this means they should go to Extensions > Permissions and data after updating?

@repparw
Copy link
Copy Markdown
Contributor Author

repparw commented Mar 19, 2026

We could also add an issue to track the chrome API implementation, out of scope for me, but maybe with this as base it's easier

@bovine3dom
Copy link
Copy Markdown
Member

ok, cool, the PR does actually do something now :)

first regression is that tgroupswitch makes a new tab rather than putting the current tabs into that group (if they're not in a group)

second one i've seen is that because tab groups aren't actually hidden, b now shows all tabs, not just ones from your group. B does work correctly, though

please could you test this PR thoroughly against current behaviour? we have like 10-50k active users so even the smallest amount of friction to muscle memory adds up to a lot of sad people

we should probably also add some config for people who prefer tridactyl's groups to the native ones

@repparw
Copy link
Copy Markdown
Contributor Author

repparw commented Mar 19, 2026

I'll check switch and b in a moment!

haven't tested it yet, maybe after fixing this or in the weekend. I didn't use the tridactyl groups so I don't really know what to test for, if you have any other pointers for use-cases/setups, I'm doing all this to have a better way to manip the native groups lmao

re config: I was working on the assumption of your comment, do you think we should keep both? at this point shouldn't be too difficult, as we have the check for tabgroups api existing, can change it to check api and config

@repparw
Copy link
Copy Markdown
Contributor Author

repparw commented Mar 19, 2026

should tgroupswitch newgroup move all ungrouped tabs to new group? was this the previous functionality?

repparw added 2 commits March 19, 2026 13:26
- tgroupcreate: group ungrouped tabs instead of creating new tab
- tgroupcreate: skip tabs.hide/show when using native groups
- tgroupmove: skip tabs.hide/show when using native groups
Only show tabs from current group when using native tab groups API
to maintain expected 'b' behavior.
@repparw
Copy link
Copy Markdown
Contributor Author

repparw commented Mar 19, 2026

afaict now's okay. move was also still hiding tabs after moving, changed that too

@repparw
Copy link
Copy Markdown
Contributor Author

repparw commented Mar 19, 2026

rename is also not working. fixing that now...
still haven't tested migrate

@repparw
Copy link
Copy Markdown
Contributor Author

repparw commented Mar 19, 2026

It works right now, at least with the mock data I used for testing, couldn't get old tabgroups into the PR branch's web-ext to try with 'real' data

Commited the mock script if you want to test yourself, in a diff commit to easily remove it for merging

@bovine3dom bovine3dom mentioned this pull request Apr 19, 2026
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.

Update tab groups functionality to support Firefox new built-in tab groups

3 participants