--mention-text purple for hashtags, real bg-blue-50/65 tint, real share dialog layout. v1–v3 are kept for history.
NavGroups section above Pinned (same Collapsible pattern as NavFolders / NavHashtags). Existing Globe-icon indicator on hashtag rows changes to the owning group's icon if the tag has defaultGroupId; tags without a group keep the Globe (when shared) or nothing (when private). Nav-main, Folders, Pinned, Mentions sections unchanged.
border-t · bg-blue-50/65 tint when shared
Sprint review moved to Thursday — board prep conflict.
Lattice intro call. They build the same hashtag capture as us, but scoped to HR. #competitor for sure — they pitched at SHRM. Could also be #customer for OEM-ing the editor.
Pushed sprint review to Thursday. Pinged @jacob + @david to confirm. #design
Sprint review moved to Thursday — board prep conflict.
Lattice intro call. They build the same hashtag capture as us, but scoped to HR. IF#competitor for sure — they pitched at SHRM. Could also be IF#customer for OEM-ing the editor.
#competitor, #customer
Pushed sprint review to Thursday. Pinged @jacob + @david to confirm. IF#design
#design
--mention-text). For team-owned hashtags, a 10×10px group glyph is prepended via inline-flex — no color change to the tag itself. Tint stays exactly as commit bb2747a shipped it (bg-blue-50/65). New note-foot row appears ONLY on tinted notes, showing which groups and which hashtags drive the share. Untinted notes (private) look identical to today.
Create a group to share streams of notes with people
defaultGroupId set to this group. Notes you write with these auto-share to IdeaFlow Team.defaultGroupId. Tag name itself stays purple (real --mention-text). Private tags (no group) get a grey Hash icon instead of purple — visual signal that they're not shared anywhere.
Sheet on mobile (sidebar.tsx:207). Width 18rem.
Lattice intro. IF#competitor — could OEM editor.
#competitor
Sprint review → Thursday. @jacob confirm. IF#design
#design
| File / component | Today | With Groups | Δ size |
|---|---|---|---|
app-sidebar.tsx |
5 sections in <SidebarContent> (NavAuthorPublicHashtags, NavPinnedNotes, NavFolders, NavHashtags, NavMentions, NavReferencedNotes) |
+1 import, +1 line: <NavGroups /> first child of SidebarContent |
2 lines |
nav-groups.tsx (new) |
— | New component, copies NavFolders pattern: Collapsible + SidebarGroup + sticky label + chevron + plus action + SidebarMenu of GroupRow children | ~180 lines |
nav-hashtags.tsx · row |
Hash icon + name + (Globe if shared) + count badge + action menu | Hash icon + name + (group-glyph if defaultGroupId set, else Globe if shared, else nothing) + count + menu (+ "Add to group" item) |
~12 lines |
note-share-dialog.tsx |
Input "Add people by email" → user-search dropdown → "People with access" list | Input "Add people or groups" → unified search (users + groups) → new "Groups with access" section above People → People shows "Inherited" tag for transitive-via-group | ~80 lines |
HashtagMark.ts · render |
renderHTML returns <span class="hashtag"> |
Add optional data-group-id attr; CSS handles glyph injection. ProseMirror renderer extension already supports decorating marks with extra attrs. |
~10 lines |
tiptap.css · .hashtag |
.hashtag { color: var(--mention-text); } |
Add .hashtag[data-group-id]::before rendering a small group icon via background-image (or inline-flex wrapper if we accept HashtagMark refactor) |
~15 lines |
notes.tsx · tint check |
note.isShared || hashtagStore.noteHasSharedHashtag(id) |
Add: || noteSharingStore.isInAnyGroup(id). Plus render the new note-foot row showing groups + reasons. |
~30 lines |
schema.prisma |
enum PrincipalType { EMAIL ANONYMOUS } |
Add GROUP to enum. New Group + GroupMember models. Add SharedHashtag.defaultGroupId String?. |
~45 lines |
note-sharing-service.ts |
Validates EMAIL + ANONYMOUS principal types | Add GROUP branch with comment explaining why this principalType is safe to add (group IDs are server-issued, no race) | ~25 lines |
search-service.ts · getVisibilityWhere |
Branches on caller's email for direct + hashtag grants | Add 3rd branch: caller's GroupMember rows → NoteSharing(GROUP, group_id) matches |
~40 lines |
routes.ts |
Sharing routes mounted | Mount new /groups + /groups/:id/members + /groups/:id/notes routes |
~12 lines |
| Total new + modified | 5 new files, ~450 lines added, 12 existing files touched |
mockups/groups-v4.html · grounded in the actual app code · v1–v3 untouched.