@@ -100,8 +102,17 @@ export default function RadarChart({ languagesA, languagesB, labelA, labelB }: R
width="320"
height="300"
viewBox="0 0 320 300"
+ role="img"
+ aria-labelledby="radar-chart-title radar-chart-desc"
className="w-full h-full overflow-visible"
>
+
+ Language Dominance Radar Chart comparing {labelA} and {labelB}
+
+
+ Radar chart visualizing language distribution percentages for top languages across
+ both profiles.
+
diff --git a/docs/customization.md b/docs/customization.md
index 773d3a701..19c9009cf 100644
--- a/docs/customization.md
+++ b/docs/customization.md
@@ -59,45 +59,45 @@ URL Parameter > Theme Default > System Fallback
> All parameters below are optional except `user`. Append them to the base URL as query string key-value pairs (e.g. `?user=YOUR_USERNAME&theme=neon&size=large`). Boolean parameters accept `true` or `false`. Hex color values are provided **without** the `#` prefix.
-| Parameter | Description | Default | Allowed Values / Constraints | Example |
-| ----------------- | ----------------------------------------------------------------------------------------------- | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | --- | ---------- | ----------------------------- | ------ | ------------------------------- | ---------------- |
-| `user` | GitHub username to render (Required) | — | Any valid GitHub username | `?user=jhasourav07` |
-| `theme` | Preset theme name | `dark` | `auto`, `dark`, `neon`, `dracula`, `github`, `light`, `gruvbox`, `random`, etc. | `?theme=dracula` |
-| `bg` | Background color | Theme default | Hex color code (without `#`) | `?bg=0d1117` |
-| `accent` | Tower & glow color | Theme default | Hex color code (without `#`) | `?accent=58a6ff` |
-| `text` | Label & stat text color | Theme default | Hex color code (without `#`) | `?text=c9d1d9` |
-| `radius` | Border corner radius in pixels | `8` | Numeric value | `?radius=16` |
-| `border` | Custom stroke color around the SVG container | — | Hex color code (without `#`) | `?border=ff0000` |
-| `speed` | Radar scan duration | `8s` | `2s`–`20s` | `?speed=4s` |
-| `scale` | Tower height scaling | `linear` | `linear`, `log`, `sqrt` | `?scale=sqrt` |
-| `size` | Badge dimensions | `medium` | `small`, `medium`, `large` | `?size=large` |
-| `font` | Custom font for text | Default typography | Any valid Google Font name | `?font=Orbitron` |
-| `refresh` | Bypass cache for real-time data | `false` | `true`, `false` | `?refresh=true` |
-| `year` | Calendar year to render | Current year | `2023`, `2024`, etc. | `?year=2023` |
-| `hide_title` | Hide GitHub username/title | `false` | `true`, `false` | `?hide_title=true` |
-| `custom_title` | Custom header title text | — | Any text string (XML-escaped) | `?custom_title=My%20Pulse` |
-| `custom_subtitle` | Custom subtitle text right below title | — | Any text string (XML-escaped) | `?custom_subtitle=Dev` |
-| `hide_background` | Remove the background rect | `false` | `true`, `false` | `?hide_background=true` |
-| `hide_stats` | Hide bottom row displaying stats | `false` | `true`, `false` | `?hide_stats=true` |
-| `tz` | IANA timezone | `UTC` | Valid IANA timezone | `?tz=Asia/Kolkata` |
-| `lang` | Language code for labels | `en` | `en`, `es`, `hi`, `fr`, `pt`, `ko`, `ja`, `de`, `zh` | `?lang=hi` |
-| `view` | Rendering mode | `default` | `default`, `monthly`, `heatmap`, `pulse`, `skyline`, `languages`, `constellation`, `weekday`, `punchcard`, `radar`, `doughnut`, `pie`, `activity_graph`, `commit_clock` | `?view=punchcard` |
-| `entrance` | Entrance animation for towers | `rise` | `rise`, `fade`, `slide`, `none` | `?entrance=fade` |
-| `delta_format` | Month-over-month delta format (`view=monthly`) | `percent` | `percent`, `absolute`, `both` | `?delta_format=absolute` |
-| `width` | Custom width for SVG canvas (`view=monthly`, `pulse`, `skyline`) | `300` | Numeric value | `?width=400` |
-| `height` | Custom height for SVG canvas (`view=monthly`, `pulse`, `skyline`) | `120` | Numeric value | `?height=150` |
-| `grace` | Grace period in days before streak resets (see [Grace Period Examples](#grace-period-examples)) | `1` | `0`–`7` | `?grace=2` |
-| `mode` | Base data rendering mode | `commits` | `commits`, `loc` | `?mode=loc` |
-| `repo` | Render monolith for a specific repository | — | `owner/repo` | `?repo=vercel/next.js` |
-| `org` | Organization name to generate a Mega-City for | — | Valid GitHub organization name | `?org=vercel` |
-| `labels` | Render optional isometric month/weekday labels | `false` | `true`, `false` | `?labels=true` |
-| `labelColor` | Custom text color for isometric labels | — | Hex color code (without `#`) | `?labelColor=ffffff` |
-| `versus` | Compare against an opponent side-by-side | — | Any valid GitHub username | `?versus=octocat` |
-| `shading` | Apply intensity-based opacity shading to tower faces | `false` | `true`, `false` | `?shading=true` |
-| `dim_weekends` | Dim weekend towers (Saturdays and Sundays) | `false` | `true`, `false` | `?dim_weekends=true` |
-| `opacity` | Global opacity scalar for tower fill | `1.0` | `0.1`–`1.0` | `?opacity=0.8` |
-| `gradient` | Show volumetric gradients on the floor | `false` | `true`, `false` | `?gradient=true` |
-| `minify` | Enable SVG minification and payload optimization | `true` | `true`, `false` | `?minify=false` |
+| Parameter | Description | Default | Allowed Values / Constraints | Example |
+| ----------------- | ----------------------------------------------------------------------------------------------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- |
+| `user` | GitHub username to render (Required) | — | Any valid GitHub username | `?user=jhasourav07` |
+| `theme` | Preset theme name | `dark` | `auto`, `dark`, `neon`, `dracula`, `github`, `light`, `gruvbox`, `random`, etc. | `?theme=dracula` |
+| `bg` | Background color | Theme default | Hex color code (without `#`) | `?bg=0d1117` |
+| `accent` | Tower & glow color | Theme default | Hex color code (without `#`) | `?accent=58a6ff` |
+| `text` | Label & stat text color | Theme default | Hex color code (without `#`) | `?text=c9d1d9` |
+| `radius` | Border corner radius in pixels | `8` | Numeric value | `?radius=16` |
+| `border` | Custom stroke color around the SVG container | — | Hex color code (without `#`) | `?border=ff0000` |
+| `speed` | Radar scan duration | `8s` | `2s`–`20s` | `?speed=4s` |
+| `scale` | Tower height scaling | `linear` | `linear`, `log`, `sqrt` | `?scale=sqrt` |
+| `size` | Badge dimensions | `medium` | `small`, `medium`, `large` | `?size=large` |
+| `font` | Custom font for text | Default typography | Any valid Google Font name | `?font=Orbitron` |
+| `refresh` | Bypass cache for real-time data | `false` | `true`, `false` | `?refresh=true` |
+| `year` | Calendar year to render | Current year | `2023`, `2024`, etc. | `?year=2023` |
+| `hide_title` | Hide GitHub username/title | `false` | `true`, `false` | `?hide_title=true` |
+| `custom_title` | Custom header title text | — | Any text string (XML-escaped) | `?custom_title=My%20Pulse` |
+| `custom_subtitle` | Custom subtitle text right below title | — | Any text string (XML-escaped) | `?custom_subtitle=Dev` |
+| `hide_background` | Remove the background rect | `false` | `true`, `false` | `?hide_background=true` |
+| `hide_stats` | Hide bottom row displaying stats | `false` | `true`, `false` | `?hide_stats=true` |
+| `tz` | IANA timezone | `UTC` | Valid IANA timezone | `?tz=Asia/Kolkata` |
+| `lang` | Language code for labels | `en` | `en`, `es`, `hi`, `fr`, `pt`, `ko`, `ja`, `de`, `zh` | `?lang=hi` |
+| `view` | Rendering mode | `default` | `default`, `monthly`, `heatmap`, `pulse`, `skyline`, `languages`, `constellation`, `weekday`, `punchcard`, `radar`, `doughnut`, `pie`, `activity_graph`, `commit_clock` | `?view=punchcard` |
+| `entrance` | Entrance animation for towers | `rise` | `rise`, `fade`, `slide`, `none` | `?entrance=fade` |
+| `delta_format` | Month-over-month delta format (`view=monthly`) | `percent` | `percent`, `absolute`, `both` | `?delta_format=absolute` |
+| `width` | Custom width for SVG canvas (`view=monthly`, `pulse`, `skyline`) | `300` | Numeric value | `?width=400` |
+| `height` | Custom height for SVG canvas (`view=monthly`, `pulse`, `skyline`) | `120` | Numeric value | `?height=150` |
+| `grace` | Grace period in days before streak resets (see [Grace Period Examples](#grace-period-examples)) | `1` | `0`–`7` | `?grace=2` |
+| `mode` | Base data rendering mode | `commits` | `commits`, `loc` | `?mode=loc` |
+| `repo` | Render monolith for a specific repository | — | `owner/repo` | `?repo=vercel/next.js` |
+| `org` | Organization name to generate a Mega-City for | — | Valid GitHub organization name | `?org=vercel` |
+| `labels` | Render optional isometric month/weekday labels | `false` | `true`, `false` | `?labels=true` |
+| `labelColor` | Custom text color for isometric labels | — | Hex color code (without `#`) | `?labelColor=ffffff` |
+| `versus` | Compare against an opponent side-by-side | — | Any valid GitHub username | `?versus=octocat` |
+| `shading` | Apply intensity-based opacity shading to tower faces | `false` | `true`, `false` | `?shading=true` |
+| `dim_weekends` | Dim weekend towers (Saturdays and Sundays) | `false` | `true`, `false` | `?dim_weekends=true` |
+| `opacity` | Global opacity scalar for tower fill | `1.0` | `0.1`–`1.0` | `?opacity=0.8` |
+| `gradient` | Show volumetric gradients on the floor | `false` | `true`, `false` | `?gradient=true` |
+| `minify` | Enable SVG minification and payload optimization | `true` | `true`, `false` | `?minify=false` |
---
diff --git a/lib/svg/radar.ts b/lib/svg/radar.ts
index dad6a0dbb..a1b41cef8 100644
--- a/lib/svg/radar.ts
+++ b/lib/svg/radar.ts
@@ -130,8 +130,9 @@ export function generateRadarSVG(
labelsSVG += ` ${RADAR_AXES[i].label}\n`;
}
- // 3. Data Polygon
+ // 3. Data Polygon & Dots
let dataPoints = '';
+ let dotsSVG = '';
for (let i = 0; i < RADAR_AXIS_COUNT; i++) {
const angle = (Math.PI * 2 * i) / RADAR_AXIS_COUNT - Math.PI / 2;
// ensure minimum size for visual appeal
@@ -140,12 +141,17 @@ export function generateRadarSVG(
const x = RADAR_CENTER_X + r * Math.cos(angle);
const y = RADAR_CENTER_Y + r * Math.sin(angle);
dataPoints += `${x},${y} `;
+ const pct = Math.round(metrics[i] * 100);
+ const axisLabel = RADAR_AXES[i].label;
+ dotsSVG += ` \n ${axisLabel}: ${pct}%\n \n`;
}
const dataPolygonSVG = `
-
- `;
+
+ Radar score breakdown for ${safeUser}
+
+${dotsSVG} `;
// CSS Animations
const css = `
diff --git a/types/achievements.ts b/types/achievements.ts
index b8c3d68c6..fd7272287 100644
--- a/types/achievements.ts
+++ b/types/achievements.ts
@@ -3,7 +3,11 @@ export type AchievementTier = 'bronze' | 'silver' | 'gold' | 'platinum' | 'diamo
export type AchievementRarity = 'common' | 'uncommon' | 'rare' | 'epic' | 'legendary' | 'mythic';
export type AchievementCategory =
- 'contribution' | 'pull-request' | 'repository' | 'collaboration' | 'technology';
+ | 'contribution'
+ | 'pull-request'
+ | 'repository'
+ | 'collaboration'
+ | 'technology';
export interface AchievementLevelDef {
tier: AchievementTier;