Implement initial UI for OrgExplorer pages#16
Implement initial UI for OrgExplorer pages#16DeveloperAmrit wants to merge 3 commits intoAOSSIE-Org:mainfrom
Conversation
📝 WalkthroughWalkthroughComprehensive migration from Vite-based React application to Next.js framework, including addition of Tailwind CSS, new dashboard pages (Home, Organization, Projects, Discovery, Governance, Profile, Repo), shared components (Navbar, Footer), and reorganization of configuration files for TypeScript, ESLint, and PostCSS. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 9
🤖 Fix all issues with AI agents
In `@src/app/organization/page.tsx`:
- Around line 11-14: The two components OrgHeatMap and OrgActivity inside the
same container render flush; update the parent div (the one wrapping OrgHeatMap
and OrgActivity) to add vertical spacing by applying a Tailwind spacing utility
(e.g., use a vertical spacing class such as space-y-6 or make it a flex-col with
gap-6) so there is consistent gap between OrgHeatMap and OrgActivity.
In `@src/app/profile/page.tsx`:
- Around line 29-43: The labels for "Current Role" and "Email Visibility" are
not associated with their selects; add matching id attributes on the select
elements and htmlFor attributes on the corresponding label elements (e.g., label
htmlFor="currentRole" with select id="currentRole", and label
htmlFor="emailVisibility" with select id="emailVisibility") so the <label> and
<select> pairs in the JSX are properly linked.
- Around line 49-61: The "Connect" items are non-interactive spans and must be
real interactive controls: replace the two <span className="text-[`#8b949e`]
text-xs font-semibold">Connect</span> nodes for Discord and GitLab with <button>
elements (e.g., a ConnectButton or inline button) inside the same parent divs
used in the profile page render (page.tsx), keep existing classes for styling,
add type="button", and include accessible attributes (aria-label describing the
action, and keyboard focus styles) plus onClick handlers that invoke the
appropriate connect logic (or a noop placeholder) so these controls are
keyboard- and screen-reader-accessible.
In `@src/app/projects/page.tsx`:
- Around line 19-21: The Link currently builds its href using
project.name.split('/')[1], which is fragile; change the href to use project.id
instead (i.e., replace the `/repo/${project.name.split('/')[1]}` expression with
`/repo/${project.id}`) and ensure the Link rendering (the JSX element using
project.name) still displays project.name while navigation uses project.id;
update any related usages in the same component that rely on the split pattern.
In `@src/components/Home/RecentActivity.tsx`:
- Line 19: The rendering uses activity.type.replace('_', ' ') which only
replaces the first underscore; update the code in RecentActivity.tsx to replace
all underscores (e.g., change activity.type.replace('_', ' ') to
activity.type.replace(/_/g, ' ') or activity.type.replaceAll('_', ' ')) so
multi-underscore types like "issue_comment_created" become "issue comment
created".
In `@src/components/Home/UserHeatMap.tsx`:
- Around line 3-5: The component calls getLevel() (which uses Math.random())
during render causing unstable colors on every re-render; move random generation
out of the render path by creating a stable heatmapData array once (e.g., in
UserHeatMap using React.useMemo or as a module-level constant) and replace JSX
calls to getLevel() with lookups like heatmapData[weekIndex][dayIndex]; ensure
useMemo dependencies are set so data is created only once for the component
lifecycle and keep the getLevel helper removed or used only inside the
memoization logic.
In `@src/components/Organization/ActiveRepos.tsx`:
- Line 18: In the ActiveRepos component update the displayed text in the JSX
where the repo summary is rendered (the <p> element showing "{repo.issues}
issues • {repo.prs} PRs these week") to correct the typo from "these week" to
"this week" so it reads "{repo.issues} issues • {repo.prs} PRs this week".
In `@src/components/Shared/Footer.tsx`:
- Around line 10-16: The footer currently uses non-semantic, non-focusable
<span> elements in the div with className "flex space-x-6"; replace each <span
className="hover:text-[`#58a6ff`]
cursor-pointer">Term/Privacy/Security/Status/Contact</span> with an accessible
interactive element — either an anchor (<a href="#">...</a>) or Next.js <Link>
wrapping an <a> — preserving the existing classes for styling so the links
remain keyboard-focusable and announced by screen readers; if any link is a
placeholder use href="#" and include descriptive aria-label attributes where
needed.
In `@src/components/Shared/Navbar.tsx`:
- Around line 15-21: Navbar currently hides navigation links on small screens
via the "hidden md:flex" wrapper, leaving no mobile menu; add a responsive
mobile toggle: introduce local state (useState) in the Navbar component to track
an "open" mobile menu, render a hamburger button (with accessible
aria-controls/aria-expanded) visible on small screens (e.g., "md:hidden") that
toggles the state, and conditionally render the links block for small screens
(e.g., a vertical menu or popover when open) while keeping the existing desktop
"hidden md:flex" for larger viewports; ensure Link click handlers close the
mobile menu and include keyboard accessibility (Esc to close) if possible.
🧹 Nitpick comments (17)
src/components/Home/Hero.tsx (1)
1-1: UnnecessaryReactimport.With the new JSX transform (enabled by default in Next.js), you don't need to import
Reactfor JSX to work.♻️ Suggested fix
-import React from 'react' - -const Hero = () => { +const Hero = () => {.gitignore (1)
409-409: Redundant.gitignoreentry.
.next/on line 368 already ignores the Next.js build output directory. This bare.nextentry on line 409 is redundant and can be removed.src/app/globals.css (1)
3-12: Define theme color tokens to avoid hardcoded hex values across components.You define
--backgroundand--foregroundCSS variables here, but every component in this PR hardcodes the same hex values (#0d1117,#161b22,#30363d,#8b949e,#58a6ff,#c9d1d9,#21262d, etc.) directly in Tailwind classes. Consider registering these as Tailwind v4 theme tokens inside the@themeblock so components can use semantic names (e.g.,bg-surface,text-muted,border-default) instead of raw hex codes.This makes future palette changes a single-line edit rather than a find-and-replace across dozens of files.
Example `@theme` extension
`@theme` { + --color-surface: `#161b22`; + --color-canvas: `#0d1117`; + --color-border: `#30363d`; + --color-muted: `#8b949e`; + --color-accent: `#58a6ff`; + --color-fg: `#c9d1d9`; + --color-overlay: `#21262d`; --font-sans: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Arial", "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; }Then use e.g.
bg-surface,text-muted,border-borderin components.src/app/repo/[repoId]/page.tsx (1)
14-21: Tab navigation uses non-interactive<span>elements.These tab-like elements lack semantic meaning and keyboard accessibility. When replacing placeholders with real functionality, use
<button>or<a>elements (or a proper tab component) to ensure keyboard navigation and screen reader support.tsconfig.json (1)
18-18:jsxshould be"preserve"for Next.js projects.Next.js (via SWC/Turbopack) handles JSX transformation itself. The standard Next.js
tsconfig.jsonuses"jsx": "preserve". While"react-jsx"won't break anything with"noEmit": true, it deviates from convention and may cause confusing type-check behavior.Suggested fix
- "jsx": "react-jsx", + "jsx": "preserve",eslint.config.js (1)
6-22: Consider adding@next/eslint-plugin-nextfor Next.js-specific linting.This is a Next.js project but the ESLint config only includes generic TS and React hooks rules. The
@next/eslint-plugin-nextplugin catches common Next.js pitfalls (e.g.,<img>instead ofnext/image, incorrectnext/linkusage, missing metadata). Consider adding it as the project matures.src/components/Home/UserHeatMap.tsx (1)
14-23:<select>elements are non-functional without"use client".Server components cannot handle client-side interactions. These dropdowns are inert as-is. Add
"use client"at the top of the file when wiring up event handlers.src/app/discovery/page.tsx (1)
31-46: Two-column grid lacks a mobile breakpoint.
grid-cols-2will render two narrow columns on small screens. Considergrid-cols-1 md:grid-cols-2for better mobile layout.Suggested fix
- <div className="mt-8 grid grid-cols-2 gap-4"> + <div className="mt-8 grid grid-cols-1 md:grid-cols-2 gap-4">src/components/Organization/OrgActivity.tsx (1)
8-12: Last list item has a trailing bottom border.Every
<li>getsborder-b, including the last one. Addlast:border-b-0to avoid an unnecessary border at the bottom of each list.Proposed fix (apply to both lists)
- <li className="p-2 border-b border-[`#30363d`]">Issue `#101` in Repo A</li> - <li className="p-2 border-b border-[`#30363d`]">Issue `#204` in Repo B</li> - <li className="p-2 border-b border-[`#30363d`]">Issue `#55` in Repo C</li> + <li className="p-2 border-b last:border-b-0 border-[`#30363d`]">Issue `#101` in Repo A</li> + <li className="p-2 border-b last:border-b-0 border-[`#30363d`]">Issue `#204` in Repo B</li> + <li className="p-2 border-b last:border-b-0 border-[`#30363d`]">Issue `#55` in Repo C</li>src/components/Shared/Navbar.tsx (1)
24-28: Add an accessible label to the profile link.Screen readers will announce the link content as "Me" without any context. Adding an
aria-labelimproves accessibility.Proposed fix
- <Link href="/profile" className="hover:text-gray-300 transition-colors"> + <Link href="/profile" className="hover:text-gray-300 transition-colors" aria-label="Profile">src/components/Home/YourIssuesPRs.tsx (2)
26-27: Use Next.jsLink(or abutton) instead of<a href="#">.The rest of the app uses
next/linkfor navigation. Anchor tags withhref="#"cause a scroll-to-top side effect and aren't semantically correct for actions. If these are placeholders for future navigation, useLink; if they'll trigger client-side behavior, use<button>.Also applies to: 51-53
4-57: Consider extracting the duplicated card layout into a shared sub-component.The Issues and PRs panels share nearly identical markup: header with title + action buttons, mapped item list with badge, and a footer link. A small
ItemListCardcomponent acceptingtitle,items,actions, and a render callback would eliminate the duplication and make it easier to add the "Export" button to Issues later (currently only PRs has it).src/app/governance/page.tsx (2)
3-8: Consider simplifying theStatCardborder-color logic.The triple ternary in the className string is correct but hard to scan. A small lookup object would improve readability.
Suggested approach
+const borderColors: Record<'good' | 'bad' | 'neutral', string> = { + bad: 'border-l-[`#f85149`]', + good: 'border-l-[`#3fb950`]', + neutral: 'border-l-[`#8b949e`]', +}; + const StatCard = ({ title, count, type }: { title: string, count: number, type: 'good' | 'bad' | 'neutral' }) => ( - <div className={`p-4 border rounded-md bg-[`#161b22`] shadow-sm ${type === 'bad' ? 'border-l-4 border-l-[`#f85149`] border-[`#30363d`]' : type === 'good' ? 'border-l-4 border-l-[`#3fb950`] border-[`#30363d`]' : 'border-l-4 border-l-[`#8b949e`] border-[`#30363d`]'}`}> + <div className={`p-4 border border-[`#30363d`] border-l-4 ${borderColors[type]} rounded-md bg-[`#161b22`] shadow-sm`}>
1-60: Cross-cutting observation: hardcoded color hex values are repeated across all files.Colors like
#161b22,#30363d,#c9d1d9,#8b949e,#58a6ff,#3fb950, and#f85149appear dozens of times across components. In Tailwind v4, you can define these as theme tokens in your CSS using the@themedirective, then reference them as semantic utilities (e.g.,bg-surface,text-muted,border-subtle). This would make the theme maintainable and reduce the risk of typos or inconsistencies.src/app/layout.tsx (1)
18-18: Consider extracting hardcoded colors to CSS custom properties or Tailwind theme tokens.
#0d1117and#c9d1d9are GitHub's dark-theme colors and are likely reused across many components. Defining them once (e.g., via@themein Tailwind v4 or CSS variables inglobals.css) avoids scattering magic hex values and makes future theme changes a single-point edit.src/components/Home/dummyData.ts (1)
1-22: Consider adding TypeScript interfaces for the mock data shapes.The objects have inconsistent optional fields — e.g.,
issuesitems have eithercreatedorassignedbut not both, andrecentActivity[2]has afromfield unique to that entry. Without explicit types, consuming components may access missing properties without a compile-time warning.Even for dummy data, lightweight interfaces help catch mismatches early:
Example types
interface Activity { id: number; type: string; repo: string; title: string; date: string; from?: string; } interface Mention { id: number; platform: 'GitHub' | 'Discord'; author: string; type: string; title: string; status: 'read' | 'unread'; time: string; } interface Issue { id: number; title: string; repo: string; status: 'open' | 'closed'; created?: string; assigned?: string; } interface PR { id: number; title: string; repo: string; status: 'open' | 'merged' | 'closed'; created: string; }package.json (1)
20-30: Removeeslint-plugin-react-refresh; consider adding Next.js ESLint configuration.
eslint-plugin-react-refresh(line 27) is not Vite-specific—it's bundler-agnostic and designed for Fast Refresh safety checks. However, it's not necessary for Next.js projects since Next.js already enforces Fast Refresh behavior through its own mechanisms. Removing it simplifies the dev dependencies.Additionally, the current custom ESLint config in
eslint.config.jsdoesn't extend any Next.js-specific rules. While the custom flat config is functional, consider either:
- Adding
eslint-config-next(the official Next.js ESLint preset) to get Next.js-specific linting rules and best practices, or- Adding
@next/eslint-plugin-nextdirectly if you prefer a custom configurationNote: Starting with Next.js v16.0.0, the
next lintcommand was removed in favor of using the ESLint CLI directly, so ensure your ESLint setup aligns with current Next.js practices for version 16.1.6.
| <div className="lg:col-span-2"> | ||
| <OrgHeatMap /> | ||
| <OrgActivity /> | ||
| </div> |
There was a problem hiding this comment.
Missing vertical spacing between OrgHeatMap and OrgActivity.
These two components sit inside a plain div with no gap or spacing utility, so they'll render flush against each other. The parent grid provides gap-6 between grid cells but not between siblings within the same cell.
Proposed fix
- <div className="lg:col-span-2">
+ <div className="lg:col-span-2 space-y-6">📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <div className="lg:col-span-2"> | |
| <OrgHeatMap /> | |
| <OrgActivity /> | |
| </div> | |
| <div className="lg:col-span-2 space-y-6"> | |
| <OrgHeatMap /> | |
| <OrgActivity /> | |
| </div> |
🤖 Prompt for AI Agents
In `@src/app/organization/page.tsx` around lines 11 - 14, The two components
OrgHeatMap and OrgActivity inside the same container render flush; update the
parent div (the one wrapping OrgHeatMap and OrgActivity) to add vertical spacing
by applying a Tailwind spacing utility (e.g., use a vertical spacing class such
as space-y-6 or make it a flex-col with gap-6) so there is consistent gap
between OrgHeatMap and OrgActivity.
| <div className="mb-4"> | ||
| <label className="block text-sm font-medium text-[#8b949e] mb-1">Current Role</label> | ||
| <select className="w-full bg-[#0d1117] text-[#c9d1d9] border-[#30363d] rounded-md shadow-sm border p-2"> | ||
| <option>Contributor</option> | ||
| <option>Maintainer</option> | ||
| <option>Admin</option> | ||
| </select> | ||
| </div> | ||
| <div className="mb-4"> | ||
| <label className="block text-sm font-medium text-[#8b949e] mb-1">Email Visibility</label> | ||
| <select className="w-full bg-[#0d1117] text-[#c9d1d9] border-[#30363d] rounded-md shadow-sm border p-2"> | ||
| <option>Public</option> | ||
| <option>Private</option> | ||
| </select> | ||
| </div> |
There was a problem hiding this comment.
Associate <label> elements with their <select> inputs.
The <label> elements lack htmlFor attributes and the <select> elements lack id attributes. Screen readers won't associate them, reducing form accessibility.
Suggested fix (example for one pair)
- <label className="block text-sm font-medium text-[`#8b949e`] mb-1">Current Role</label>
- <select className="w-full bg-[`#0d1117`] text-[`#c9d1d9`] border-[`#30363d`] rounded-md shadow-sm border p-2">
+ <label htmlFor="current-role" className="block text-sm font-medium text-[`#8b949e`] mb-1">Current Role</label>
+ <select id="current-role" className="w-full bg-[`#0d1117`] text-[`#c9d1d9`] border-[`#30363d`] rounded-md shadow-sm border p-2">Apply the same pattern for the "Email Visibility" label/select pair.
🤖 Prompt for AI Agents
In `@src/app/profile/page.tsx` around lines 29 - 43, The labels for "Current Role"
and "Email Visibility" are not associated with their selects; add matching id
attributes on the select elements and htmlFor attributes on the corresponding
label elements (e.g., label htmlFor="currentRole" with select id="currentRole",
and label htmlFor="emailVisibility" with select id="emailVisibility") so the
<label> and <select> pairs in the JSX are properly linked.
| <div className="flex items-center justify-between p-3 bg-[#0d1117] rounded border border-[#30363d]"> | ||
| <span className="font-medium text-sm text-[#c9d1d9]">GitHub</span> | ||
| <span className="text-[#3fb950] text-xs font-semibold">Connected</span> | ||
| </div> | ||
| <div className="flex items-center justify-between p-3 bg-[#0d1117] rounded border border-[#30363d]"> | ||
| <span className="font-medium text-sm text-[#c9d1d9]">Discord</span> | ||
| <span className="text-[#8b949e] text-xs font-semibold">Connect</span> | ||
| </div> | ||
| <div className="flex items-center justify-between p-3 bg-[#0d1117] rounded border border-[#30363d]"> | ||
| <span className="font-medium text-sm text-[#c9d1d9]">GitLab</span> | ||
| <span className="text-[#8b949e] text-xs font-semibold">Connect</span> | ||
| </div> | ||
| </div> |
There was a problem hiding this comment.
"Connect" actions should be interactive elements.
The "Connect" text on lines 55 and 59 appears clickable but uses <span>, making it inaccessible to keyboard and screen reader users. Use <button> elements instead.
Suggested fix
- <span className="text-[`#8b949e`] text-xs font-semibold">Connect</span>
+ <button className="text-[`#8b949e`] text-xs font-semibold hover:text-[`#58a6ff`] bg-transparent border-none cursor-pointer">Connect</button>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <div className="flex items-center justify-between p-3 bg-[#0d1117] rounded border border-[#30363d]"> | |
| <span className="font-medium text-sm text-[#c9d1d9]">GitHub</span> | |
| <span className="text-[#3fb950] text-xs font-semibold">Connected</span> | |
| </div> | |
| <div className="flex items-center justify-between p-3 bg-[#0d1117] rounded border border-[#30363d]"> | |
| <span className="font-medium text-sm text-[#c9d1d9]">Discord</span> | |
| <span className="text-[#8b949e] text-xs font-semibold">Connect</span> | |
| </div> | |
| <div className="flex items-center justify-between p-3 bg-[#0d1117] rounded border border-[#30363d]"> | |
| <span className="font-medium text-sm text-[#c9d1d9]">GitLab</span> | |
| <span className="text-[#8b949e] text-xs font-semibold">Connect</span> | |
| </div> | |
| </div> | |
| <div className="flex items-center justify-between p-3 bg-[`#0d1117`] rounded border border-[`#30363d`]"> | |
| <span className="font-medium text-sm text-[`#c9d1d9`]">GitHub</span> | |
| <span className="text-[`#3fb950`] text-xs font-semibold">Connected</span> | |
| </div> | |
| <div className="flex items-center justify-between p-3 bg-[`#0d1117`] rounded border border-[`#30363d`]"> | |
| <span className="font-medium text-sm text-[`#c9d1d9`]">Discord</span> | |
| <button className="text-[`#8b949e`] text-xs font-semibold hover:text-[`#58a6ff`] bg-transparent border-none cursor-pointer">Connect</button> | |
| </div> | |
| <div className="flex items-center justify-between p-3 bg-[`#0d1117`] rounded border border-[`#30363d`]"> | |
| <span className="font-medium text-sm text-[`#c9d1d9`]">GitLab</span> | |
| <button className="text-[`#8b949e`] text-xs font-semibold hover:text-[`#58a6ff`] bg-transparent border-none cursor-pointer">Connect</button> | |
| </div> | |
| </div> |
🤖 Prompt for AI Agents
In `@src/app/profile/page.tsx` around lines 49 - 61, The "Connect" items are
non-interactive spans and must be real interactive controls: replace the two
<span className="text-[`#8b949e`] text-xs font-semibold">Connect</span> nodes for
Discord and GitLab with <button> elements (e.g., a ConnectButton or inline
button) inside the same parent divs used in the profile page render (page.tsx),
keep existing classes for styling, add type="button", and include accessible
attributes (aria-label describing the action, and keyboard focus styles) plus
onClick handlers that invoke the appropriate connect logic (or a noop
placeholder) so these controls are keyboard- and screen-reader-accessible.
| <Link href={`/repo/${project.name.split('/')[1]}`} className="font-semibold text-[#58a6ff] hover:underline text-lg"> | ||
| {project.name} | ||
| </Link> |
There was a problem hiding this comment.
Use project.id for the route instead of splitting project.name.
project.name.split('/')[1] is fragile — if the name format changes or lacks a /, this silently produces /repo/undefined. The id field already exists for exactly this purpose.
Suggested fix
- <Link href={`/repo/${project.name.split('/')[1]}`} className="font-semibold text-[`#58a6ff`] hover:underline text-lg">
+ <Link href={`/repo/${project.id}`} className="font-semibold text-[`#58a6ff`] hover:underline text-lg">📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <Link href={`/repo/${project.name.split('/')[1]}`} className="font-semibold text-[#58a6ff] hover:underline text-lg"> | |
| {project.name} | |
| </Link> | |
| <Link href={`/repo/${project.id}`} className="font-semibold text-[`#58a6ff`] hover:underline text-lg"> | |
| {project.name} | |
| </Link> |
🤖 Prompt for AI Agents
In `@src/app/projects/page.tsx` around lines 19 - 21, The Link currently builds
its href using project.name.split('/')[1], which is fragile; change the href to
use project.id instead (i.e., replace the `/repo/${project.name.split('/')[1]}`
expression with `/repo/${project.id}`) and ensure the Link rendering (the JSX
element using project.name) still displays project.name while navigation uses
project.id; update any related usages in the same component that rely on the
split pattern.
| </div> | ||
| <div> | ||
| <p className="text-[#c9d1d9]"> | ||
| <span className="font-semibold">{activity.type.replace('_', ' ')}</span>: {activity.title} |
There was a problem hiding this comment.
replace('_', ' ') only replaces the first underscore.
String.prototype.replace with a string argument replaces only the first match. If an activity type like issue_comment_created is added, it would render as "issue comment_created". Use a global replace instead.
Proposed fix
- <span className="font-semibold">{activity.type.replace('_', ' ')}</span>: {activity.title}
+ <span className="font-semibold">{activity.type.replaceAll('_', ' ')}</span>: {activity.title}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <span className="font-semibold">{activity.type.replace('_', ' ')}</span>: {activity.title} | |
| <span className="font-semibold">{activity.type.replaceAll('_', ' ')}</span>: {activity.title} |
🤖 Prompt for AI Agents
In `@src/components/Home/RecentActivity.tsx` at line 19, The rendering uses
activity.type.replace('_', ' ') which only replaces the first underscore; update
the code in RecentActivity.tsx to replace all underscores (e.g., change
activity.type.replace('_', ' ') to activity.type.replace(/_/g, ' ') or
activity.type.replaceAll('_', ' ')) so multi-underscore types like
"issue_comment_created" become "issue comment created".
| const UserHeatMap = () => { | ||
| // varied colors for heatmap | ||
| const getLevel = () => Math.floor(Math.random() * 5); |
There was a problem hiding this comment.
Math.random() called during render will produce unstable output in a client component.
getLevel() is invoked per cell on every render (371 calls). In a server component this renders once, but once you add "use client" for interactivity (the <select> elements need it), the heatmap colors will randomly change on every re-render. Generate the data once outside the render path (e.g., via useMemo or a module-level constant).
Suggested approach
+'use client';
import React from 'react';
+import { useMemo } from 'react';
const UserHeatMap = () => {
- const getLevel = () => Math.floor(Math.random() * 5);
+ const heatmapData = useMemo(
+ () => Array.from({ length: 53 }, () =>
+ Array.from({ length: 7 }, () => Math.floor(Math.random() * 5))
+ ),
+ []
+ );
const colors = ['bg-[`#161b22`]', 'bg-[`#0e4429`]', 'bg-[`#006d32`]', 'bg-[`#26a641`]', 'bg-[`#39d353`]'];Then reference heatmapData[weekIndex][dayIndex] instead of calling getLevel() in the JSX.
🤖 Prompt for AI Agents
In `@src/components/Home/UserHeatMap.tsx` around lines 3 - 5, The component calls
getLevel() (which uses Math.random()) during render causing unstable colors on
every re-render; move random generation out of the render path by creating a
stable heatmapData array once (e.g., in UserHeatMap using React.useMemo or as a
module-level constant) and replace JSX calls to getLevel() with lookups like
heatmapData[weekIndex][dayIndex]; ensure useMemo dependencies are set so data is
created only once for the component lifecycle and keep the getLevel helper
removed or used only inside the memoization logic.
| <div key={repo.name} className="flex items-center justify-between p-3 border border-[#30363d] rounded hover:bg-[#21262d]"> | ||
| <div> | ||
| <h3 className="text-sm font-semibold text-[#58a6ff]">{repo.name}</h3> | ||
| <p className="text-xs text-[#8b949e]">{repo.issues} issues • {repo.prs} PRs these week</p> |
There was a problem hiding this comment.
Typo: "these week" → "this week".
Proposed fix
- <p className="text-xs text-[`#8b949e`]">{repo.issues} issues • {repo.prs} PRs these week</p>
+ <p className="text-xs text-[`#8b949e`]">{repo.issues} issues • {repo.prs} PRs this week</p>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <p className="text-xs text-[#8b949e]">{repo.issues} issues • {repo.prs} PRs these week</p> | |
| <p className="text-xs text-[`#8b949e`]">{repo.issues} issues • {repo.prs} PRs this week</p> |
🤖 Prompt for AI Agents
In `@src/components/Organization/ActiveRepos.tsx` at line 18, In the ActiveRepos
component update the displayed text in the JSX where the repo summary is
rendered (the <p> element showing "{repo.issues} issues • {repo.prs} PRs these
week") to correct the typo from "these week" to "this week" so it reads
"{repo.issues} issues • {repo.prs} PRs this week".
| <div className="flex space-x-6"> | ||
| <span className="hover:text-[#58a6ff] cursor-pointer">Terms</span> | ||
| <span className="hover:text-[#58a6ff] cursor-pointer">Privacy</span> | ||
| <span className="hover:text-[#58a6ff] cursor-pointer">Security</span> | ||
| <span className="hover:text-[#58a6ff] cursor-pointer">Status</span> | ||
| <span className="hover:text-[#58a6ff] cursor-pointer">Contact</span> | ||
| </div> |
There was a problem hiding this comment.
Footer links are not accessible — use <a> or <button> instead of <span>.
These <span> elements look clickable (cursor-pointer, hover styles) but are not focusable via keyboard and have no semantic role. Screen readers and keyboard users cannot interact with them.
Even as placeholders, use <a href="#"> (or Next.js <Link>) so they are natively focusable and announced as links.
Suggested fix
- <span className="hover:text-[`#58a6ff`] cursor-pointer">Terms</span>
- <span className="hover:text-[`#58a6ff`] cursor-pointer">Privacy</span>
- <span className="hover:text-[`#58a6ff`] cursor-pointer">Security</span>
- <span className="hover:text-[`#58a6ff`] cursor-pointer">Status</span>
- <span className="hover:text-[`#58a6ff`] cursor-pointer">Contact</span>
+ <a href="#" className="hover:text-[`#58a6ff`]">Terms</a>
+ <a href="#" className="hover:text-[`#58a6ff`]">Privacy</a>
+ <a href="#" className="hover:text-[`#58a6ff`]">Security</a>
+ <a href="#" className="hover:text-[`#58a6ff`]">Status</a>
+ <a href="#" className="hover:text-[`#58a6ff`]">Contact</a>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <div className="flex space-x-6"> | |
| <span className="hover:text-[#58a6ff] cursor-pointer">Terms</span> | |
| <span className="hover:text-[#58a6ff] cursor-pointer">Privacy</span> | |
| <span className="hover:text-[#58a6ff] cursor-pointer">Security</span> | |
| <span className="hover:text-[#58a6ff] cursor-pointer">Status</span> | |
| <span className="hover:text-[#58a6ff] cursor-pointer">Contact</span> | |
| </div> | |
| <div className="flex space-x-6"> | |
| <a href="#" className="hover:text-[`#58a6ff`]">Terms</a> | |
| <a href="#" className="hover:text-[`#58a6ff`]">Privacy</a> | |
| <a href="#" className="hover:text-[`#58a6ff`]">Security</a> | |
| <a href="#" className="hover:text-[`#58a6ff`]">Status</a> | |
| <a href="#" className="hover:text-[`#58a6ff`]">Contact</a> | |
| </div> |
🤖 Prompt for AI Agents
In `@src/components/Shared/Footer.tsx` around lines 10 - 16, The footer currently
uses non-semantic, non-focusable <span> elements in the div with className "flex
space-x-6"; replace each <span className="hover:text-[`#58a6ff`]
cursor-pointer">Term/Privacy/Security/Status/Contact</span> with an accessible
interactive element — either an anchor (<a href="#">...</a>) or Next.js <Link>
wrapping an <a> — preserving the existing classes for styling so the links
remain keyboard-focusable and announced by screen readers; if any link is a
placeholder use href="#" and include descriptive aria-label attributes where
needed.
| <div className="hidden md:flex space-x-6 text-sm font-semibold"> | ||
| <Link href="/" className="hover:text-gray-300 transition-colors">Home</Link> | ||
| <Link href="/organization" className="hover:text-gray-300 transition-colors">Organization</Link> | ||
| <Link href="/projects" className="hover:text-gray-300 transition-colors">Projects</Link> | ||
| <Link href="/discovery" className="hover:text-gray-300 transition-colors">Discovery</Link> | ||
| <Link href="/governance" className="hover:text-gray-300 transition-colors">Governance</Link> | ||
| </div> |
There was a problem hiding this comment.
No mobile navigation — links are completely hidden on small screens.
hidden md:flex hides all nav links below the md breakpoint with no hamburger menu or alternative. Users on mobile devices can only reach Home (via logo) and Profile, but not Organization, Projects, Discovery, or Governance.
Consider adding a mobile menu toggle (e.g., a hamburger button that reveals links) to ensure all pages remain accessible on smaller viewports.
🤖 Prompt for AI Agents
In `@src/components/Shared/Navbar.tsx` around lines 15 - 21, Navbar currently
hides navigation links on small screens via the "hidden md:flex" wrapper,
leaving no mobile menu; add a responsive mobile toggle: introduce local state
(useState) in the Navbar component to track an "open" mobile menu, render a
hamburger button (with accessible aria-controls/aria-expanded) visible on small
screens (e.g., "md:hidden") that toggles the state, and conditionally render the
links block for small screens (e.g., a vertical menu or popover when open) while
keeping the existing desktop "hidden md:flex" for larger viewports; ensure Link
click handlers close the mobile menu and include keyboard accessibility (Esc to
close) if possible.
Addressed Issues:
Fixes #15
Screenshots/Recordings:
Preview - https://org-explorer-two.vercel.app/
Additional Notes:
Description
This PR introduces the core UI architecture for the OrgExplorer application. It implements the key pages and components outlined in the project requirements, establishing the visual structure and navigation flow. The interface is built with Next.js and Tailwind CSS, designed with a GitHub-inspired dark theme for consistency with the developer environment.
Changes
Provides a high-level overview of the organization's health.
Helps users find interesting content.
Monitoring dashboard for project health and compliance.
Checklist
Summary by CodeRabbit
New Features
Refactor
Chores