feat(ui): glassmorphism visual overhaul — premium dark mode ✨#1
feat(ui): glassmorphism visual overhaul — premium dark mode ✨#1helioneto144 wants to merge 1 commit into
Conversation
Implemented a comprehensive visual redesign of the Dashboard, Sidebar,
and Layout components to achieve a premium glassmorphism aesthetic.
## Assets (NanoBanana generated)
- Add frontend/public/img/bg.png: 8K dark-mode texture with subtle noise,
neon emerald/violet edge glows for immersive layered backgrounds
- Add frontend/public/img/sprite.png: 3D finance-themed illustration
sprites with glossy effect, soft lighting and iridescent tones
## Layout.tsx
- Replace solid bg-background with translucent dark glass stack:
bg.png as background layer + black/60 overlay + backdrop-blur
- Add decorative sprite image (top-right, rotated, animated pulse)
- Add teal brand ambient orb (blur-[100px] radial glow)
- Intensify top ambient gradient (from-brand-900/20)
## Sidebar.tsx
- Apply backdrop-blur-2xl glass panel: bg-zinc-950/40 + border-white/5
- Add ambient glow orb at sidebar top (brand-500/10 blur)
- Logo: iridescent gradient text + hover flash overlay + glow shadow
- Nav items: glass active state with inset border + gradient fill:
Active → text-white bg-white/10 + brand gradient
Inactive → hover:bg-white/5
- Active indicator: glowing neon line (brand-400 + drop-shadow)
- Icons: drop-shadow glow on active, smoother hover transitions
- 'Beta' badge: brighter, glowing indigo variant
## DashboardPage.tsx
- KPI Cards: glass panels (bg-zinc-900/30) with:
Hover gradient overlay (from-brand-500/5)
Icon animates on hover (scale + rotate)
Amount translates subtly on hover
drop-shadow-md on money values
- Charts grid: ambient brand glow backdrop behind the grid
Each chart card gets a corner orb that brightens on hover
- Pie/Merchants/Transactions panels: glass border, hover border-white/10
- Transaction rows: hover bg fill, icon glows on hover, amount scale-105
Income amounts get emerald drop-shadow glow
- Account cards: hover lift (-translate-y-1), glass institution badge,
'Crédito' tag with brand color + glow
Co-authored-by: Hélio Neto <helioneto144@gmail.com>
📝 WalkthroughWalkthroughThree frontend components receive visual design system updates featuring glass-morphism styling, layered animated backgrounds, gradient overlays, and enhanced hover interactions. Root layout introduces a backdrop-blurred background with hero sprite positioning, sidebar adds glassy panels with gradient text and glow effects, and dashboard components implement consistent glass-styled cards with hover-driven transitions and decorative elements throughout. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). 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
🧹 Nitpick comments (3)
frontend/src/components/Sidebar.tsx (1)
29-29: Excessively high z-index values indicate potential stacking context issues.
z-[99999]on the aside andz-[999999]on nav links are unusually high. This pattern often emerges when fighting stacking context issues rather than properly managing them. With the newbackdrop-blurin Layout.tsx creating a containing block, these high values may be working around the same root cause.Consider establishing a z-index scale in your Tailwind config (e.g.,
z-sidebar: 50,z-modal: 100) for maintainability rather than escalating to arbitrary large values.Also applies to: 55-55
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/components/Sidebar.tsx` at line 29, The aside in Sidebar.tsx uses an extremely large z-index class (z-[99999]) and related nav link classes use z-[999999]; replace these ad-hoc values by defining a small, consistent z-index scale in your Tailwind config (for example keys like z-sidebar and z-modal mapped to sensible numbers such as 50 and 100) and then update the Sidebar component (the aside element with class z-[99999]) and the nav link elements (currently using z-[999999]) to use the new named utilities (or z-50/z-100) instead; also review Layout.tsx's backdrop-blur containing block to ensure stacking contexts are intentional so you don't need inflated z-values.frontend/src/pages/DashboardPage.tsx (1)
296-310: Consider extracting repeated chart card wrapper.The two chart cards share identical structure: glass styling, decorative corner orb, and hover behavior. This pattern could be extracted into a reusable
ChartCardcomponent for consistency and DRY.♻️ Optional refactor
function ChartCard({ title, children }: { title: string; children: React.ReactNode }) { return ( <div className="bg-zinc-900/30 backdrop-blur-xl border border-white/5 shadow-glass rounded-2xl p-6 relative overflow-hidden group"> <div className="absolute top-0 right-0 w-32 h-32 bg-brand-500/10 rounded-full blur-3xl -mr-16 -mt-16 pointer-events-none transition-all duration-700 group-hover:bg-brand-500/20" /> <SectionHeader title={title} /> <div className="h-[280px]">{children}</div> </div> ); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/pages/DashboardPage.tsx` around lines 296 - 310, The two chart card blocks duplicate styling and structure; extract them into a reusable ChartCard component (e.g., function ChartCard({ title, children })) and replace the two duplicated div trees with <ChartCard title="Evolução do Saldo"><BalanceLineChart data={balanceData} /></ChartCard> and <ChartCard title="Fluxo de Caixa"><MonthlyBarChart data={monthlyData} /></ChartCard>; keep SectionHeader usage inside ChartCard and ensure the decorative orb div and the inner wrapper with className "h-[280px]" are moved into ChartCard so the page imports/uses ChartCard while leaving BalanceLineChart and MonthlyBarChart props unchanged.frontend/src/components/Layout.tsx (1)
14-21: Considerprefers-reduced-motionfor animated decorative elements.The sprite uses
animate-pulsecombined withblur-[1px]. Users who prefer reduced motion (accessibility setting) would benefit from disabling this animation. Tailwind providesmotion-reduce:variant.- className="absolute -top-32 -right-32 w-[600px] h-[600px] object-cover opacity-20 transform rotate-12 drop-shadow-[0_0_100px_transparent] animate-pulse blur-[1px]" + className="absolute -top-32 -right-32 w-[600px] h-[600px] object-cover opacity-20 transform rotate-12 drop-shadow-[0_0_100px_transparent] animate-pulse motion-reduce:animate-none blur-[1px]"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/components/Layout.tsx` around lines 14 - 21, The decorative sprite image currently uses the Tailwind class animate-pulse which should be disabled for users who prefer reduced motion; update the img element's className (the element with src="/img/sprite.png" and className containing "animate-pulse") to include the Tailwind motion-reduce variant (e.g., add "motion-reduce:animate-none") so the animation is suppressed when prefers-reduced-motion is set; ensure any other motion on the same decorative block (if present) uses the motion-reduce variant as well.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@frontend/src/components/Layout.tsx`:
- Line 11: The fixed-position modal in CategoriesPage.tsx (uses "position: fixed
inset-0") is being constrained by Layout.tsx's content wrapper which has
"relative z-10" (the wrapper div with className including "relative z-10"); to
fix, either 1) move the modal out of that wrapper by rendering it via a React
Portal to document.body (use createPortal in the CategoriesPage modal
component), or 2) remove the "relative" from the Layout content wrapper div in
Layout.tsx if that relative isn't required, or 3) implement a top-level modal
root/manager that mounts modals at the document root; choose one approach and
update the modal rendering (CategoriesPage.tsx modal component) and/or
Layout.tsx wrapper accordingly so the modal's fixed positioning is relative to
the viewport.
---
Nitpick comments:
In `@frontend/src/components/Layout.tsx`:
- Around line 14-21: The decorative sprite image currently uses the Tailwind
class animate-pulse which should be disabled for users who prefer reduced
motion; update the img element's className (the element with
src="/img/sprite.png" and className containing "animate-pulse") to include the
Tailwind motion-reduce variant (e.g., add "motion-reduce:animate-none") so the
animation is suppressed when prefers-reduced-motion is set; ensure any other
motion on the same decorative block (if present) uses the motion-reduce variant
as well.
In `@frontend/src/components/Sidebar.tsx`:
- Line 29: The aside in Sidebar.tsx uses an extremely large z-index class
(z-[99999]) and related nav link classes use z-[999999]; replace these ad-hoc
values by defining a small, consistent z-index scale in your Tailwind config
(for example keys like z-sidebar and z-modal mapped to sensible numbers such as
50 and 100) and then update the Sidebar component (the aside element with class
z-[99999]) and the nav link elements (currently using z-[999999]) to use the new
named utilities (or z-50/z-100) instead; also review Layout.tsx's backdrop-blur
containing block to ensure stacking contexts are intentional so you don't need
inflated z-values.
In `@frontend/src/pages/DashboardPage.tsx`:
- Around line 296-310: The two chart card blocks duplicate styling and
structure; extract them into a reusable ChartCard component (e.g., function
ChartCard({ title, children })) and replace the two duplicated div trees with
<ChartCard title="Evolução do Saldo"><BalanceLineChart data={balanceData}
/></ChartCard> and <ChartCard title="Fluxo de Caixa"><MonthlyBarChart
data={monthlyData} /></ChartCard>; keep SectionHeader usage inside ChartCard and
ensure the decorative orb div and the inner wrapper with className "h-[280px]"
are moved into ChartCard so the page imports/uses ChartCard while leaving
BalanceLineChart and MonthlyBarChart props unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d33c0b72-bfbb-48b0-9406-a2a1cba3affd
⛔ Files ignored due to path filters (2)
frontend/public/img/bg.pngis excluded by!**/*.pngfrontend/public/img/sprite.pngis excluded by!**/*.png
📒 Files selected for processing (3)
frontend/src/components/Layout.tsxfrontend/src/components/Sidebar.tsxfrontend/src/pages/DashboardPage.tsx
| <div className="absolute inset-0 -z-30 pointer-events-none"> | ||
| <img src="/img/bg.png" alt="" className="w-full h-full object-cover opacity-60" /> | ||
| </div> | ||
| <div className="absolute inset-0 bg-black/60 backdrop-blur-[2px] -z-20 pointer-events-none" /> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find all fixed-position elements in child components that would be affected
rg -n 'fixed\s+inset' --type=tsx --type=ts -g '!**/Layout.tsx' frontend/src/Repository: helioneto144/financebr
Length of output: 93
🏁 Script executed:
# Search for fixed-position elements using correct rg syntax
rg 'fixed.*inset|position.*fixed' --type=js --type=json -g '!node_modules' -A 2 frontend/src/ | head -50Repository: helioneto144/financebr
Length of output: 48
🏁 Script executed:
# Check if Layout.tsx exists and examine line 11
ls -la frontend/src/components/Layout.tsx 2>/dev/null && echo "---" && sed -n '1,20p' frontend/src/components/Layout.tsxRepository: helioneto144/financebr
Length of output: 1230
🏁 Script executed:
# Look for CategoriesPage.tsx and check line 121 area
find frontend/src -name 'CategoriesPage.tsx' -o -name 'CategoriesPage.ts' -o -name 'CategoriesPage.jsx'Repository: helioneto144/financebr
Length of output: 103
🏁 Script executed:
# Check CategoriesPage.tsx around line 121 for the modal
wc -l frontend/src/pages/CategoriesPage.tsx && echo "---" && sed -n '110,135p' frontend/src/pages/CategoriesPage.tsxRepository: helioneto144/financebr
Length of output: 1107
🏁 Script executed:
# Search for all fixed-position elements in the frontend
grep -r "fixed" frontend/src --include="*.tsx" --include="*.jsx" -n | grep -E "(className|position)" | head -20Repository: helioneto144/financebr
Length of output: 250
🏁 Script executed:
# Specifically search for position: fixed or fixed className patterns
rg "position:\s*fixed|className=\"[^\"]*fixed[^\"]*" frontend/src -A 2 -B 2Repository: helioneto144/financebr
Length of output: 636
🏁 Script executed:
# View complete Layout.tsx
cat -n frontend/src/components/Layout.tsxRepository: helioneto144/financebr
Length of output: 1932
🏁 Script executed:
# Check CSS documentation behavior - backdrop-filter creates containing block
# Let's also check if there are other modals or fixed elements
rg "position.*fixed|fixed.*inset" frontend/src --type=js -c | head -20Repository: helioneto144/financebr
Length of output: 48
🏁 Script executed:
# Check if the modal is actually rendered as a portal or inside Layout
grep -n "createPortal\|Portal\|Outlet" frontend/src/components/Layout.tsxRepository: helioneto144/financebr
Length of output: 136
🏁 Script executed:
# Check if there are any Portal implementations or ReactDOM usage
rg "createPortal|Portal|ReactDOM" frontend/src --include="*.tsx" --include="*.ts"Repository: helioneto144/financebr
Length of output: 507
🏁 Script executed:
# Check the actual behavior: is the modal using portal or direct rendering?
cat -n frontend/src/pages/CategoriesPage.tsx | grep -A 5 -B 5 "showModal &&"Repository: helioneto144/financebr
Length of output: 679
🏁 Script executed:
# Check for Portal usage with corrected rg syntax
rg "createPortal|Portal" frontend/srcRepository: helioneto144/financebr
Length of output: 48
🏁 Script executed:
# Look for any fixed positioning in other components
rg "fixed" frontend/src -g "*.tsx" -B 2 -A 2 | head -40Repository: helioneto144/financebr
Length of output: 636
🏁 Script executed:
# Verify if the modal actually needs viewport positioning or if relative to parent is intentional
grep -r "showModal" frontend/src/pages/CategoriesPage.tsx -B 10 | head -30Repository: helioneto144/financebr
Length of output: 661
🏁 Script executed:
# Check the exact structure of how Outlet is nested
sed -n '25,32p' frontend/src/components/Layout.tsxRepository: helioneto144/financebr
Length of output: 530
🏁 Script executed:
# Check if there are other pages with fixed elements that might be affected
find frontend/src/pages -name "*.tsx" -exec grep -l "fixed" {} \;Repository: helioneto144/financebr
Length of output: 103
🌐 Web query:
CSS backdrop-filter containing block stacking context fixed positioning
💡 Result:
backdrop-filter(when notnone) creates a new stacking context, so it can change howz-indexand painting order behave for the element and its descendants. [1][2]- It can also establish a containing block for positioned descendants; as a result, a descendant with
position: fixedmay be fixed to that ancestor’s padding box instead of the viewport (often experienced as “fixed stops being fixed”). [1][3] - This behavior has been a long-standing real‑world gotcha/bug surface area in browsers (notably WebKit/Safari), e.g. reports of
backdrop-filter“restricting”position: fixedchildren. [4]
Common workaround: move the position: fixed element outside any ancestor that has backdrop-filter (or apply the blur on a separate overlay/pseudo-element that is not an ancestor of the fixed element). [3]
Sources:
[1] web.dev – “Create OS-style backgrounds with backdrop-filter” https://web.dev/articles/backdrop-filter
[2] MDN – “Stacking context” https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Positioned_layout/Stacking_context
[3] Stack Overflow – “modal is constrained to parent when backdrop-filter is applied” https://stackoverflow.com/questions/74961395/modal-is-constrained-to-parent-when-backdrop-filter-is-applied
[4] WebKit Bug 215256 – “backdrop-filter restricts child elements with position: fixed” https://bugs.webkit.org/show_bug.cgi?id=215256
Fixed-position modal is constrained by relative-positioned ancestors.
The modal at line 121 of CategoriesPage.tsx uses position: fixed inset-0, but it's rendered inside Layout's content wrapper (line 28) which has relative z-10 positioning. This creates a containing block that constrains the fixed-position modal to that ancestor instead of the viewport, causing incorrect positioning and preventing full-screen behavior.
Consider one of these solutions:
- Render modal using React Portal to
document.bodyto escape the containing block - Remove
relativepositioning from the content wrapper if it's not essential for other layout needs - Implement a modal management system that renders at the document root
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@frontend/src/components/Layout.tsx` at line 11, The fixed-position modal in
CategoriesPage.tsx (uses "position: fixed inset-0") is being constrained by
Layout.tsx's content wrapper which has "relative z-10" (the wrapper div with
className including "relative z-10"); to fix, either 1) move the modal out of
that wrapper by rendering it via a React Portal to document.body (use
createPortal in the CategoriesPage modal component), or 2) remove the "relative"
from the Layout content wrapper div in Layout.tsx if that relative isn't
required, or 3) implement a top-level modal root/manager that mounts modals at
the document root; choose one approach and update the modal rendering
(CategoriesPage.tsx modal component) and/or Layout.tsx wrapper accordingly so
the modal's fixed positioning is relative to the viewport.
🎨 Resumo
Redesign visual completo do Dashboard, Sidebar e Layout com estética glassmorphism premium dark mode.
🖼️ Assets gerados (NanoBanana)
frontend/public/img/bg.pngfrontend/public/img/sprite.pngMudanças por arquivo
Layout.tsxblur-[100px])from-brand-900/20)Sidebar.tsxbackdrop-blur-2xlebg-zinc-950/40bg-white/10+ borda interna + fill gradiente verdedrop-shadowbrilhanteDashboardPage.tsxKPI Cards:
bg-zinc-900/30 backdrop-blur-xl)from-brand-500/5)drop-shadow-mdCharts Grid:
Seções (Pie/Gastos/Transações):
hover:border-white/10hover:bg-white/[0.02], ícone com glow verdedrop-shadowesmeralda-translate-y-1)Checklist
npm run build)/public/img/(servidos estaticamente pelo Vite)Summary by CodeRabbit