Skip to content

[FEATURE] Group the sidebar's connections in collapsible sections #1170

Description

@yizhixiaokong

The Connections panel is one flat list with a Favorites section above it, so twenty connections have no way to
be kept apart. What I propose is the same sectioning, made user-defined: collapsible sections, in this panel
only, for the connections the user added.

Today:

Connections
  pg-prod-main          postgres
  pg-staging-main       postgres
  local-mysql           mysql
  test-redis-6380       redis

With sections:

Favorites
  pg-prod-main          postgres
Production                    2
  pg-prod-main          postgres
  pg-prod-replica       postgres
Staging                       1
Ungrouped                     1
Seeds                         1
  test-redis-6380       redis

The shape follows Favorites: a small label, a count, a hairline, and the connection rows under it at the same
indent they have today. The header becomes collapsible, and the sections are ordered as the user wants them. The
group membership is one more user preference next to favorite_connections and connection_order, so nothing
about the connection records or the other places that list connections changes.

The one conflict to settle first: the star moves a row today. favorite_connections cuts the panel in two,
and a favorited connection leaves the Connections section to render under Favorites (a test pins that it
renders once, not twice). With user-defined sections that rule pulls a row out of its group: a starred connection
in Production would leave Production, which reads as the group having lost a member. Three readings:

  1. Favorites keeps winning: the star still moves the row to the top section, and its group is remembered but
    not shown while it is starred.
  2. The star becomes a mark: the row stays in its group and also appears under Favorites. This changes today's
    rule, and it is the reading I would pick, because "which group it is in" and "pinned to the top" stay
    independent and no group silently loses a member.
  3. Favorites becomes a group of its own: the star moves the connection into it like any other group, so a
    connection lives in exactly one place. Then there is no favorite inside Production, and drag and drop
    already does what the star would do.

The rest of what I would like your view on

  1. Which of the three readings above, or a fourth?
  2. Where do the seed connections sit? Their own fixed section, or left ungrouped in their configured order?
  3. How does a connection get into a group: drag onto the section header, a Move to group item in the row menu,
    or a Group field in the connection form?
  4. Is there always an Ungrouped section, or does the panel hide it while it is empty? When a group is deleted,
    do its connections fall back to Ungrouped?
  5. Does a section header carry a count, and does it remember being collapsed per user?
  6. What should the search box do: flatten the list, or keep the sections and filter within them?
  7. In a narrow sidebar, does the grouped view stand down to the flat list?

Once the shape is settled, the implementation and its tests are a small piece of work.

