Jiseoup/showmycodePublic
EN|KO
  • Code
  • Commits
  • Pull Requests
← Back to list

Merge pull request #13 from Jiseoup/fix/pr-label-light-mode-contrast

fix: improve PR label contrast in light mode

JiseoupJISUB LIM · May 20, 202623fd650

Files changed4+49 -34

Changed files

+49 -34 · 4

@@ -1,7 +1,7 @@
import Link from "next/link";
import Image from "next/image";
import { getPull, getPullFiles, getPullCommits } from "@/lib/github";
-import { formatDate } from "@/lib/utils";
+import { formatDate, labelStyle } from "@/lib/utils";
import { getDictionary, type Locale } from "@/lib/i18n.server";
import { FilesChangedWithTree } from "@/components/FilesChangedWithTree";
import { MarkdownBody } from "@/components/MarkdownBody";
@@ -106,22 +106,15 @@ export default async function PullDetailPage({ params, searchParams }: Props) {
{pr.labels.length > 0 && (
<div className="mt-2 flex flex-wrap items-center gap-1.5">
- {pr.labels.map((l) => {
- const safeColor = /^[0-9a-fA-F]{6}$/.test(l.color) ? l.color : "8b949e";
- return (
- <span
- key={l.name}
- className="rounded px-1.5 py-0.5 text-xs"
- style={{
- background: `#${safeColor}33`,
- color: `#${safeColor}`,
- border: `1px solid #${safeColor}55`,
- }}
- >
- {l.name}
- </span>
- );
- })}
+ {pr.labels.map((l) => (
+ <span
+ key={l.name}
+ className="gh-label rounded px-1.5 py-0.5 text-xs"
+ style={labelStyle(l.color)}
+ >
+ {l.name}
+ </span>
+ ))}
</div>
)}
</div>
@@ -1,7 +1,7 @@
import Link from "next/link";
import Image from "next/image";
import { getPulls } from "@/lib/github";
-import { formatDate } from "@/lib/utils";
+import { formatDate, labelStyle } from "@/lib/utils";
import { getDictionary, type Locale } from "@/lib/i18n.server";
const PER_PAGE = Number(process.env.PULLS_PER_PAGE) || 10;
@@ -100,22 +100,15 @@ export default async function PullsPage({ params, searchParams }: Props) {
<span className="text-muted-foreground text-xs">
{pr.user.login} · {formatDate(pr.created_at, lang)}
</span>
- {pr.labels.map((l) => {
- const safeColor = /^[0-9a-fA-F]{6}$/.test(l.color) ? l.color : "8b949e";
- return (
- <span
- key={l.name}
- className="rounded px-1.5 py-0.5 text-xs"
- style={{
- background: `#${safeColor}33`,
- color: `#${safeColor}`,
- border: `1px solid #${safeColor}55`,
- }}
- >
- {l.name}
- </span>
- );
- })}
+ {pr.labels.map((l) => (
+ <span
+ key={l.name}
+ className="gh-label rounded px-1.5 py-0.5 text-xs"
+ style={labelStyle(l.color)}
+ >
+ {l.name}
+ </span>
+ ))}
</div>
</div>
</Link>
@@ -79,6 +79,21 @@
user-select: none;
}
+/* GitHub-style PR labels. Light mode uses the solid label color with a */
+/* readable black/white text picked in JS via WCAG luminance. Dark mode */
+/* tints the same color into a low-alpha background to keep contrast. */
+.gh-label {
+ background: var(--label);
+ color: var(--label-fg);
+ border: 1px solid var(--label);
+}
+
+.dark .gh-label {
+ background: color-mix(in srgb, var(--label) 20%, transparent);
+ color: var(--label);
+ border-color: color-mix(in srgb, var(--label) 33%, transparent);
+}
+
/* Shiki dark mode. */
.dark .shiki,
.dark .shiki span {
@@ -1,4 +1,5 @@
import { clsx, type ClassValue } from "clsx";
+import type { CSSProperties } from "react";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
@@ -13,6 +14,19 @@ export function formatDate(iso: string, lang = "ko") {
});
}
+export function labelStyle(color: string): CSSProperties {
+ const safe = /^[0-9a-fA-F]{6}$/.test(color) ? color : "8b949e";
+ const r = parseInt(safe.slice(0, 2), 16);
+ const g = parseInt(safe.slice(2, 4), 16);
+ const b = parseInt(safe.slice(4, 6), 16);
+ // WCAG relative luminance — picks readable black/white text in light mode.
+ const luminance = (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255;
+ return {
+ "--label": `#${safe}`,
+ "--label-fg": luminance > 0.5 ? "#000" : "#fff",
+ } as CSSProperties;
+}
+
export function getLanguage(filename: string) {
const ext = filename.split(".").pop() ?? "";
const map: Record<string, string> = {