Skip to content

polish: improve UI feel across the board#108

Closed
TerrifiedBug wants to merge 3 commits intomainfrom
ui/interface-polish
Closed

polish: improve UI feel across the board#108
TerrifiedBug wants to merge 3 commits intomainfrom
ui/interface-polish

Conversation

@TerrifiedBug
Copy link
Copy Markdown
Owner

Summary

Systematic UI polish pass across 37 files — focused on making interactions feel tactile and preventing visual jank on dynamic content.

Changes

Transitions & Animation

  • Replace transition-all with specific transition properties (transition-colors, transition-shadow, etc.) to avoid animating layout-triggering properties
  • Add active:scale-[0.96] to Button component for tactile press feedback

Typography & Layout Stability

  • Add tabular-nums to all dynamically updating numbers (~20 files) to prevent layout shift on value changes
  • Add text-wrap: balance on headings and text-wrap: pretty on body text across Card, Dialog, PageHeader, EmptyState, auth layout, and not-found page

Visual Depth & Polish

  • Add layered box-shadow to Card component for natural depth
  • Add subtle outline to AvatarImage for edge definition on same-background avatars
  • Fix concentric border radius on flow nodes (overflow-hidden + remove inner rounded-t-lg)

Interaction Improvements

  • Add optional pulse prop to StatusDot for liveness indication
  • Expand hit areas on small icon buttons (dashboard tab actions, update banner dismiss) with pseudo-element technique
  • Add background-color/color to sidebar menu button transitions for smoother hover states

Verification

  • tsc --noEmit
  • eslint src/
  • pnpm test — 105/105 pass ✅
  • No functional changes — purely visual/interaction improvements

dependabot bot and others added 3 commits March 23, 2026 20:25
…dates

Bumps the npm_and_yarn group with 2 updates in the / directory: [next](https://github.com/vercel/next.js) and [flatted](https://github.com/WebReflection/flatted).


Updates `next` from 16.1.6 to 16.1.7
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](vercel/next.js@v16.1.6...v16.1.7)

Updates `flatted` from 3.4.1 to 3.4.2
- [Commits](WebReflection/flatted@v3.4.1...v3.4.2)

---
updated-dependencies:
- dependency-name: next
  dependency-version: 16.1.7
  dependency-type: direct:production
  dependency-group: npm_and_yarn
- dependency-name: flatted
  dependency-version: 3.4.2
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
- Replace all transition-all with specific transition properties to
  avoid animating layout-triggering properties
- Add active:scale-[0.96] to buttons for tactile press feedback
- Add tabular-nums to all dynamically updating numbers (~20 files)
  to prevent layout shift on value changes
- Add text-wrap: balance on headings, text-wrap: pretty on body text
  across Card, Dialog, PageHeader, EmptyState, auth layout, not-found
- Fix concentric border radius on flow nodes (overflow-hidden + remove
  inner rounded-t-lg)
- Add layered box-shadow to Card component for natural depth
- Add subtle outline to AvatarImage for edge definition
- Add optional pulse prop to StatusDot for liveness indication
- Expand hit areas on small icon buttons (dashboard tab actions,
  update banner dismiss) with pseudo-element technique
- Add background-color/color to sidebar menu button transitions
  for smoother hover states
@github-actions github-actions bot added the dependencies Pull requests that update a dependency file label Mar 24, 2026
@TerrifiedBug
Copy link
Copy Markdown
Owner Author

Duplicate — this branch was already merged in #107.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 24, 2026

Greptile Summary

A broad UI polish pass across 37 source files with no functional changes — replacing transition-all with targeted transition properties, adding tabular-nums to ~20 numeric displays, applying text-balance/text-pretty to headings and body copy, expanding small hit areas via pseudo-elements, and fixing the concentric border-radius on flow nodes.