Activity

  1. nawazish2 commented on Oct 2, 2026

    @nawazish2
    Contributor

    I'd like to take this one. I've shipped a few PRs here (#994, #1122, #1175) and the sidebar and preference-storage side (favorite_connections / connection_order) is territory I can work in.

    I'll wait for the design questions above to be settled before writing code, especially the star-versus-group conflict. Once @cevheri has picked a reading, I'll start with the tests, per the repo's coverage gate. Could this be assigned to me when you're ready?

  2. added theissue type on Oct 2, 2026
  3. cevheri commented on Oct 2, 2026

    @cevheri
    Member

    Thank you @yizhixiaokong for raising this. Twenty connections in one flat list is a real problem, and your proposal to reuse the Favorites shape made the design much easier to settle.

    Thank you @nawazish2 for picking it up, and for waiting on the design before writing code. The issue is assigned to you. Below are the decisions, then the path I would take through the code. When you open the PR, please link this comment in the description as the spec it follows, and add Closes #1170.

    Decisions

    1. The star becomes a mark (reading 2). A starred row stays in its own section and also appears under Favorites. This applies whether or not the user has any groups, so it is one rule everywhere. It intentionally changes today's behaviour, so the test a favorited connection renders once, under Favorites, not duplicated under Connections (tests/components/sidebar/ConnectionsList.test.tsx:352) gets rewritten to pin the new rule, and the PR description should say so.
    2. Seed connections are ordinary rows. No fixed section: they start ungrouped and can be moved into a group like any other connection. Managed rows keep their lock icon.
    3. A Move to group control on the row, built with the existing src/components/ui/dropdown-menu.tsx: it lists the groups, Ungrouped and New group.... No Group field in the connection form, because a managed connection cannot be edited there and membership is a preference, not part of the connection record. Drag onto a section header can come later as a follow-up.
    4. No groups means no visible change in layout: one Connections section, as today. Once at least one group exists, connections without a group render under Ungrouped, and that section is hidden while it is empty. Deleting a group never deletes a connection: its members fall back to Ungrouped.
    5. Each header shows a count and is collapsible, and the collapsed state is stored per user with the groups themselves. A collapsed section still shows its header and count.
    6. Search and narrow sidebar are out of scope. This panel has no search box and no narrow mode today, so there is nothing to adapt.
    7. Reordering the groups themselves is out of scope for this PR. New groups append at the end. Please open a follow-up issue for group reordering once this lands.

    Suggested path, test first at each step

    The closest precedent is #817 (drag-and-drop reordering, #748). It added connection_order and touched the same files this change needs, so it is a good map to read first.

    1. Storage. Add a connection_groups collection in src/lib/storage/types.ts, an ordered array of { id, name, collapsed, connectionIds }, with a docblock that explains why it lives outside DatabaseConnection (the same reason as favorite_connections: managed connections are replaced on every load). Add it to STORAGE_COLLECTIONS, add a getter and setter in src/lib/storage/storage-facade.ts, and remove a deleted connection's id from its group in deleteConnection, next to the existing favorites and order pruning. Wire both places in src/hooks/use-storage-sync.ts that handle connection_order, and update the three docs/STORAGE.md spots that list the collections. Tests: tests/unit/lib/storage/storage-facade.test.ts and tests/isolated/use-storage-sync.test.ts.
    2. A pure section builder. Put the layout logic in src/lib/connection-groups.ts: given the already ordered connections (from applyConnectionOrder), the groups and the favorite ids, return the list of sections to render. Within every section, rows keep the one saved connection_order, exactly as Favorites does today. Unit-test it in tests/unit/lib/connection-groups.test.ts, covering no groups, empty Ungrouped, a stale id in a group, and a starred row in a group. Keeping this pure keeps the component simple and makes 100% coverage easy.
    3. A hook. src/hooks/use-connection-groups.ts, modelled on use-connection-order.ts: create, rename, delete, move a connection, toggle collapsed. A connection belongs to at most one group, so moving it removes it from the previous one. Tests in tests/hooks/.
    4. The list. In src/components/sidebar/ConnectionsList.tsx, render the sections from step 2. Extend SectionHeader with the count and a collapse button with aria-expanded; src/components/ui/collapsible.tsx is available. Rename and Delete for a group go in a small menu on its header, and New group in the panel header. Because a starred row now renders twice, the drag state must record the section as well as the id, otherwise both copies highlight. Dragging stays within one section, generalising today's inSameSection.
    5. The row. Add the Move to group control to src/components/sidebar/ConnectionItem.tsx, with tests in tests/components/sidebar/ConnectionItem.test.tsx.
    6. Wiring. Pass the new props through src/components/sidebar/Sidebar.tsx and both ConnectionsList call sites in src/components/Studio.tsx (desktop and mobile), with tests in tests/components/Studio.test.tsx and tests/components/sidebar/Sidebar.test.tsx.

    Before opening the PR

    Run the gate set from CLAUDE.md (format, lint, typecheck, knip, the four :check scripts, test, build), then bun run test:coverage && bun run coverage:check, which prints any uncovered lines. Please attach before and after screenshots of the panel with two groups, one starred row inside a group, and one collapsed section.

    If any of the above does not fit once you are in the code, say so here before working around it, and we will adjust the decision together.

  4. added a commit that references this issue on Oct 2, 2026
    e94832e
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions