refactor(credits-page): standardized styling and added pagination - #217
Conversation
📝 WalkthroughWalkthroughAdds a reusable Pagination component with keyboard navigation and integrates client-side pagination (PAGE_SIZE=10) into Contributors and Dependency credits tables; introduces responsive table CSS modules and minor static-table structural/styling tweaks. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Pagination
participant CreditsCard
participant DataSource
User->>Pagination: click page button / press Arrow key
Pagination->>CreditsCard: onChange(newPage)
CreditsCard->>CreditsCard: compute start = page * PAGE_SIZE
CreditsCard->>DataSource: request/render rows for start..start+PAGE_SIZE-1
CreditsCard->>User: render table rows for current page
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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: 1
🤖 Fix all issues with AI agents
In @src/pages/Credits/ContributorsCreditsCard.jsx:
- Around line 48-50: Update the pluralization check for contributor counts in
the ContributorsCreditsCard rendering: replace the current conditional that uses
c.contributions > 1 with a check for exactly one (c.contributions === 1) so that
only a single contribution renders "commit" and all other values (including 0)
render "commits"; make this change where the JSX outputs "{c.contributions} ..."
for variable c.contributions.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
|
Hi @laxitajain. Thank you for this change - it is worth having. Since this is such a small PR and I intended to create an issue for a full refactor of this page, would you be interested in updating this PR to do that? It involves ensuring that the styles on the credits page are consistent with the rest of the pages and adding pagination to the tables (since they've grown a lot since the creation of the page and dynamic fetches can be slow). Below is the main problem, the
|
|
sure, will be working on this refactor then! |
Great. I'll create an issue for it now. You can start work on it so long if you'd like - I've already explained the basics. |
|
@laxitajain, I just added #218 - comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In @src/components/Pagination.jsx:
- Around line 18-30: The global keydown handler in the Pagination component's
useEffect (handler) acts on ArrowLeft/ArrowRight without checking the event
target, which breaks arrow key usage inside inputs/textareas/contenteditable
elements; update handler to ignore events when the active/target element is an
input, textarea, select, or has isContentEditable true (or when an element with
role textbox is focused) before running onChange(page ± 1), keeping the existing
page, totalPages and onChange logic intact.
In @src/pages/Credits/ContributorsCreditsCard.jsx:
- Line 1: The import statement in ContributorsCreditsCard.jsx imports useEffect
but it is unused; update the React import to remove useEffect (keep useState) so
the import reads only the hooks actually used, ensuring no other references to
useEffect remain in the ContributorsCreditsCard component.
- Line 54: The cell currently hardcodes "commits" causing incorrect grammar for
a single contribution; update the rendering in ContributorsCreditsCard.jsx to
conditionally use "commit" vs "commits" based on c.contributions (e.g.,
c.contributions === 1 ? 'commit' : 'commits') or extract a small helper like
formatContributions(contributions) that returns the correctly pluralized string
and use it where the JSX presently renders "<td>{c.contributions} commits</td>".
🧹 Nitpick comments (3)
src/pages/Credits/StaticCreditsCard.jsx (1)
43-43: Fix inconsistent spacing around the dash."Pixel Art Hedgehog- By" has the dash attached to "Hedgehog" with no space before it, but a space after the dash before "By". This creates inconsistent visual spacing.
✨ Proposed fix for consistent spacing
- Pixel Art Hedgehog- By{' '} + Pixel Art Hedgehog - By{' '}This provides balanced spacing on both sides of the dash separator.
src/components/Pagination.jsx (1)
18-30: Consider documenting onChange stability requirement.The
onChangecallback is included in theuseEffectdependency array. If parent components don't provide a stable reference (e.g., passing an inline arrow function), the keyboard listener will be removed and re-added on every render.Current usage in this PR passes
setStatefunctions directly, which are stable. However, for future maintainability, consider adding a JSDoc comment documenting thatonChangeshould be a stable reference.📝 Optional: Add JSDoc to document prop requirements
+/** + * Pagination component with keyboard navigation support. + * @param {Object} props + * @param {number} props.page - Current page index (0-based) + * @param {number} props.totalPages - Total number of pages + * @param {Function} props.onChange - Callback when page changes (should be stable/memoized) + */ export default function Pagination({ page, totalPages, onChange }) {src/pages/Credits/DependencyCreditsCard.module.css (1)
4-4: Remove!importantdeclarations and resolve specificity conflicts.The
!importantflags on width properties indicate specificity issues. CSS modules already provide scoping, so these shouldn't be necessary. Using!importantmakes the styles harder to maintain and debug.🧹 Suggested approach to resolve
- Remove the
!importantdeclarations- If styles don't apply correctly, investigate competing styles:
- Check for global table styles
- Check if parent components (like
GlassCard) override table widths- Use browser DevTools to identify which styles are conflicting
.table { margin-left: auto; margin-right: auto; - width: 80% !important; + width: 80%; min-width: 80%; table-layout: fixed; } @media (max-width: 600px) { .table { - width: 100% !important; + width: 100%; min-width: 100%; table-layout: fixed; }Also applies to: 44-44
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
src/components/Pagination.jsxsrc/components/Pagination.module.csssrc/pages/Credits/ContributorsCreditsCard.jsxsrc/pages/Credits/Credits.module.csssrc/pages/Credits/DependencyCreditsCard.jsxsrc/pages/Credits/DependencyCreditsCard.module.csssrc/pages/Credits/StaticCreditsCard.jsxsrc/pages/Credits/StaticCreditsCard.module.css
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Ryan-Millard
Repo: Ryan-Millard/Img2Num PR: 217
File: src/pages/Credits/ContributorsCreditsCard.jsx:48-50
Timestamp: 2026-01-09T14:45:56.443Z
Learning: In src/pages/Credits/ContributorsCreditsCard.jsx, the contributor data comes from GitHub's /contributors API endpoint (via scripts/generate-contributor-credits-json.js), which only returns contributors with at least one contribution. Therefore, c.contributions will always be >= 1 and the zero case is impossible.
📚 Learning: 2026-01-09T14:45:56.443Z
Learnt from: Ryan-Millard
Repo: Ryan-Millard/Img2Num PR: 217
File: src/pages/Credits/ContributorsCreditsCard.jsx:48-50
Timestamp: 2026-01-09T14:45:56.443Z
Learning: In src/pages/Credits/ContributorsCreditsCard.jsx, the contributor data comes from GitHub's /contributors API endpoint (via scripts/generate-contributor-credits-json.js), which only returns contributors with at least one contribution. Therefore, c.contributions will always be >= 1 and the zero case is impossible.
Applied to files:
src/pages/Credits/DependencyCreditsCard.jsxsrc/pages/Credits/StaticCreditsCard.jsxsrc/pages/Credits/ContributorsCreditsCard.jsx
🧬 Code graph analysis (3)
src/pages/Credits/DependencyCreditsCard.jsx (3)
src/pages/Credits/ContributorsCreditsCard.jsx (1)
page(17-17)src/components/Tooltip.jsx (1)
Tooltip(5-35)src/components/Pagination.jsx (1)
Pagination(16-88)
src/pages/Credits/StaticCreditsCard.jsx (2)
src/components/GlassCard.jsx (1)
GlassCard(5-9)src/components/Tooltip.jsx (1)
Tooltip(5-35)
src/pages/Credits/ContributorsCreditsCard.jsx (4)
src/components/Pagination.jsx (2)
i(9-9)Pagination(16-88)src/components/GlassCard.jsx (1)
GlassCard(5-9)src/components/Tooltip.jsx (1)
Tooltip(5-35)src/components/FallbackImage.jsx (1)
FallbackImage(10-19)
🪛 GitHub Actions: CI
src/pages/Credits/ContributorsCreditsCard.jsx
[error] 1-1: ESLint: 'useEffect' is defined but never used. (no-unused-vars)
🪛 GitHub Check: Lint Code
src/pages/Credits/ContributorsCreditsCard.jsx
[failure] 1-1:
'useEffect' is defined but never used. Allowed unused vars must match /^[A-Z_]/u
🔇 Additional comments (12)
src/pages/Credits/Credits.module.css (1)
4-4: LGTM! Tighter spacing complements the pagination additions.The reduced gap (2rem → 1rem) creates a denser layout that works well with the new paginated content structure.
src/components/Pagination.module.css (1)
1-64: LGTM! Well-structured pagination styles with accessibility and responsiveness.The CSS module is cleanly organized with:
- Proper use of CSS variables for theming
- Smooth transitions for interactive states
- Appropriate disabled state handling (opacity + cursor: not-allowed)
- Mobile optimization for smaller screens
- Clear visual hierarchy between arrows, pages, and ellipsis
src/pages/Credits/StaticCreditsCard.module.css (1)
1-13: LGTM! Clean table styling with appropriate specificity.The use of
!importanton line 4 is justified to override inherited width styles. The nowrap on first-child prevents label wrapping while keeping content cells flexible.src/pages/Credits/ContributorsCreditsCard.jsx (1)
17-17: LGTM! Pagination implementation is clean and correct.The client-side pagination correctly:
- Maintains page state with
useState(0)- Renders only the current page's table (
i === page)- Integrates the
Paginationcomponent with proper propsAlso applies to: 24-60, 63-63
src/pages/Credits/StaticCreditsCard.jsx (1)
3-3: LGTM! CSS module integration is clean.The import and application of the CSS module properly centralizes table styling.
Also applies to: 10-10
src/components/Pagination.jsx (1)
32-86: LGTM: Well-structured pagination UI with good accessibility.The pagination rendering logic is solid:
- Proper semantic
<nav>with ARIA labels- Correct handling of edge cases (hidden when only 1 page)
- Good accessibility with
aria-currentfor active page- Appropriate disabled states for navigation controls
- Clear visual feedback with ellipses for truncated ranges
src/pages/Credits/DependencyCreditsCard.jsx (4)
10-10: LGTM: Reasonable pagination constants and state initialization.PAGE_SIZE of 10 provides good balance for readability without excessive scrolling, and the page state is correctly initialized to 0 for zero-indexed pagination.
Also applies to: 16-17
46-58: LGTM: Correct pagination logic and index calculations.The pagination implementation correctly:
- Slices items for the current page
- Maps local indices to global indices via
page * PAGE_SIZE + localIndex- Uses globalIndex to access the corresponding query in the full queries array
- Generates unique keys with
${name}-${globalIndex}
64-77: LGTM: Well-implemented URL rendering with proper security and UX.The URL rendering logic properly handles all states:
- Loading feedback during fetch
- Tooltip with descriptive content for accessibility
- Secure external links with
rel="noopener noreferrer"- Dual display (full URL + icon) with CSS-controlled visibility
- Clear fallback message when URL is unavailable
93-93: LGTM: Correct Pagination integration with proper state management.The Pagination component is properly integrated:
- Independent page state for each section prevents interference
Math.ceilcorrectly handles partial pages- Direct
setStatereferences provide stable callbacks- Component automatically hides when pagination is unnecessary (≤1 page)
Also applies to: 101-101
src/pages/Credits/DependencyCreditsCard.module.css (2)
1-32: LGTM: Reasonable table layout with overflow handling.The fixed table layout with explicit column widths (35% / 15% / 50%) provides consistent presentation:
- Package names get adequate space with ellipsis for very long names
- Versions get compact space appropriate for version strings
- URLs get the most space as they tend to be longest
The
text-overflow: ellipsisprevents layout breaks while keeping content accessible in the DOM.
42-71: LGTM: Effective mobile-responsive strategy.The mobile breakpoint (600px) provides a well-optimized layout:
- Full-width table maximizes available space
- Package names get 50% allocation for better readability
- URL column reduces to icon-only (40px) to conserve horizontal space
- Icon size (18px from DependencyCreditsCard.jsx line 71) fits comfortably in 40px with proper tap target
vertical-align: middleensures proper icon alignment
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @src/pages/Credits/ContributorsCreditsCard.jsx:
- Line 54: The ContributorsCreditsCard still always renders "commits"; update
the rendering that uses c.contributions to choose the correct singular/plural
form (e.g., use a conditional on c.contributions === 1 to render "commit"
otherwise "commits") inside the ContributorsCreditsCard component where the <td>
displays contributions so a single contribution reads "1 commit" and others read
"N commits".
🧹 Nitpick comments (1)
src/pages/Credits/ContributorsCreditsCard.jsx (1)
24-60: Inefficient rendering pattern: mapping all tables to find current page.The current implementation maps over all tables and conditionally renders only the active page. This creates unnecessary iterations.
♻️ More efficient approach using direct array access
<div className={styles.contributorsGrid}> - {tables.map( - (group, i) => - i === page && ( - <table key={i}> - <tbody> - {group.map((c) => ( - <tr key={c.id}> - <td> - <Tooltip content={`Open ${c.login}'s GitHub profile`}> - <a href={c.html_url} target="_blank" rel="noopener noreferrer"> - <FallbackImage - src={c.avatar_url} - fallback={<User color="var(--color-text-light)" />} - alt={c.login} - width="28" - height="28" - className={styles.avatar} - /> - </a> - </Tooltip> - </td> - - <td> - <Tooltip content={`Visit ${c.login}'s GitHub profile`}> - <a href={c.html_url} target="_blank" rel="noopener noreferrer"> - {c.login} - </a> - </Tooltip> - </td> - - <td>{c.contributions} commits</td> - </tr> - ))} - </tbody> - </table> - ) - )} + {tables[page] && ( + <table> + <tbody> + {tables[page].map((c) => ( + <tr key={c.id}> + <td> + <Tooltip content={`Open ${c.login}'s GitHub profile`}> + <a href={c.html_url} target="_blank" rel="noopener noreferrer"> + <FallbackImage + src={c.avatar_url} + fallback={<User color="var(--color-text-light)" />} + alt={c.login} + width="28" + height="28" + className={styles.avatar} + /> + </a> + </Tooltip> + </td> + + <td> + <Tooltip content={`Visit ${c.login}'s GitHub profile`}> + <a href={c.html_url} target="_blank" rel="noopener noreferrer"> + {c.login} + </a> + </Tooltip> + </td> + + <td>{c.contributions} {c.contributions === 1 ? 'commit' : 'commits'}</td> + </tr> + ))} + </tbody> + </table> + )} </div>Note: This also includes the grammar fix from the previous comment.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/pages/Credits/ContributorsCreditsCard.jsx
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Ryan-Millard
Repo: Ryan-Millard/Img2Num PR: 217
File: src/pages/Credits/ContributorsCreditsCard.jsx:48-50
Timestamp: 2026-01-09T14:45:56.443Z
Learning: In src/pages/Credits/ContributorsCreditsCard.jsx, the contributor data comes from GitHub's /contributors API endpoint (via scripts/generate-contributor-credits-json.js), which only returns contributors with at least one contribution. Therefore, c.contributions will always be >= 1 and the zero case is impossible.
📚 Learning: 2026-01-09T14:45:56.443Z
Learnt from: Ryan-Millard
Repo: Ryan-Millard/Img2Num PR: 217
File: src/pages/Credits/ContributorsCreditsCard.jsx:48-50
Timestamp: 2026-01-09T14:45:56.443Z
Learning: In src/pages/Credits/ContributorsCreditsCard.jsx, the contributor data comes from GitHub's /contributors API endpoint (via scripts/generate-contributor-credits-json.js), which only returns contributors with at least one contribution. Therefore, c.contributions will always be >= 1 and the zero case is impossible.
Applied to files:
src/pages/Credits/ContributorsCreditsCard.jsx
🧬 Code graph analysis (1)
src/pages/Credits/ContributorsCreditsCard.jsx (4)
src/components/Pagination.jsx (2)
i(9-9)Pagination(16-88)src/components/GlassCard.jsx (1)
GlassCard(5-9)src/components/Tooltip.jsx (1)
Tooltip(5-35)src/components/FallbackImage.jsx (1)
FallbackImage(10-19)
🔇 Additional comments (3)
src/pages/Credits/ContributorsCreditsCard.jsx (3)
1-8: LGTM: Imports are correct for pagination.The added
useStateandPaginationimports are properly used in the component.
14-18: LGTM: State setup is appropriate.The pagination state is correctly initialized, and the chunk size of 10 contributors per page is reasonable.
63-63: LGTM: Pagination component is correctly integrated.The
Paginationcomponent receives the correct props (page,totalPages,onChange), and the state setter is appropriately used as the change handler.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @src/pages/Credits/ContributorsCreditsCard.jsx:
- Around line 24-60: The table cell currently renders only the label and drops
the numeric contribution count; update the cell that uses c.contributions
(inside ContributorsCreditsCard.jsx where tables.map and the row rendering
occurs) to include the numeric value followed by the pluralized label (e.g.,
render c.contributions then choose 'commit' vs 'commits' based on
c.contributions === 1). While here, you can also simplify rendering by using the
active page directly (use tables[page] instead of mapping all tables and
checking i === page) to avoid iterating unused pages.
🧹 Nitpick comments (2)
src/pages/Credits/ContributorsCreditsCard.jsx (2)
11-18: Prefer memoized/extracted chunking to avoid re-allocating on every render.
chunk,tables, andchunkSizeare recreated each render; consider extractingchunkoutside the component and/or usinguseMemofortables.
63-63: Consider clampingpageon change for extra safety.
Even though the control disables out-of-range navigation, a small wrapper prevents accidental invalid state iftables.lengthchanges.Example
- <Pagination page={page} totalPages={tables.length} onChange={setPage} /> + <Pagination + page={page} + totalPages={tables.length} + onChange={(p) => setPage(Math.max(0, Math.min(p, tables.length - 1)))} + />
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/pages/Credits/ContributorsCreditsCard.jsx
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Ryan-Millard
Repo: Ryan-Millard/Img2Num PR: 217
File: src/pages/Credits/ContributorsCreditsCard.jsx:48-50
Timestamp: 2026-01-09T14:45:56.443Z
Learning: In src/pages/Credits/ContributorsCreditsCard.jsx, the contributor data comes from GitHub's /contributors API endpoint (via scripts/generate-contributor-credits-json.js), which only returns contributors with at least one contribution. Therefore, c.contributions will always be >= 1 and the zero case is impossible.
📚 Learning: 2026-01-09T14:45:56.443Z
Learnt from: Ryan-Millard
Repo: Ryan-Millard/Img2Num PR: 217
File: src/pages/Credits/ContributorsCreditsCard.jsx:48-50
Timestamp: 2026-01-09T14:45:56.443Z
Learning: In src/pages/Credits/ContributorsCreditsCard.jsx, the contributor data comes from GitHub's /contributors API endpoint (via scripts/generate-contributor-credits-json.js), which only returns contributors with at least one contribution. Therefore, c.contributions will always be >= 1 and the zero case is impossible.
Applied to files:
src/pages/Credits/ContributorsCreditsCard.jsx
🧬 Code graph analysis (1)
src/pages/Credits/ContributorsCreditsCard.jsx (4)
src/components/Pagination.jsx (2)
i(9-9)Pagination(16-88)src/components/GlassCard.jsx (1)
GlassCard(5-9)src/components/Tooltip.jsx (1)
Tooltip(5-35)src/components/FallbackImage.jsx (1)
FallbackImage(10-19)
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
|
Hi @Ryan-Millard, please have a look, and let me know what you think: Pagination
Consistent styling
Responsive improvements
|
There was a problem hiding this comment.
This is great! Thank you!
I just have a few small things to ask of you:
- Please write some tests for the Pagination component (and the other pages if you'd like - the Pagination component one is the most important since it may get used elsewhere in the code).
- Please will you write some documentation for the Pagination component inside
docs/docs/reference/react/components/so future contributors will know how to use it. - Please will you add the
glassglobal class (fromglobal-styles/components.css) to the buttons to maintain consistency across the app. - Please will you change the styling on the buttons (see my comment on
Pagination.module.css). As you can see below, it's hard to read the numbers on the active ones in the dark theme:
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
src/pages/Credits/ContributorsCreditsCard.jsx (2)
11-12: Consider moving thechunkutility outside the component.The
chunkfunction is pure and doesn't depend on component state or props. Moving it outside avoids recreating it on every render and improves readability.♻️ Suggested refactor
import { User } from 'lucide-react'; +const chunk = (arr, size) => + Array.from({ length: Math.ceil(arr.length / size) }, (_, i) => arr.slice(i * size, i * size + size)); + export default function ContributorsCreditsCard() { - const chunk = (arr, size) => - Array.from({ length: Math.ceil(arr.length / size) }, (_, i) => arr.slice(i * size, i * size + size)); - const chunkSize = 10;
24-60: Simplify rendering by directly accessing the current page's data.The current pattern maps over all table groups but only renders one, producing an array like
[false, false, <table>, false]. This is inefficient and harder to read. Directly accesstables[page]instead.♻️ Suggested refactor
<div className={styles.contributorsGrid}> - {tables.map( - (group, i) => - i === page && ( - <table key={i}> - <tbody> - {group.map((c) => ( - <tr key={c.id}> - <td> - <Tooltip content={`Open ${c.login}'s GitHub profile`}> - <a href={c.html_url} target="_blank" rel="noopener noreferrer"> - <FallbackImage - src={c.avatar_url} - fallback={<User color="var(--color-text-light)" />} - alt={c.login} - width="28" - height="28" - className={styles.avatar} - /> - </a> - </Tooltip> - </td> - <td> - <Tooltip content={`Visit ${c.login}'s GitHub profile`}> - <a href={c.html_url} target="_blank" rel="noopener noreferrer"> - {c.login} - </a> - </Tooltip> - </td> - <td> - {c.contributions} {c.contributions === 1 ? 'commit' : 'commits'} - </td> - </tr> - ))} - </tbody> - </table> - ) - )} + <table> + <tbody> + {tables[page]?.map((c) => ( + <tr key={c.id}> + <td> + <Tooltip content={`Open ${c.login}'s GitHub profile`}> + <a href={c.html_url} target="_blank" rel="noopener noreferrer"> + <FallbackImage + src={c.avatar_url} + fallback={<User color="var(--color-text-light)" />} + alt={c.login} + width="28" + height="28" + className={styles.avatar} + /> + </a> + </Tooltip> + </td> + <td> + <Tooltip content={`Visit ${c.login}'s GitHub profile`}> + <a href={c.html_url} target="_blank" rel="noopener noreferrer"> + {c.login} + </a> + </Tooltip> + </td> + <td> + {c.contributions} {c.contributions === 1 ? 'commit' : 'commits'} + </td> + </tr> + ))} + </tbody> + </table> </div>
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/components/Pagination.jsxsrc/pages/Credits/ContributorsCreditsCard.jsx
🚧 Files skipped from review as they are similar to previous changes (1)
- src/components/Pagination.jsx
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Ryan-Millard
Repo: Ryan-Millard/Img2Num PR: 217
File: src/pages/Credits/ContributorsCreditsCard.jsx:48-50
Timestamp: 2026-01-09T14:45:56.443Z
Learning: In src/pages/Credits/ContributorsCreditsCard.jsx, the contributor data comes from GitHub's /contributors API endpoint (via scripts/generate-contributor-credits-json.js), which only returns contributors with at least one contribution. Therefore, c.contributions will always be >= 1 and the zero case is impossible.
📚 Learning: 2026-01-09T14:45:56.443Z
Learnt from: Ryan-Millard
Repo: Ryan-Millard/Img2Num PR: 217
File: src/pages/Credits/ContributorsCreditsCard.jsx:48-50
Timestamp: 2026-01-09T14:45:56.443Z
Learning: In src/pages/Credits/ContributorsCreditsCard.jsx, the contributor data comes from GitHub's /contributors API endpoint (via scripts/generate-contributor-credits-json.js), which only returns contributors with at least one contribution. Therefore, c.contributions will always be >= 1 and the zero case is impossible.
Applied to files:
src/pages/Credits/ContributorsCreditsCard.jsx
🧬 Code graph analysis (1)
src/pages/Credits/ContributorsCreditsCard.jsx (4)
src/components/Pagination.jsx (2)
i(9-9)Pagination(16-94)src/components/GlassCard.jsx (1)
GlassCard(5-9)src/components/Tooltip.jsx (1)
Tooltip(5-35)src/components/FallbackImage.jsx (1)
FallbackImage(10-19)
🔇 Additional comments (4)
src/pages/Credits/ContributorsCreditsCard.jsx (4)
1-8: LGTM!Imports are appropriate for the added pagination functionality.
14-18: LGTM!Chunk size of 10 is reasonable for table pagination, and the page state is correctly initialized.
52-53: Grammar fix correctly implemented.The pluralization logic properly handles the singular "commit" case. Based on learnings,
c.contributionsis always >= 1 from the GitHub API, so both branches are valid.
63-63: Pagination integration looks correct.The Pagination component receives the appropriate props and aligns with the reusable component's API shown in
src/components/Pagination.jsx.
|
Hi @laxitajain. Just checking in - are you still interested in this PR? There's no rush whatsoever. I'd just like to know if you're unable to complete it and would like someone else to pick up from where you left off. |
Hello, thanks for waiting. I apologize for not being able to update you sooner, I haven't been able to find time to continue work here. I'm still interested and shall make the required changes soon. |
Co-authored-by: Ryan Millard <142347829+Ryan-Millard@users.noreply.github.com>
|
No problem at all! I just wanted to check up on it. |
|
hey @Ryan-Millard, I've realised I won't be able to continue work on this PR and therefore will be revoking my claim on the issue. Sorry for the inconvenience! |
|
Hi @laxitajain. That's not a problem at all. Someone else will carry on from where you left off. Have a good day! |
|
hey @Ryan-Millard! |
Ryan-Millard
left a comment
There was a problem hiding this comment.
Thank you! This is wonderful.
|
@Ryan-Millard is attempting to deploy a commit to the Ryan Millard's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
Don't worry about Vercel's failure. I'm between changing hosts at the moment because GitHub Pages doesn't support setting headers and I haven't finished configuring Vercel. |
|
Thank you for your wonderful work so far @laxitajain! |







Please choose one of the following:
If none of these fit, you may use this default to describe your change manually.
If this is the right template, go ahead and complete it below 👇
📌 Description
Currently, in the Contributors section on the Credits page, the plural “commits” is used even for a single commit. While I understand that a full rework of the Credits page is needed, this PR fixes the grammatical issue for the time being.
Issue
Fixes #218
✅ Type of Change
Place an "x" in the brackets below:
🧪 How Has This Been Tested?
Please describe how you tested your changes (e.g., unit tests, manual testing, screenshots, etc.)
🧩 Checklist
Place an "x" in the brackets below:
📸 Screenshots / Demo (if applicable)
Paste images, GIFs, or demo links here.
💬 Additional Context
Anything else relevant to the PR.
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.