Skip to content

refactor(frontend): redesign SVG embed card for cleaner visual - #384

Merged
junhoyeo merged 3 commits into
junhoyeo:mainfrom
hellosunghyun:refactor/embed-card-redesign
Apr 2, 2026
Merged

refactor(frontend): redesign SVG embed card for cleaner visual#384
junhoyeo merged 3 commits into
junhoyeo:mainfrom
hellosunghyun:refactor/embed-card-redesign

Conversation

@hellosunghyun

@hellosunghyun hellosunghyun commented Apr 1, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Redesign the profile embed SVG card with a cleaner, GitHub Primer-inspired visual language
  • Fix token number overflow by auto-scaling font size for long values
  • Replace "README EMBED" eyebrow with a compact bar-chart brand icon + "Tokscale Stats"

What Changed

Visual

Functional

  • fitValueFontSize() — new auto-scaling function that shrinks oversized metric values (e.g. "15,726,314,363" renders at 20px instead of overflowing at 28px)
  • Floating-point cleanupMath.round() on computed display-name x-position to avoid ugly decimals in SVG attributes
  • Removed unused importformatCompact was imported but never directly referenced

Tests

  • Updated all assertions to match the new gradient IDs, color values, and card structure
  • Added new test: auto-scales font size for very long token values
  • Restored existing test comment explaining raw-vs-escaped width measurement behavior

Full Changelog: renderProfileEmbedSvg.ts + renderProfileEmbedSvg.test.ts — no other files touched.


Summary by cubic

Redesigned the profile embed SVG for a cleaner, Primer-inspired look and added an optional contributions graph. Long metric values now auto-fit, and the error card matches the new style.

  • New Features

    • Brand header with a bar-chart icon + “Tokscale Stats” and a compact rank badge.
    • Metric cards with left accent bars and rank-aware colors; tokens use token-grad, cost is green; values auto-fit to prevent overflow.
    • Optional GitHub-style contribution graph via graph=1/true: theme-aware cells with day/month labels; increases card height; ignored in compact mode.
  • Refactors

    • Simplified to a single gradient background with a subtle divider and updated Primer palette.
    • Updated theme shape and IDs (bg, glow, divider-grad, acc-*, error err-bg); removed formatCompact; rounded display-name x-position.
    • API reads graph from the query and includes contributions from getUserEmbedContributions (built from dailyBreakdown + submissions, intensity 0–4, cached 60s). Tests updated for the new structure/colors, long-value scaling, and graph rendering.

Written for commit c5e7c70. Summary will update on new commits.

Copilot AI review requested due to automatic review settings April 1, 2026 13:38
@vercel

vercel Bot commented Apr 1, 2026

Copy link
Copy Markdown
Contributor

@hellosunghyun is attempting to deploy a commit to the Inevitable Team on Vercel.

A member of the Team first needs to authorize it.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR redesigns the profile embed SVG card in packages/frontend to use a cleaner, GitHub Primer-inspired visual style while improving metric rendering for long numeric values.

Changes:

  • Reworked the embed SVG layout (new gradients, border/glow, brand icon header, metric accent bars, updated palette).
  • Added fitValueFontSize() to auto-scale oversized metric values to prevent overflow.
  • Updated/expanded tests to match the new SVG structure, colors, and font-scaling behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
packages/frontend/src/lib/embed/renderProfileEmbedSvg.ts Implements the redesigned SVG markup, palette, accent gradients, and auto-fit font sizing.
packages/frontend/tests/lib/renderProfileEmbedSvg.test.ts Updates assertions for new IDs/colors/structure and adds coverage for long-value font scaling.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 125 to +130
function getRankColor(rank: number | null, palette: ThemePalette): string {
if (rank === 1) return "#EAB308";
if (rank === 2) return "#94A3B8";
if (rank === 3) return "#D97706";
return palette.accentSoft;
if (rank === 1) return palette.rankGold;
if (rank === 2) return palette.rankSilver;
if (rank === 3) return palette.rankBronze;
return palette.rankDefault;
}

