Repository navigation
UX review pass — Wave 5: clarity, honesty, componentization - #43
Merged
Merged
Conversation
Splits the overloaded .meta block into two visually separated clusters: .topbar-status (sync + refresh + summary + rate-low) and .topbar-actions (help + logout). The rate-limit now only renders inline when low; when healthy it lives in the sync-indicator tooltip so the bar stays calm. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ark-read The review-requested row had ✓/✗ stubs that silently opened the modal instead of approving. Now they open the modal with a pendingAction that DetailModal fires once the PR detail loads (approve submits immediately; request-changes jumps to the composer for the required body). The mentioned "Mark read" stub is now an honest snooze with a clear tooltip. Plumbing: ScopeProps.onOpenItemWithAction → NeedsScope → AttentionRow → HomeShell.selectItemWithAction → DetailModal.pendingAction. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Snoozing a row now shows an inline "Snoozed 18h · Undo" toast for 5s. The toast sits above the faded row (pointer-events: auto overrides the snoozed none) and calls unsnoozePr + refresh on click. Plumbing adds onUnsnoozeItem through ScopeProps → NeedsScope → AttentionRow. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Replaces the ambiguous unicode icons (● ◔ ↻ ◈ ∿ ★ ▴ ⊞ ◉ ◆ ◇) with react-icons/md (MdInbox, MdNotificationsActive, MdRefresh, MdReport, MdDashboard, MdStar, MdTrendingUp, MdFolder, MdPerson, MdGroup, MdGroupWork). Same weight, conventional meanings. ItemDef.icon is now ReactNode instead of string. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Splits the 8 flat stat cards into two tiers: 4 primary (active, open PRs, failing CI, stale PRs) at full size, and 4 secondary (total repos, merged, avg time, pinned) compact and borderless. Failing/stale keep the warn border. Responsive: 4→2 columns under 720px. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…only Pinned used to add +20 to the signal score, pushing a quiet pinned repo to 'attention' alongside repos with failing CI. Now pinned only adds a reason tag and lifts a quiet repo to 'active' (not 'attention'), so the critical/attention levels stay reserved for real signals. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Adds a Write/Preview tab toggle to the PR comment composer. Preview renders the draft through a minimal inline markdown→HTML converter (headers, bold, italic, code, links, lists, blockquote) piped through SanitizedMarkdown — no new dependency. Preview is disabled when the body is empty. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Splits the files touched in this branch into focused, reusable units: - miniMarkdown → src/utils/miniMarkdown.ts (shared util) - Composer → src/components/home/detail/Composer.tsx (self-contained) - computeDigest + types → src/components/home/scopes/digestMath.ts - DigestStat/DigestAttn/Sparkline → src/components/home/scopes/DigestParts.tsx - ReasonChips/actionsFor/ActionDef → src/components/home/rowParts.tsx - syncTitle/timeAgoShort → src/utils/topbar.ts LOC reductions: DetailModalBody: 275 → 140 DigestScope: 307 → 168 AttentionRow: 182 → 112 Dashboard: 285 → 251 All extracted modules are reusable (RowProps shared by AttentionRow + other scopes; miniMarkdown usable anywhere; DigestParts presentational). Lint clean, build green. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Replaces 14 plain <div className="hs-empty"> blocks with a shared EmptyState component that supports an icon, title, description, and optional CTA button. Key improvements: - Needs me: icon + "Browse open PRs" CTA when empty - Pinned: icon + "Browse repos" CTA when empty - Issues/Notifications/Since: icon + contextual description - Error states use tone="danger" for red title - All filter-no-match states get "Try clearing the filter" hint EmptyState is reusable (presentational, no domain logic). CSS updated with flex column layout, icon opacity, and CTA hover styles. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
P2.10 — Focus trap for the mobile sidebar drawer: - New useFocusTrap hook (src/hooks/useFocusTrap.ts) traps Tab/Shift+Tab inside the sidebar while open, focuses the first element on open, restores focus to the toggle button on close, and closes on Escape. - Removed the redundant keydown handler on the backdrop (the hook handles Escape on the container). Responsive pass (860px + 480px breakpoints): - Topbar: wraps status/actions, hides verbose summary + QS trigger text, pads left for the floating ≡ button - Rows: stack title/meta + actions vertically on narrow - Issue/notification groups: tighter padding - Digest: less horizontal padding, smaller headings - Modal: horizontal-scroll tabs, tighter header/footer padding - Composer: smaller textarea, wrapping actions - Relationships table: wrapped in scrollable .rel-table-wrap - 480px: hide sparklines, branch badges, kbd hints; 2-col stat cards Also migrated remaining empty states (Repos, Relationships, Digest sections) to the shared EmptyState component. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ests Four refactors in one pass, all preserving existing imports via barrels: **demo-data.ts (727 → 4 LOC barrel)** → src/api/demo/helpers.ts (215) — shared builders: ago, ghAvatar, pr, makeRepo, fullPR, issue, notif, mergedPR, deploy → src/api/demo/github.ts (421) — all GitHub demo data → src/api/demo/sentry.ts (34) — Sentry demo data → src/api/demo/vercel.ts (63) — Vercel demo data **ui.tsx (323 → 5 LOC barrel)** → src/components/ui/Skeletons.tsx (84) — Skeleton, CardSkeleton, ListSkeleton, Spinner, Pulse → src/components/ui/Motion.tsx (120) — FadeIn, SlideIn, Stagger, StaggerItem, PageTransition, TabTransition → src/components/ui/Primitives.tsx (122) — Avatar, Badge, Button, Input, Flex, Divider **SentryConnector.tsx (350 → 198 LOC)** → src/components/connectors/sentry/SetupForm.tsx (114) — credentials form + describeError helper → src/components/connectors/sentry/ProjectMappingList.tsx (50) — presentational mapping list → src/components/connectors/sentry/IssueTestPanel.tsx (26) — test-issues result panel → src/components/connectors/sentry/types.ts (2) — shared Async<T> type **useViewerData.ts (254 → 145 LOC)** → src/hooks/loadRepos.ts (156) — pure sortRepos, mergeOrgs, syncRepos (testable) → src/hooks/loadRepos.test.ts (96) — 7 new tests for sortRepos + mergeOrgs All gates: tsc ✓, eslint ✓, vitest 71/71 ✓, vite build ✓ Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- SettingsTab.tsx (282→96 LOC): extract AppearanceSection, PinnedPanel, StoragePanel into src/components/settings/ - QuickSwitcher.tsx (251→124 LOC): extract buildItems, matchScore, kindLabel, VIEWS/SCOPES into quickSwitcherData.ts (+13 tests) - CSS audit: remove 244 dead rules across styles.css (-841), home.css (-182), ui.css (-210). CSS bundle 106.47→104.12 kB. Dynamic class constructions protected via manual verification. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Wave 5 UX review pass — 9 UX improvements + 1 refactor commit. All items from the systematic review are now complete.
UX improvements
.metainto.topbar-status(sync + refresh + summary + rate-low) and.topbar-actions(help + logout); rate-limit only renders inline when low, otherwise lives in the sync-indicator tooltippendingActionthat fires once the PR loads (approve submits; request-changes jumps to composer). "Mark read" on mentioned rows is now an honest snooze with a clear tooltip — no more dead stubspointer-events: autooverrides the faded row so the button stays clickablereact-icons/md(MdInbox, MdNotificationsActive, MdRefresh, MdReport, MdDashboard, MdStar, MdTrendingUp, MdFolder)active(notattention), so critical/attention stay reserved for real signalsEmptyStatecomponent (icon + title + description + optional CTA button) replaces 14 plainhs-emptydivs across all scopes. Needs me gets "Browse open PRs →", Pinned gets "Browse repos →", error states usetone="danger"useFocusTraphook traps Tab/Shift+Tab in the mobile sidebar drawer, focuses first element on open, restores focus on close, Escape closes. Responsive 860px + 480px breakpoints: topbar wraps, rows stack, modal tabs scroll horizontally, relationships table scrolls, sparklines/branch badges/kbd hints hide at 480pxRefactor — componentization
Extracted 7 reusable modules to keep files under 300 LOC:
utils/miniMarkdown.tsutils/topbar.tshooks/useFocusTrap.tshome/EmptyState.tsxhome/detail/Composer.tsxhome/scopes/digestMath.tshome/scopes/DigestParts.tsxhome/rowParts.tsxLOC reductions in existing files:
DetailModalBody.tsx: 275 → 140DigestScope.tsx: 307 → 168AttentionRow.tsx: 182 → 112Dashboard.tsx: 285 → 251Test plan
npm run lint— cleannpm run build— green (tsc -b && vite build)Generated with Devin