Key changes:

  • Button: transition-all → explicit properties + active:scale-[0.96] press feedback; link variant opts out with active:!scale-100
  • Flow nodes (source-node, sink-node, transform-node): overflow-hidden on outer container + removal of rounded-t-lg from header bar correctly fixes the rounded-corner bleed issue
  • StatusDot: New pulse prop backed by a status-pulse keyframe animation — works as an opacity fade but the per-variant shadow-[0_0_0_0_var(--status-...)] classes in pulseStyles are dead code because the animation overrides box-shadow at all keyframes; additionally, the glow color uses currentColor (inherited text color) instead of the intended status CSS variable, so all variants will pulse with the same color regardless of the variant passed
  • Hit areas: before:absolute before:-inset-* pseudo-element technique correctly applied to dashboard tab actions and update banner dismiss button
  • Dependency bump: Next.js 16.1.6 → 16.1.7 (patch); lockfile updated accordingly

Confidence Score: 4/5

  • Safe to merge — purely visual changes with one minor visual bug in the new pulse feature.
  • All 40 changes are cosmetic/interaction polish with no functional, security, or data-path impact. The only real defect is in the new StatusDot pulse prop: the per-variant shadow classes are overridden by the animation and the glow color resolves to the inherited text color rather than the intended status variable. This is a P2 visual bug in a brand-new optional feature, not a regression.
  • src/components/ui/status-dot.tsx and src/app/globals.css — the status-pulse keyframe / pulseStyles interaction needs a small fix so the glow color matches the status variant.

Important Files Changed

Filename Overview
src/components/ui/status-dot.tsx Adds optional pulse prop; the per-variant shadow-[...] classes in pulseStyles are dead code overridden by the animation, and the glow uses currentColor (inherited text) rather than the intended status CSS variable.
src/app/globals.css Adds @keyframes status-pulse for the StatusDot pulse feature; keyframe uses currentColor for glow color — correct only if the element also exposes the status color via color, which it currently does not.
src/components/ui/button.tsx Replaces transition-all with specific properties and adds active:scale-[0.96] for press feedback; link variant correctly overrides with active:!scale-100.
src/components/ui/card.tsx Adds layered box-shadow for depth and text-balance/text-pretty to title and description; purely cosmetic, no issues.
src/components/flow/source-node.tsx Adds overflow-hidden to outer container and removes rounded-t-lg from header bar, correctly fixing the concentric border-radius issue.
src/components/flow/sink-node.tsx Same concentric border-radius fix as source-node; adds tabular-nums to metrics display.
src/components/flow/transform-node.tsx Same concentric border-radius fix; adds tabular-nums to both metrics display variants.
src/app/(dashboard)/page.tsx Correctly expands hit areas for edit/delete icon buttons using relative + before:absolute before:-inset-1; adds tabular-nums to stats display.
src/components/update-banner.tsx Expands dismiss button hit area using before:absolute before:-inset-2; uses relative correctly on the button.
src/components/ui/avatar.tsx Adds subtle outline to AvatarImage for edge definition; rounded-full correctly constrains outline shape in modern browsers.
src/components/ui/sidebar.tsx Adds background-color and color to menu button transition list; replaces transition-all on SidebarRail — no issues.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["StatusDot rendered\n(pulse=true, variant='healthy')"] --> B["dotStyles applied\nbg-status-healthy"]
    A --> C["pulseStyles applied\nshadow-0-0-0-0-var--status-healthy\nanimate-status-pulse"]
    C --> D{"CSS Animation\nstatus-pulse runs"}
    D --> E["0%/100%: box-shadow 0 0 0 0 currentColor\nopacity: 1"]
    D --> F["50%: box-shadow 0 0 0 4px transparent\nopacity: 0.7"]
    E --> G["Animation OVERRIDES\nTailwind shadow class\n(dead code)"]
    E --> H["currentColor resolves to\ninherited text color\n(not --status-healthy)"]
    H --> I["All variants glow\nwith same color ⚠️"]
    F --> J["Opacity fades to 0.7\n(visible pulse ✓)"]
Loading