Copilot AI Apr 1, 2026

Copy link

Choose a reason for hiding this comment

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

accentRank is defined in ThemePalette/THEMES but never used. As a result, non-medal ranks currently use rankDefault (brand blue) for both the rank value color and the accent-bar gradient via getRankColor(), which doesn't match the PR description's “amber for rank” default. Consider using palette.accentRank for the rank card accent (and reserving rankDefault/title for the value), or remove accentRank if the default should be blue.

Copilot uses AI. Check for mistakes.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 issue found across 2 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/frontend/src/lib/embed/renderProfileEmbedSvg.ts">

<violation number="1" location="packages/frontend/src/lib/embed/renderProfileEmbedSvg.ts:225">
P2: `rankAccent` is computed identically to `rankColor` via `getRankColor()`, so the accent bar for non-medal ranks renders as blue (`rankDefault`) instead of the intended amber. Meanwhile `palette.accentRank` (`#D29922` / `#9A6700`) is defined in both themes but never referenced. Use `palette.accentRank` here for the accent bar default, and let `getRankColor()` continue to drive the value text color.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

const metricsW = width - px * 2;
const metricW = (metricsW - metricsGap * 2) / 3;
const rankColor = getRankColor(data.stats.rank, palette);
const rankAccent = getRankColor(data.stats.rank, palette);

@cubic-dev-ai cubic-dev-ai Bot Apr 1, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: rankAccent is computed identically to rankColor via getRankColor(), so the accent bar for non-medal ranks renders as blue (rankDefault) instead of the intended amber. Meanwhile palette.accentRank (#D29922 / #9A6700) is defined in both themes but never referenced. Use palette.accentRank here for the accent bar default, and let getRankColor() continue to drive the value text color.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/frontend/src/lib/embed/renderProfileEmbedSvg.ts, line 225:

<comment>`rankAccent` is computed identically to `rankColor` via `getRankColor()`, so the accent bar for non-medal ranks renders as blue (`rankDefault`) instead of the intended amber. Meanwhile `palette.accentRank` (`#D29922` / `#9A6700`) is defined in both themes but never referenced. Use `palette.accentRank` here for the accent bar default, and let `getRankColor()` continue to drive the value text color.</comment>

<file context>
@@ -160,117 +201,118 @@ function renderProfileCardSvg(data: UserEmbedStats, options: RenderProfileEmbedO
+  const metricsW = width - px * 2;
+  const metricW = (metricsW - metricsGap * 2) / 3;
   const rankColor = getRankColor(data.stats.rank, palette);
+  const rankAccent = getRankColor(data.stats.rank, palette);
 
   return `<?xml version="1.0" encoding="UTF-8"?>
</file context>
Suggested change
const rankAccent = getRankColor(data.stats.rank, palette);
const rankAccent = (data.stats.rank && data.stats.rank <= 3) ? getRankColor(data.stats.rank, palette) : palette.accentRank;
Fix with Cubic

…-redesign

# Conflicts:
#	packages/frontend/src/lib/embed/renderProfileEmbedSvg.ts
@hellosunghyun

Copy link
Copy Markdown
Contributor Author

Combined Preview

This PR now includes a merge commit from the other related PR to show the combined result and avoid confusion during review.

Dark Theme

dark

Light Theme

light

These previews show both PRs (#384 visual redesign + #386 contribution graph) merged together.

@junhoyeo junhoyeo left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

LGTM — clean Primer-inspired redesign with solid auto-scaling logic. Review suggestions will be addressed in a follow-up PR.

@junhoyeo
junhoyeo merged commit 1c77e7b into junhoyeo:main Apr 2, 2026
3 of 4 checks passed
junhoyeo added a commit that referenced this pull request Apr 2, 2026
fix(frontend): address review suggestions from embed card PRs (#384, #386)
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.

3 participants