Skip to content

[Feat] Add TeamsHub browse UI with tab switching and registry management#290

Merged
samzong merged 2 commits intomainfrom
feat/teamshub-browse-ui
Apr 7, 2026
Merged

[Feat] Add TeamsHub browse UI with tab switching and registry management#290
samzong merged 2 commits intomainfrom
feat/teamshub-browse-ui

Conversation

@samzong
Copy link
Copy Markdown
Collaborator

@samzong samzong commented Apr 7, 2026

Summary

Add TeamsHub browse UI as a second tab in TeamsPanel, enabling users to browse community team registries and manage registry sources. This is PR-2 of the TeamsHub implementation plan.

Type of change

  • [Feat] new feature
  • [UI] UI or UX change

Why is this needed?

Users need a way to discover and browse community teams from Git-native registries. This PR adds the browse experience; install flow follows in PR-3.

What changed?

  • Added tab switching (My Teams / TeamsHub) in TeamsPanel titlebar
  • Created TeamsHubTab component with search, category filter chips, refresh, and card grid
  • Created TeamHubCard component aligned with existing TeamCard styling (install button placeholder for PR-3)
  • Created RegistryManageDialog for adding/removing/refreshing registries with inline error display
  • Added teamshub.* i18n keys across all 8 locale files

Architecture impact

  • Owning layer: renderer
  • Cross-layer impact: none — consumes existing IPC bridge from PR-1 (hubListRegistries, hubFetchRegistry, hubAddRegistry, hubRemoveRegistry)
  • Invariants touched from docs/architecture-invariants.md: none
  • Why those invariants remain protected: pure renderer UI, no new IPC handlers or shared types

Linked issues

Part of TeamsHub implementation plan (PR-2 of 4).

Validation

  • pnpm lint
  • pnpm check:ui-contract
  • pnpm check:i18n
  • pnpm check:dead-code
  • pnpm format:check
  • pnpm typecheck
  • pnpm test (4 pre-existing failures in file-reader.test.ts, unrelated)
  • Manual smoke test
pnpm check passes (except 4 pre-existing file-reader test failures)
Tab switching, empty state, registry dialog, search, category filter all verified
Dark/light theme verified

Screenshots or recordings

Tab bar integrated into WindowTitlebar. TeamsHub tab shows browse grid with search + category chips. Registry dialog with inline URL validation hint and error display.

All colors use CSS variables. Typography uses semantic type-* classes. No raw Tailwind palette colors or text sizes.

Release note

  • User-facing change. Release note is included below.
Added TeamsHub tab to browse community team registries with search, category filtering, and registry management.

Checklist

  • All commits are signed off (git commit -s)
  • The PR title uses at least one approved prefix: [Feat], [Fix], [UI], [Docs], [Refactor], [Build], or [Chore]
  • The summary explains both what changed and why
  • Validation reflects the commands actually run for this PR
  • Architecture impact is described and references any touched invariants
  • Cross-layer changes are explicitly justified
  • The release note block is accurate

…anagement

Signed-off-by: samzong <samzong.lu@gmail.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 7, 2026

Hi @samzong,
Thanks for your pull request!
If the PR is ready, use the /auto-cc command to assign Reviewer to Review.
We will review it shortly.

Details

Instructions for interacting with me using comments are available here.
If you have questions or suggestions related to my behavior, please file an issue against the gh-ci-bot repository.

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces the 'TeamsHub' browse UI, marking the second phase of the TeamsHub implementation plan. It enables users to discover and browse community teams from Git-native registries directly within the TeamsPanel. The changes include a new tabbed interface, a card-based browsing experience with search and category filtering, and a management dialog for registry sources, all while maintaining existing architectural patterns and IPC communication.

Highlights

  • UI Integration: Added a tab switching mechanism to the TeamsPanel titlebar, allowing users to toggle between 'My Teams' and the new 'TeamsHub' view.
  • TeamsHub Components: Implemented the TeamsHubTab, TeamHubCard, and RegistryManageDialog components to provide a browseable interface for community team registries.
  • Registry Management: Added functionality to add, remove, and refresh community team registries, including inline error handling and validation.
  • Localization: Added comprehensive i18n support for the new TeamsHub features across all 8 supported locales.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages bot commented Apr 7, 2026

Deploying cpwa with  Cloudflare Pages  Cloudflare Pages

Latest commit: 6de2d6d
Status: ✅  Deploy successful!
Preview URL: https://c377cecc.cpwa.pages.dev
Branch Preview URL: https://feat-teamshub-browse-ui.cpwa.pages.dev