Comments Outside Diff (1)

  1. src/components/ui/status-dot.tsx, line 1194-1200 (link)

    P2 shadow-[...] values in pulseStyles are dead code

    The shadow-[0_0_0_0_var(--status-...)] Tailwind classes in pulseStyles have no effect. The status-pulse keyframe animation overrides the box-shadow property at every frame (0%/100% use box-shadow: 0 0 0 0 currentColor, 50% uses box-shadow: 0 0 0 4px transparent), so the Tailwind shadow declaration is always overridden the moment the animation starts.

    As a result, the ripple glow will use currentColor — the inherited text color from the parent element — rather than the intended per-variant status color (e.g., --status-healthy). The <span> has no explicit color class, so it inherits from its container (e.g., foreground white in dark mode), meaning all variants will pulse with the same color.

    The simplest fix is to add a matching text-* color alongside each bg-* so currentColor resolves to the right value:

    const dotStyles: Record<StatusVariant, string> = {
      healthy: "bg-status-healthy text-status-healthy",
      degraded: "bg-status-degraded text-status-degraded",
      error: "bg-status-error text-status-error",
      neutral: "bg-status-neutral text-status-neutral",
      info: "bg-status-info text-status-info",
    };

    And then the shadow-[...] entries in pulseStyles can be dropped since they serve no purpose.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: src/components/ui/status-dot.tsx
    Line: 1194-1200
    
    Comment:
    **`shadow-[...]` values in `pulseStyles` are dead code**
    
    The `shadow-[0_0_0_0_var(--status-...)]` Tailwind classes in `pulseStyles` have no effect. The `status-pulse` keyframe animation overrides the `box-shadow` property at every frame (0%/100% use `box-shadow: 0 0 0 0 currentColor`, 50% uses `box-shadow: 0 0 0 4px transparent`), so the Tailwind shadow declaration is always overridden the moment the animation starts.
    
    As a result, the ripple glow will use `currentColor` — the inherited text color from the parent element — rather than the intended per-variant status color (e.g., `--status-healthy`). The `<span>` has no explicit `color` class, so it inherits from its container (e.g., foreground white in dark mode), meaning all variants will pulse with the same color.
    
    The simplest fix is to add a matching `text-*` color alongside each `bg-*` so `currentColor` resolves to the right value:
    
    ```tsx
    const dotStyles: Record<StatusVariant, string> = {
      healthy: "bg-status-healthy text-status-healthy",
      degraded: "bg-status-degraded text-status-degraded",
      error: "bg-status-error text-status-error",
      neutral: "bg-status-neutral text-status-neutral",
      info: "bg-status-info text-status-info",
    };
    ```
    
    And then the `shadow-[...]` entries in `pulseStyles` can be dropped since they serve no purpose.
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/components/ui/status-dot.tsx
Line: 1194-1200

Comment:
**`shadow-[...]` values in `pulseStyles` are dead code**

The `shadow-[0_0_0_0_var(--status-...)]` Tailwind classes in `pulseStyles` have no effect. The `status-pulse` keyframe animation overrides the `box-shadow` property at every frame (0%/100% use `box-shadow: 0 0 0 0 currentColor`, 50% uses `box-shadow: 0 0 0 4px transparent`), so the Tailwind shadow declaration is always overridden the moment the animation starts.

As a result, the ripple glow will use `currentColor` — the inherited text color from the parent element — rather than the intended per-variant status color (e.g., `--status-healthy`). The `<span>` has no explicit `color` class, so it inherits from its container (e.g., foreground white in dark mode), meaning all variants will pulse with the same color.

The simplest fix is to add a matching `text-*` color alongside each `bg-*` so `currentColor` resolves to the right value:

```tsx
const dotStyles: Record<StatusVariant, string> = {
  healthy: "bg-status-healthy text-status-healthy",
  degraded: "bg-status-degraded text-status-degraded",
  error: "bg-status-error text-status-error",
  neutral: "bg-status-neutral text-status-neutral",
  info: "bg-status-info text-status-info",
};
```

And then the `shadow-[...]` entries in `pulseStyles` can be dropped since they serve no purpose.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "chore: add .gsd to .gitignore" | Re-trigger Greptile

@TerrifiedBug TerrifiedBug deleted the ui/interface-polish branch March 26, 2026 19:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant