-
Notifications
You must be signed in to change notification settings - Fork 155
Created SponsorCard component for featured projects #235
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
@praveenzsp is attempting to deploy a commit to the AJEET PRATAP SINGH's projects Team on Vercel. A member of the Team first needs to authorize it. |
WalkthroughA new SponsorCard React component was added at apps/web/src/components/ui/SponsorCard.tsx. It renders a linked card showing a sponsor logo, name, and description, accepts props for content and behavior, uses Next.js Image and composes with an existing Card component. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~5–10 minutes
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
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 |
|
Hey @apsinghdev & @huamanraj created a basic card component by referring the draft u provided. lemme know if any changes are needed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/web/src/components/ui/SponsorCard.tsx(1 hunks)
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx,js,jsx}: Always use lowercase when writing comments
Avoid unnecessary comments; code should be self-documenting when possible
Use comments to explain 'why', not 'what'
Remove unused imports
Use UPPER_SNAKE_CASE for constants
Use camelCase for functions and variables
Files:
apps/web/src/components/ui/SponsorCard.tsx
apps/web/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
apps/web/src/**/*.{ts,tsx}: Always follow the design system defined inapps/web/src/lib/design-tokens.tsandapps/web/tailwind.config.ts
NEVER use hardcoded hex values (e.g.,#5519f7) directly in components; ALWAYS reference colors from the design token system using Tailwind classes
Use semantic color names that describe purpose, not appearance
Usefont-sansfor standard UI text (Geist Sans) andfont-monofor code, technical content, or monospace needs (DM Mono)
Follow Tailwind's spacing scale (0.25rem increments); for section padding use mobilep-4(1rem) and desktopp-[60px]
Use appropriate border radius: small elementsrounded-lg, mediumrounded-xl, largerounded-2xl, buttonsrounded-[16px]
Use animation durations: fastduration-100(0.1s), normalduration-300(0.3s), slowduration-600(0.6s)
Files:
apps/web/src/components/ui/SponsorCard.tsx
**/*.{tsx,ts}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{tsx,ts}: Prefer functional components with TypeScript and use proper TypeScript types, avoidany
Extract reusable logic into custom hooks
Use descriptive prop names and define prop types using TypeScript interfaces or types
Prefer controlled components over uncontrolled
Use zustand for global state (located insrc/store/)
Use absolute imports from@/prefix when available
Include proper aria labels for accessibility
Ensure keyboard navigation works
Maintain proper heading hierarchy
Provide alt text for images
Avoid unnecessary re-renders
Files:
apps/web/src/components/ui/SponsorCard.tsx
**/*.{tsx,ts,jsx,js}
📄 CodeRabbit inference engine (.cursorrules)
Organize imports: react → third-party → local components → utils → types
Files:
apps/web/src/components/ui/SponsorCard.tsx
**/*[A-Z]*.{tsx,ts}
📄 CodeRabbit inference engine (.cursorrules)
Use PascalCase for component file names (e.g.,
UserProfile.tsx)
Files:
apps/web/src/components/ui/SponsorCard.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx}: Use PascalCase for types and interfaces with descriptive names
Use dynamic imports for code splitting when appropriate
Memoize expensive computations
Files:
apps/web/src/components/ui/SponsorCard.tsx
apps/web/src/**/*.{tsx,ts}
📄 CodeRabbit inference engine (.cursorrules)
Optimize images using next/image
apps/web/src/**/*.{tsx,ts}: Use Zustand for global state, located insrc/store/
Use PascalCase for types and interfaces with descriptive names
Use dynamic imports for code splitting when appropriate
Optimize images using next/image
Memoize expensive computations
Define a type when defining const functions
Files:
apps/web/src/components/ui/SponsorCard.tsx
**/*.{js,jsx,ts,tsx,py,java,go,rb,php}
📄 CodeRabbit inference engine (.cursor/rules/general_rules.mdc)
**/*.{js,jsx,ts,tsx,py,java,go,rb,php}: Always use lowercase when writing comments
Avoid unnecessary comments; code should be self-documenting when possible
Use comments to explain 'why', not 'what'
Files:
apps/web/src/components/ui/SponsorCard.tsx
apps/web/src/components/**/*.{tsx,ts,jsx,js}
📄 CodeRabbit inference engine (apps/web/.cursor/rules/frontend_rules.mdc)
apps/web/src/components/**/*.{tsx,ts,jsx,js}: Never use hardcoded hex values directly in components; always reference colors from the design token system using Tailwind classes
Use semantic color names from the design token system that describe purpose, not appearance (e.g., bg-brand-purple, bg-surface-primary, text-text-primary)
Use font-sans for standard UI text (Geist Sans) and font-mono for code, technical content, or monospace needs (DM Mono)
Follow Tailwind's spacing scale for section padding: p-4 (1rem) on mobile, p-[60px] on desktop
Use rounded-lg (0.5rem) for small elements, rounded-xl (1rem) for medium elements, rounded-2xl (1.5rem) for large elements, and rounded-[16px] for buttons
Use duration-100 (0.1s) for fast transitions, duration-300 (0.3s) for normal transitions, and duration-600 (0.6s) for slow transitions
Use available custom animations: animate-accordion-down, animate-accordion-up, animate-scrollRight, animate-scrollLeft, animate-customspin, animate-spin-slow, animate-spin-slow-reverse, animate-marquee, animate-marquee-vertical, animate-shine
Prefer functional components with TypeScript
Extract reusable logic into custom hooks
Prefer controlled components over uncontrolled
Include proper aria labels for accessibility
Ensure keyboard navigation works in interactive components
Maintain proper heading hierarchy in page components
Provide alt text for images
Use 'class:' instead of the ternary operator in class tags whenever possible
Implement accessibility features on interactive elements (e.g., tabindex='0', aria-label, onClick, onKeyDown)
Always follow the design system defined inapps/web/src/lib/design-tokens.tsandapps/web/tailwind.config.ts
Files:
apps/web/src/components/ui/SponsorCard.tsx
apps/web/src/components/**/*.{tsx,ts}
📄 CodeRabbit inference engine (apps/web/.cursor/rules/frontend_rules.mdc)
apps/web/src/components/**/*.{tsx,ts}: Use proper TypeScript types and avoid usinganytype
Use descriptive prop names and define prop types using TypeScript interfaces or types
Name components using PascalCase (e.g., UserProfile.tsx)
Files:
apps/web/src/components/ui/SponsorCard.tsx
apps/web/src/**/*.{tsx,ts,jsx,js}
📄 CodeRabbit inference engine (apps/web/.cursor/rules/frontend_rules.mdc)
apps/web/src/**/*.{tsx,ts,jsx,js}: Organize imports in order: React → third-party → local components → utils → types
Use absolute imports from@/prefix when available
Remove unused imports
Use UPPER_SNAKE_CASE for constants
Use camelCase for functions and variables
Always use Tailwind classes for styling HTML elements; avoid using CSS or style tags
Use descriptive variable and function names; name event functions with a 'handle' prefix (e.g., handleClick, handleKeyDown)
Use const with arrow functions instead of function declarations (e.g., 'const toggle = () =>')
Files:
apps/web/src/components/ui/SponsorCard.tsx
🧠 Learnings (5)
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Include proper aria labels for accessibility
Applied to files:
apps/web/src/components/ui/SponsorCard.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts} : Use descriptive prop names and define prop types using TypeScript interfaces or types
Applied to files:
apps/web/src/components/ui/SponsorCard.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Provide alt text for images
Applied to files:
apps/web/src/components/ui/SponsorCard.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{tsx,ts} : Optimize images using next/image
Applied to files:
apps/web/src/components/ui/SponsorCard.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Always follow the design system defined in `apps/web/src/lib/design-tokens.ts` and `apps/web/tailwind.config.ts`
Applied to files:
apps/web/src/components/ui/SponsorCard.tsx
🧬 Code graph analysis (1)
apps/web/src/components/ui/SponsorCard.tsx (1)
apps/web/src/lib/utils.ts (1)
cn(4-6)
🔇 Additional comments (1)
apps/web/src/components/ui/SponsorCard.tsx (1)
6-14: props shape and accessibility defaults look solidprops are clearly typed, use descriptive names, and the optional
logoAltwith sensible fallback plusopenInNewTabdefault cover common cases without overcomplicating the api. this aligns well with the repo guidelines on prop typing and accessibility.As per coding guidelines, ...
Also applies to: 21-24
| import React from "react"; | ||
| import { cn } from "@/lib/utils"; | ||
| import Image from "next/image"; | ||
| import { Card } from "./card"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
align imports and component definition with project conventions
- reorder imports to follow the documented order:
react → third‑party → local components → utils. here that would meannext/imagefirst, then./card, then@/lib/utils. - the
reactdefault import is unused with the current jsx setup; it can be removed. - guidelines prefer
const+ arrow for components; consider:
-import React from "react";
-import { cn } from "@/lib/utils";
-import Image from "next/image";
-import { Card } from "./card";
+import Image from "next/image";
+import { Card } from "./card";
+import { cn } from "@/lib/utils";
@@
-function SponsorCard({
- name,
- description,
- href,
- logoSrc,
- logoAlt,
- className,
- openInNewTab = true,
-}: SponsorCardProps) {
+const SponsorCard = ({
+ name,
+ description,
+ href,
+ logoSrc,
+ logoAlt,
+ className,
+ openInNewTab = true,
+}: SponsorCardProps) => {
@@
-}
+};As per coding guidelines, ...
Also applies to: 16-24
🤖 Prompt for AI Agents
In apps/web/src/components/ui/SponsorCard.tsx around lines 1 to 4 (and component
definition at lines 16 to 24), the imports and component style don't follow
project conventions: remove the unused default React import, reorder imports to
follow react → third‑party → local components → utils (so place next/image
first, then ./card, then @/lib/utils), and refactor the component to use a const
arrow function (e.g., const SponsorCard: React.FC<Props> = (...) => {...})
instead of a function declaration; update any export accordingly.
| className={cn( | ||
| "flex h-full flex-col overflow-hidden border-[#252525] bg-[#111111] text-sm text-muted-foreground/90 [box-shadow:0_0_60px_-24px_#14111C_inset]", | ||
| "transition-colors hover:border-[#3a3a3a]", | ||
| className |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
replace hardcoded hex colors and box‑shadow with design‑token tailwind classes
the classes border-[#252525], bg-[#111111], bg-[#050505], hover:border-[#3a3a3a], and [box-shadow:0_0_60px_-24px_#14111C_inset] violate the rule to never use raw hex values in components. please swap these for semantic tailwind classes wired to your design tokens (e.g., appropriate bg-*, border-*, and shadow-* variants defined in design-tokens.ts / tailwind.config.ts).
As per coding guidelines, ...
Also applies to: 40-41, 51-51
🤖 Prompt for AI Agents
In apps/web/src/components/ui/SponsorCard.tsx around lines 34-37 (also apply
same changes at 40-41 and 51), replace the hardcoded hex utility classes
(border-[#252525], bg-[#111111], bg-[#050505], hover:border-[#3a3a3a],
[box-shadow:0_0_60px_-24px_#14111C_inset]) with the corresponding semantic
Tailwind design-token classes defined in design-tokens.ts / tailwind.config.ts
(use the configured bg-*, border-*, hover:border-*, and shadow-* tokens
instead). Update the cn(...) call to remove raw hex and inline box-shadow and
substitute the appropriate token names, ensuring consistency with other
components and running the Tailwind build to verify class names exist.
| <Image | ||
| src={logoSrc} | ||
| alt={logoAlt ?? `${name} logo`} | ||
| fill | ||
| className="object-contain" | ||
| unoptimized | ||
| priority | ||
| /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
🧩 Analysis chain
🌐 Web query:
next/image unoptimized priority props best practices reusable components
💡 Result:
Here are concise best practices for using next/image’s unoptimized and priority props and for building reusable image components.
Key rules
- Use next/image (default) for automatic responsive resizing, modern formats, caching and to avoid layout shift — only use unoptimized when you deliberately want to bypass Next’s optimizer (e.g., images already served by a CDN, hitting Vercel optimization quotas, or to preserve exact source pixels). [1][4]
- Add priority only to the single LCP / above‑the‑fold image per page. Do NOT set priority on many images — it disables lazy loading and increases bandwidth/processing cost. Use priority sparingly. [1]
- Always supply width+height (or use fill with a container that has explicit size) and good alt text to avoid CLS and for accessibility. [1]
Server/process recommendations
- Install sharp in production to speed image processing (reduces server-side latency for optimized images). Test that your deployment’s image optimizer is behaving as expected. [2]
- If you use Vercel’s image optimization and hit quotas or want zero server processing, set images.unoptimized or use Image unoptimized prop—but expect larger payloads and loss of responsive format delivery. Monitor for broken images if quota limits are reached. [4]
Reusable Image component patterns
- Component API (minimal, safe defaults):
- props: src, alt, width?, height?, sizes?, className?, priority?: boolean (default false), unoptimized?: boolean (default false), quality?
- Internally compute sizes based on layout/responsive breakpoints; map a boolean isLCP or page prop to set priority.
- Defaults and guardrails:
- Default priority = false. Only expose a semantic prop like isLCP or critical that sets priority internally so callers don’t overuse it.
- Default unoptimized = false; expose forceUnoptimized only when intentionally bypassing optimization.
- Validate/normalize src (reject empty/invalid), and provide a fallback src and onError handler to avoid infinite retries/ broken images.
- Performance helpers:
- Provide sensible sizes and srcSet through sizes prop; compute srcSets for common breakpoints.
- Lazy-load non-critical images (omit priority) so they use native lazy loading.
- Memoize component or wrap in React.memo where props are stable to avoid re-renders.
- If many images are processed server-side, consider pre-generating/resizing at build time or use a CDN that serves pre-optimized variants to reduce runtime processing.
- Accessibility & UX:
- Require alt, support aria-* where needed, offer low‑quality placeholder (blurDataURL) for perceived performance.
Example (conceptual)
- export default function AppImage({src, alt, width, height, isLCP=false, forceUnoptimized=false, ...}) {
return
}
When to use unoptimized vs priority (summary)
- Use priority for the single LCP image to improve LCP. [1]
- Use unoptimized only when you must bypass Next’s optimizer (CDN already optimized, Vercel quota issues, or need exact source bytes). Be aware of larger payloads and potential quality/format differences. [1][4]
References
- Next.js Image docs (priority, sizing, best practices). [1]
- Recommendation to install sharp for production image processing speed. [2]
- General image optimization and tradeoffs (guidance on when to avoid unoptimized). [3]
- Reports/experience about Vercel optimization quotas and broken images when quota reached. [4]
If you want, I can: (A) sketch a production-ready reusable Image component (TS + prop types + sizes logic), or (B) review your current Image component and suggest concrete fixes. Which do you prefer?
🏁 Script executed:
# Search for SponsorCard usage to understand the impact of priority attribute
rg "SponsorCard" --type tsx --type ts -lRepository: apsinghdev/opensox
Length of output: 180
Expose image optimization as opt-in props with safe defaults for reusable components
The unoptimized prop disables next/image optimization entirely, and priority should only be used for a single above-the-fold image per page—setting it by default on a reusable card component will result in multiple priority images across pages, defeating lazy loading and increasing bandwidth.
For a generic UI component, remove both props or expose them as opt-in props with semantic naming and safe defaults:
- Replace
prioritywith anisLCP?: booleanprop (defaultfalse) so callers explicitly mark only the critical image per page - Replace
unoptimizedwith aforceUnoptimized?: booleanprop (defaultfalse) and expose it only when intentionally bypassing optimization
This ensures the component respects next/image best practices by default while allowing callers to opt in when needed.
🤖 Prompt for AI Agents
In apps/web/src/components/ui/SponsorCard.tsx around lines 41 to 48, the Image
currently hardcodes unoptimized and priority which breaks next/image
best-practices for reusable components; add two optional props to the component
signature isLCP?: boolean = false and forceUnoptimized?: boolean = false, remove
the hardcoded unoptimized and priority attributes from the Image tag, and
instead pass unoptimized={forceUnoptimized} and priority={isLCP} so callers must
opt in to bypass optimization or mark the image as LCP; also update the
component's props type/interface and default values accordingly and adjust any
callers if they need the previous behavior.
Fixes #232
Implementation Details
Manually added cards to landing page to display them
sponsorcard.mp4
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.