View logs

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces the TeamsHub feature, which allows users to browse and manage community team registries through a new tabbed interface in the TeamsPanel. The implementation includes a registry management dialog, team cards, and comprehensive i18n support across multiple locales. The review feedback focuses on enhancing the robustness of the UI when interacting with external registry data. Specifically, it is recommended to add error handling for the initial registry list fetch and to use optional chaining when accessing registry properties like teams, descriptions, and tags to prevent potential runtime crashes from malformed or incomplete data.

Comment on lines +24 to +25
const res = await window.clawwork.hubListRegistries();
if (res.ok && res.result) setRegistries(res.result);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

If the IPC call to hubListRegistries fails (e.g., res.ok is false), the component silently stops loading and shows an empty state. It would be better to provide feedback to the user via a toast message if the initial registry list fails to load.

Suggested change
const res = await window.clawwork.hubListRegistries();
if (res.ok && res.result) setRegistries(res.result);
const res = await window.clawwork.hubListRegistries();
if (res.ok && res.result) {
setRegistries(res.result);
} else if (!res.ok) {
toast.error(res.error ?? t('errors.unknown'));
}

const allEntries = useMemo(() => {
const entries: (TeamHubEntry & { _registryId: string })[] = [];
for (const reg of registries) {
for (const team of reg.teams) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The code assumes reg.teams is always defined. If a registry configuration exists but hasn't been successfully fetched or the cache is malformed, reg.teams might be undefined, leading to a crash. It's safer to use optional chaining or a default empty array.

Suggested change
for (const team of reg.teams) {
for (const team of reg.teams ?? []) {

Comment on lines +59 to +61
e.name.toLowerCase().includes(q) ||
e.description.toLowerCase().includes(q) ||
e.tags.some((tag) => tag.toLowerCase().includes(q)),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The search logic performs toLowerCase() on description and some() on tags without checking if they exist. While the TypeScript interface marks them as required, data fetched from external JSON registries (via the main process) might have missing fields, causing the renderer to crash during filtering.

Suggested change
e.name.toLowerCase().includes(q) ||
e.description.toLowerCase().includes(q) ||
e.tags.some((tag) => tag.toLowerCase().includes(q)),
e.name.toLowerCase().includes(q) ||
(e.description?.toLowerCase() ?? '').includes(q) ||
e.tags?.some((tag) => tag.toLowerCase().includes(q)),

{reg.name || reg.url}
</span>
<span className="type-support flex-shrink-0 text-[var(--text-muted)]">
{reg.fetchedAt ? t('teamshub.teamCount', { count: reg.teams.length }) : t('teamshub.notFetched')}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Accessing reg.teams.length directly can cause a crash if reg.teams is undefined (e.g., if the registry hasn't been fetched or the data is malformed). Using optional chaining is safer here.

Suggested change
{reg.fetchedAt ? t('teamshub.teamCount', { count: reg.teams.length }) : t('teamshub.notFetched')}
{reg.fetchedAt ? t('teamshub.teamCount', { count: reg.teams?.length ?? 0 }) : t('teamshub.notFetched')}

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 644fe14767

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +60 to +61
e.description.toLowerCase().includes(q) ||
e.tags.some((tag) => tag.toLowerCase().includes(q)),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Harden TeamsHub search against malformed registry entries

When users search, this filter unconditionally calls e.description.toLowerCase() and e.tags.some(...). Registry data comes from external teamshub.json files and is not runtime-normalized before being rendered, so a registry entry with missing/null description or tags will throw here and break the TeamsHub tab as soon as text is entered in search. Please add safe fallbacks (for example, default description to '' and tags to []) before lowercasing/filtering.

Useful? React with 👍 / 👎.

Comment on lines +74 to +76
if (!v) {
setUrl('');
setAddError('');
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Guard registry dialog close when form state is dirty

This dialog holds user-entered state (url) but closes immediately and clears that state whenever onOpenChange(false) fires, so an accidental outside click or ESC silently discards in-progress input. Per the stateful dialog rule in .claude/rules/frontend.md, this should use useDialogGuard/discard confirmation behavior; otherwise users can lose typed registry URLs without warning.

Useful? React with 👍 / 👎.

- Add error toast when initial hubListRegistries fails
- Use optional chaining for registry teams/description/tags
- Use Promise.allSettled for parallel refresh
- Fix double-toast on remove by consolidating in parent
- Reset dialog error state on close
- Add teamshub.all i18n key (decouple from cron.filterAll)

Signed-off-by: samzong <samzong.lu@gmail.com>
@samzong samzong merged commit b9ed5f6 into main Apr 7, 2026
9 checks passed
@samzong samzong deleted the feat/teamshub-browse-ui branch April 7, 2026 09:44
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.

1 participant