Skip to content

feat(ui): glassmorphism visual overhaul — premium dark mode ✨#1

Open
helioneto144 wants to merge 1 commit into
mainfrom
feat/glassmorphism-visual-overhaul
Open

feat(ui): glassmorphism visual overhaul — premium dark mode ✨#1
helioneto144 wants to merge 1 commit into
mainfrom
feat/glassmorphism-visual-overhaul

Conversation

@helioneto144
Copy link
Copy Markdown
Owner

@helioneto144 helioneto144 commented Mar 10, 2026

🎨 Resumo

Redesign visual completo do Dashboard, Sidebar e Layout com estética glassmorphism premium dark mode.


🖼️ Assets gerados (NanoBanana)

Arquivo Descrição
frontend/public/img/bg.png Textura 8K dark-mode com ruído sutil e glows neon esmeralda/violeta
frontend/public/img/sprite.png Sprites 3D de ilustrações financeiras com efeito glossy iridescente

Mudanças por arquivo

Layout.tsx

  • Background agora é uma camada tripla: bg.png → overlay preto/60 → backdrop-blur sutil
  • Sprite decorativo flutuando no canto superior direito (animated pulse)
  • Orb ambiente verde-esmeralda no fundo (radial blur blur-[100px])
  • Gradiente do topo intensificado (from-brand-900/20)

Sidebar.tsx

  • Painel de vidro com backdrop-blur-2xl e bg-zinc-950/40
  • Glow orb ambiente no topo da sidebar
  • Logo com texto gradiente iridescente + flash hover
  • Nav items — estado ativo redesenhado:
    • bg-white/10 + borda interna + fill gradiente verde
    • Indicador lateral neon com drop-shadow brilhante
    • Ícones com glow verde no estado ativo
  • Badge 'Beta' com brilho indigo mais intenso

DashboardPage.tsx

KPI Cards:

  • Painéis de vidro (bg-zinc-900/30 backdrop-blur-xl)
  • Overlay gradiente surge no hover (from-brand-500/5)
  • Ícone anima scale+rotate no hover
  • Valor monetário com micro-translate + drop-shadow-md

Charts Grid:

  • Glow ambiente atrás do grid inteiro
  • Cada card tem orb no canto que brilha no hover

Seções (Pie/Gastos/Transações):

  • Bordas de vidro com hover:border-white/10
  • Linhas de transação: hover:bg-white/[0.02], ícone com glow verde
  • Valores de receita com drop-shadow esmeralda
  • Cards de conta: lift no hover (-translate-y-1)

Checklist

  • Build compila sem erros (npm run build)
  • Sem breaking changes em lógica ou API
  • Responsive mantido (mobile/tablet/desktop)
  • Assets em /public/img/ (servidos estaticamente pelo Vite)

Quer dar merge e ver no browser? Rode financebr start depois do merge 🚀

Summary by CodeRabbit

  • Style
    • Modernized dashboard interface with glassmorphism effects and smooth animations
    • Enhanced sidebar with improved hover states and interactive visual feedback
    • Updated KPI cards, charts, data cards, and transaction lists with refined styling
    • Added decorative background layers and gradient overlays for improved visual depth
    • Enhanced active state indicators with glowing effects and better visual hierarchy

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>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 10, 2026

📝 Walkthrough

Walkthrough

Three 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

Cohort / File(s) Summary
UI & Visual Design System Refresh
frontend/src/components/Layout.tsx, frontend/src/components/Sidebar.tsx, frontend/src/pages/DashboardPage.tsx
Comprehensive styling overhaul across layout, navigation, and dashboard components. Introduces glass-morphism effects (backdrop blur, translucent overlays), layered animated backgrounds with sprite positioning, gradient accents, enhanced active states with glow effects, and hover-driven transitions. Adds decorative non-interactive elements (ambient orbs, glowing accents) and updates opacity/z-index layering throughout. No functional logic changes; pure visual enhancements.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Whiskers twitching with delight,
Glass and glow now shine so bright,
Layers dance with hover grace,
Gradients bloom in every space,
The dashboard dreams in frosted light!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(ui): glassmorphism visual overhaul — premium dark mode ✨' directly and accurately describes the main change—a comprehensive UI redesign implementing a glassmorphism aesthetic across Layout, Sidebar, and DashboardPage components.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/glassmorphism-visual-overhaul

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 and z-[999999] on nav links are unusually high. This pattern often emerges when fighting stacking context issues rather than properly managing them. With the new backdrop-blur in 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 ChartCard component 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: Consider prefers-reduced-motion for animated decorative elements.

The sprite uses animate-pulse combined with blur-[1px]. Users who prefer reduced motion (accessibility setting) would benefit from disabling this animation. Tailwind provides motion-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

📥 Commits

Reviewing files that changed from the base of the PR and between a9a7602 and 2af2aa5.

⛔ Files ignored due to path filters (2)
  • frontend/public/img/bg.png is excluded by !**/*.png
  • frontend/public/img/sprite.png is excluded by !**/*.png
📒 Files selected for processing (3)
  • frontend/src/components/Layout.tsx
  • frontend/src/components/Sidebar.tsx
  • frontend/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" />
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 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 -50

Repository: 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.tsx

Repository: 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.tsx

Repository: 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 -20

Repository: 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 2

Repository: helioneto144/financebr

Length of output: 636


🏁 Script executed:

# View complete Layout.tsx
cat -n frontend/src/components/Layout.tsx

Repository: 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 -20

Repository: 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.tsx

Repository: 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/src

Repository: 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 -40

Repository: 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 -30

Repository: 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.tsx

Repository: 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 not none) creates a new stacking context, so it can change how z-index and 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: fixed may 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: fixed children. [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:

  1. Render modal using React Portal to document.body to escape the containing block
  2. Remove relative positioning from the content wrapper if it's not essential for other layout needs
  3. 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant