(SP: 2) [Frontend] Q&A UI refresh#169
Conversation
✅ Deploy Preview for develop-devlovers ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
📝 WalkthroughWalkthroughThis PR adds a DynamicGridBackground component, introduces typed qaTabStyles and a QaTabButton, converts the Q&A page to async locale-aware rendering with header text, removes debounced search from useQaTabs, updates QaSection to use QaTabButton and simplified loading logic, and surfaces accentColor to Pagination for themed styling. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant QAPage
participant DynamicGridBackground
participant QaSection
participant useQaTabs
participant API
participant Pagination
User->>QAPage: Request Q&A page
QAPage->>QAPage: Resolve async params (locale) and load translations
QAPage->>DynamicGridBackground: Render wrapper + headers
DynamicGridBackground->>QaSection: Mount child content
QaSection->>useQaTabs: Init (category, page, locale)
useQaTabs->>API: Fetch items (active, currentPage, locale)
API-->>useQaTabs: Return items + totalPages
useQaTabs-->>QaSection: Provide items, isLoading, totalPages
QaSection->>Pagination: Pass accentColor from qaTabStyles[active]
Pagination-->>QaSection: Render pages with accent styling
User->>QaSection: Click category tab
QaSection->>useQaTabs: handleCategoryChange(category)
useQaTabs->>useQaTabs: Reset currentPage -> 1
useQaTabs->>API: Fetch new category items
API-->>useQaTabs: Return items
useQaTabs-->>QaSection: Update items, Pagination accent updates
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
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: 3
🤖 Fix all issues with AI agents
In `@frontend/components/q`&a/useQaTabs.ts:
- Around line 112-117: In the finally block in useQaTabs.ts, remove the early
`return` that can suppress exceptions and instead guard the cleanup call:
replace the `if (!isActive) { return; } setIsLoading(false);` pattern with a
conditional that only calls `setIsLoading(false)` when `isActive` is true (e.g.,
`if (isActive) setIsLoading(false);`), ensuring no control-flow (throws/returns)
from the try/catch is overridden; keep all thrown errors intact so they
propagate normally.
In `@frontend/components/shared/DynamicGridBackground.tsx`:
- Around line 35-43: The useMotionTemplate hooks are being called inside the
style prop of the motion.div (maskImage/WebkitMaskImage), which violates rules
of hooks; move those useMotionTemplate calls to the top level of the
DynamicGridBackground component (e.g., compute maskImageTemplate and
webkitMaskImageTemplate using useMotionTemplate with mouseX and mouseY before
the return), then reference those variables in the motion.div style prop; ensure
you keep the same template string and variable names (mouseX, mouseY) so
behavior is unchanged.
In `@frontend/messages/en.json`:
- Around line 36-38: Delete the unused Q&A translation entries
qa.searchPlaceholder, qa.clearSearch, and qa.noResults from the translations
(remove the "searchPlaceholder", "clearSearch", and "noResults" keys shown in
the diff) to eliminate dead keys; after removal, run the i18n validation or
translation linting step used in the repo to ensure no references remain and
update any translation extraction artifacts if applicable.
🧹 Nitpick comments (6)
frontend/components/shared/DynamicGridBackground.tsx (1)
26-47: Consider adding aria-hidden to decorative background layers.The background grid layers are purely decorative and don't convey meaningful content. Adding
aria-hidden="true"to the decorative divs improves accessibility by ensuring screen readers skip them.♿ Suggested improvement
- <div className="pointer-events-none absolute inset-0"> + <div className="pointer-events-none absolute inset-0" aria-hidden="true"> <div className="absolute inset-0 bg-[linear-gradient(to_right,`#8080800a_1px`,transparent_1px),linear-gradient(to_bottom,`#8080800a_1px`,transparent_1px)] bg-[size:40px_40px] [mask-image:radial-gradient(ellipse_80%_80%_at_50%_50%,`#000_70`%,transparent_100%)]" /> </div> <motion.div className="pointer-events-none absolute inset-0 opacity-0 transition-opacity duration-300 group-hover/dynamic:opacity-100" + aria-hidden="true" style={{frontend/components/about/HeroSection.tsx (2)
91-106: Add proper TypeScript types instead ofany.Using
anyfor theGlassWidgetprops bypasses TypeScript's type checking. Define a proper interface for type safety.🔧 Suggested type definition
+import type { LucideIcon } from 'lucide-react'; +interface StatWidgetProps { + icon: LucideIcon; + color: string; + bg: string; + label: string; + value: string; +} -function GlassWidget({ icon: Icon, color, bg, label, value }: any) { +function GlassWidget({ icon: Icon, color, bg, label, value }: StatWidgetProps) {
108-120: Add proper TypeScript types forMobileStatItem.Same issue as
GlassWidget— define a proper interface instead of usingany.🔧 Suggested fix
-function MobileStatItem({ icon: Icon, color, bg, label, value }: any) { +function MobileStatItem({ icon: Icon, color, bg, label, value }: StatWidgetProps) {frontend/components/q&a/Pagination.tsx (1)
14-21: Consider handling 3-character shorthand hex codes.The
hexToRgbafunction only supports 6-character hex codes. If a 3-character shorthand like#FFFis passed, it will fall back torgba(0, 0, 0, alpha), which may produce unexpected results.🔧 Enhanced implementation
function hexToRgba(hex: string, alpha: number): string { const normalized = hex.replace('#', ''); - if (normalized.length !== 6) return `rgba(0, 0, 0, ${alpha})`; - const r = parseInt(normalized.slice(0, 2), 16); - const g = parseInt(normalized.slice(2, 4), 16); - const b = parseInt(normalized.slice(4, 6), 16); + let r: number, g: number, b: number; + if (normalized.length === 3) { + r = parseInt(normalized[0] + normalized[0], 16); + g = parseInt(normalized[1] + normalized[1], 16); + b = parseInt(normalized[2] + normalized[2], 16); + } else if (normalized.length === 6) { + r = parseInt(normalized.slice(0, 2), 16); + g = parseInt(normalized.slice(2, 4), 16); + b = parseInt(normalized.slice(4, 6), 16); + } else { + return `rgba(0, 0, 0, ${alpha})`; + } return `rgba(${r}, ${g}, ${b}, ${alpha})`; }frontend/components/q&a/QaSection.tsx (1)
51-55: Consider adding accessibility attributes to the loading spinner.The spinner lacks screen reader context. Adding an accessible label improves the experience for assistive technology users.
Suggested enhancement
{isLoading && ( - <div className="flex justify-center py-12"> - <div className="animate-spin h-8 w-8 border-b-2" /> + <div className="flex justify-center py-12" role="status" aria-label={t('common.loading')}> + <div className="animate-spin h-8 w-8 border-b-2" aria-hidden="true" /> + <span className="sr-only">{t('common.loading')}</span> </div> )}frontend/messages/uk.json (1)
36-38: Consider removing unused search-related translation keys.Since search functionality was removed from the Q&A page, these keys (
searchPlaceholder,clearSearch,noResults) are now unused. Cleaning them up would reduce translation maintenance burden.
Summary
Changes
CLOSES: #168
Summary by CodeRabbit
New Features
Changes
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.