TRUEBench / src /display /css_html_js.py
송종윤/AI Productivity팀(SR)/삼성전자
Initial commit
8a254d6
custom_css = """
/* Info icon for column tooltips */
.info-icon {
color: #b0b0b0;
font-size: 15px;
margin-left: 4px;
vertical-align: middle;
font-family: Arial, sans-serif;
font-style: normal;
font-weight: bold;
user-select: none;
}
.info-icon:hover {
color: #888;
}
/* Model Name link hover effect */
.pretty-leaderboard-table a:hover {
text-decoration: underline;
color: #1098F7;
cursor: pointer;
}
/* INTRO FEATURE CARDS (for about page) */
.intro-feature-row {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 24px;
margin: 18px 0 !important;
}
.intro-feature-box {
background: linear-gradient(135deg, #f8fafc 60%, #e3e6f3 100%);
border-radius: 18px;
box-shadow: 0 4px 16px rgba(44,62,80,0.08);
padding: 32px 28px;
width: 380px;
min-width: 260px;
max-width: 420px;
text-align: left;
display: flex;
flex-direction: column;
align-items: flex-start;
transition: box-shadow 0.2s;
}
.intro-feature-title {
font-weight: 900;
font-size: 1.45em;
margin-bottom: 12px;
color: #23244a;
}
.intro-feature-desc {
font-size: 1.18em;
color: #444;
margin-bottom: 7px;
}
.intro-feature-icon {
font-size: 2.3em;
margin-bottom: 16px;
color: #1098F7;
}
.intro-feature-box:hover {
box-shadow: 0 0 24px #a5a1ff55, 0 4px 16px rgba(0,0,0,0.18);
transform: translateY(-4px) scale(1.025);
transition: box-shadow 0.2s, transform 0.2s;
cursor: default;
}
@media (prefers-color-scheme: dark) {
.intro-feature-box {
background: linear-gradient(135deg, #23244a 0%, #2a1859 100%) !important;
color: #f5f6f7 !important;
}
.intro-feature-title, .intro-feature-desc {
color: #f5f6f7 !important;
}
}
/* Dataset Sample Button (below feature cards) */
.intro-dataset-btn {
display: inline-block;
background: #1098F7;
color: #fff !important;
border: none;
border-radius: 12px;
font-weight: 700;
font-size: 1.18em;
padding: 16px 36px;
margin: 32px auto 0 auto;
text-align: center;
text-decoration: none;
box-shadow: 0 2px 8px #1098f733;
transition: background 0.18s, color 0.18s, box-shadow 0.18s;
cursor: pointer;
outline: none;
}
.intro-dataset-btn:hover, .intro-dataset-btn:focus {
background: #0a6dc2;
color: #fff !important;
box-shadow: 0 4px 16px #1098f755;
text-decoration: none;
}
@media (prefers-color-scheme: dark) {
.intro-dataset-btn {
background: #1a4b7a;
color: #fff !important;
}
.intro-dataset-btn:hover, .intro-dataset-btn:focus {
background: #1098F7;
color: #fff !important;
}
}
.radar-chart, .plot-container {
display: block;
margin-left: auto;
margin-right: auto;
width: fit-content;
max-width: 100%;
}
/* Ensure injected HTML/Markdown blocks are transparent and text is visible in all color schemes */
.gr-html, .gr-markdown, .gr-html * {
background: transparent !important;
color: inherit !important;
}
.gr-html div, .gr-html body, .gr-markdown div, .gr-markdown body {
background: transparent !important;
color: inherit !important;
}
@media (prefers-color-scheme: dark) {
.gr-html, .gr-markdown, .gr-html *, .gr-markdown * {
color: #f5f6f7 !important;
}
}
@media (prefers-color-scheme: light) {
.gr-html, .gr-markdown, .gr-html *, .gr-markdown * {
color: #23244a !important;
}
}
/* Custom radio styles for category selector */
.cat-btn-radio label {
border-radius: 18px !important;
border: 1.5px solid #d1d5db !important;
background: #f8fafc !important;
color: #222 !important;
font-weight: 600 !important;
cursor: pointer !important;
padding: 8px 20px !important;
box-shadow: 0 2px 8px #e5e7eb88 !important;
margin: 0 !important;
font-size: 1.08rem !important;
transition: background 0.2s, color 0.2s, box-shadow 0.2s, border 0.2s !important;
display: inline-block !important;
}
.cat-btn-radio input[type="radio"] {
display: none !important;
}
.cat-btn-radio input[type="radio"]:checked + label,
.cat-btn-radio label.selected {
background: #1098F7 !important;
color: #fff !important;
border: 1.5px solid #1098F7 !important;
box-shadow: 0 4px 16px #1098f755, 0 2px 8px #e5e7eb88 !important;
}
.cat-btn-radio label:hover {
border: 1.5px solid #1098F7 !important;
box-shadow: 0 4px 16px #1098f733, 0 2px 8px #e5e7eb88 !important;
}
/* Gradio tab content: Space-themed background */
.gr-tabitem {
background: linear-gradient(135deg, #e3e6f3 60%, #f5f6fa 100%);
background-image:
radial-gradient(rgba(255,255,255,0.10) 1.2px, transparent 1.2px),
radial-gradient(rgba(255,255,255,0.06) 1px, transparent 1px);
background-size: 40px 40px, 80px 80px;
background-position: 0 0, 20px 20px;
}
@media (prefers-color-scheme: dark) {
.gr-tabitem {
background: linear-gradient(135deg, #181c3a 0%, #2a1859 100%) !important;
background-image:
radial-gradient(rgba(255,255,255,0.10) 1.2px, transparent 1.2px),
radial-gradient(rgba(255,255,255,0.06) 1px, transparent 1px);
background-size: 40px 40px, 80px 80px;
background-position: 0 0, 20px 20px;
}
}
@media (prefers-color-scheme: light) {
.gr-tabitem {
background: linear-gradient(135deg, #e3e6f3 60%, #f5f6fa 100%) !important;
background-image:
radial-gradient(rgba(255,255,255,0.10) 1.2px, transparent 1.2px),
radial-gradient(rgba(255,255,255,0.06) 1px, transparent 1px);
background-size: 40px 40px, 80px 80px;
background-position: 0 0, 20px 20px;
}
h3 a, h3 a:visited {
color: #222 !important;
}
}
/* Sort arrow/button styles */
.sort-arrow, .sort-btn {
display: inline-flex;
align-items: center;
justify-content: center;
background: #23244a;
color: #ffd700 !important; /* Always yellow */
border: 1.5px solid #ffd700; /* Gold border */
border-radius: 6px;
font-size: 15px;
font-weight: 700;
margin-left: 6px;
margin-right: 2px;
padding: 2px 8px 2px 6px;
cursor: pointer;
transition: background 0.2s, color 0.2s, border 0.2s;
min-width: 28px;
min-height: 28px;
outline: none;
}
.sort-arrow.active, .sort-btn.active {
color: #ffd700 !important; /* Gold */
border-color: #ffd700;
background: #1a237e;
}
.sort-arrow:hover, .sort-btn:hover {
background: #ffd700;
color: #23244a !important;
border-color: #ffd700;
}
.sort-arrow svg, .sort-btn svg {
margin-left: 2px;
margin-right: 0;
width: 1em;
height: 1em;
vertical-align: middle;
}
/* Enhanced leaderboard table styles */
.pretty-leaderboard-table {
width: 100%;
border-collapse: separate;
border-spacing: 0;
background: rgba(30, 34, 54, 0.98);
/* border-radius: 16px; 테이블 자체에는 radius 제거 */
box-shadow: 0 4px 24px 0 rgba(16, 152, 247, 0.10), 0 1.5px 6px 0 rgba(227, 84, 84, 0.08);
margin-bottom: 24px;
}
.pretty-leaderboard-table thead {
border-radius: 16px 16px 0 0;
overflow: hidden;
background: #23244a;
}
/* Sticky first and second columns */
/* Sticky first and second columns - header(th) */
.pretty-leaderboard-table th:nth-child(1) {
position: sticky;
left: 0;
top: 0;
z-index: 5;
background: #23244a;
min-width: 60px;
max-width: 60px;
width: 60px;
}
.pretty-leaderboard-table th:nth-child(2) {
position: sticky;
left: 60px;
top: 0;
z-index: 5;
background: #23244a;
min-width: 220px;
max-width: 400px;
width: 220px;
}
/* Sticky first and second columns - body(td) with CSS variable for background */
.pretty-leaderboard-table td:nth-child(1) {
position: sticky;
left: 0;
z-index: 4;
background: var(--row-bg) !important;
min-width: 60px;
max-width: 60px;
width: 60px;
}
.pretty-leaderboard-table td:nth-child(2) {
position: sticky;
left: 60px;
z-index: 4;
background: var(--row-bg) !important;
min-width: 220px;
max-width: 400px;
width: 220px;
}
/* Set --row-bg variable for each row type */
.pretty-leaderboard-table tr {
--row-bg: #1e2236;
}
.pretty-leaderboard-table tr:nth-child(even) {
--row-bg: #23253a;
}
.pretty-leaderboard-table tr:hover {
--row-bg: #2066a0;
}
.pretty-leaderboard-table th {
z-index: 4;
}
.pretty-leaderboard-table th, .pretty-leaderboard-table td {
padding: 12px 16px;
text-align: left;
border-bottom: 1px solid #23244a;
font-size: 16px;
}
.pretty-leaderboard-table th {
background: #23244a;
color: #fff;
font-weight: 800;
letter-spacing: 0.5px;
border-bottom: 2px solid #1098F7;
text-shadow: 0 1px 8px #0006;
transition: background 0.2s, color 0.2s;
position: sticky;
top: 0;
z-index: 2;
border-radius: 0 !important;
}
.pretty-leaderboard-table th:hover, .pretty-leaderboard-table th:focus {
background: #273a8a;
color: #fff;
}
.pretty-leaderboard-table td {
color: #F5F6F7;
vertical-align: middle;
background: var(--row-bg);
}
.pretty-leaderboard-table tr:last-child td {
border-bottom: none;
}
/* th/td의 border-radius는 모두 제거, 둥근 효과는 thead에만 */
/* Enhanced score bar styles */
.score-bar {
display: flex;
align-items: center;
gap: 12px;
width: 100%;
}
.score-bar-track {
flex-grow: 1;
height: 10px;
background: rgba(245, 246, 247, 0.12);
border-radius: 5px;
overflow: hidden;
max-width: 220px;
box-shadow: 0 1px 4px 0 rgba(16, 152, 247, 0.10);
}
.score-bar-fill {
height: 100%;
background: linear-gradient(90deg, #a259f7 0%, #6d28d9 100%);
border-radius: 5px;
transition: width 0.3s cubic-bezier(0.4,0,0.2,1);
}
.score-bar-value {
font-family: 'SF Mono', monospace;
font-weight: 600;
color: #F5F6F7;
min-width: 60px;
font-size: 14px;
}
body {
min-height: 100vh;
}
/* 전체 배경색은 브라우저 기본값을 따름. gradio-container도 마찬가지로 별도 배경 없음 */
.markdown-text {
font-size: 16px !important;
}
#citation-button span {
font-size: 16px !important;
}
#citation-button textarea {
font-size: 16px !important;
}
#citation-button > label > button {
margin: 6px;
transform: scale(1.3);
}
.leaderboard-table-container {
margin-top: 15px;
/* Space-themed background */
background: linear-gradient(135deg, #e3e6f3 60%, #f5f6fa 100%);
position: relative;
background-image:
radial-gradient(rgba(255,255,255,0.15) 1.2px, transparent 1.2px),
radial-gradient(rgba(255,255,255,0.10) 1px, transparent 1px);
background-size: 40px 40px, 80px 80px;
background-position: 0 0, 20px 20px;
}
@media (prefers-color-scheme: dark) {
.leaderboard-table-container {
background: linear-gradient(135deg, #1a237e 0%, #311b92 100%) !important;
background-image:
radial-gradient(rgba(255,255,255,0.15) 1.2px, transparent 1.2px),
radial-gradient(rgba(255,255,255,0.10) 1px, transparent 1px);
background-size: 40px 40px, 80px 80px;
background-position: 0 0, 20px 20px;
}
}
@media (prefers-color-scheme: light) {
.leaderboard-table-container {
background: linear-gradient(135deg, #e3e6f3 60%, #f5f6fa 100%) !important;
background-image:
radial-gradient(rgba(255,255,255,0.15) 1.2px, transparent 1.2px),
radial-gradient(rgba(255,255,255,0.10) 1px, transparent 1px);
background-size: 40px 40px, 80px 80px;
background-position: 0 0, 20px 20px;
}
}
/* Limit the width of the first column so that names don't expand too much */
.leaderboard-table-container td:nth-child(2),
.leaderboard-table-container th:nth-child(2) {
max-width: 400px;
overflow: auto;
white-space: nowrap;
}
.tab-buttons button {
font-size: 20px;
}
/* Model type and think badge styles */
.badge {
display: inline-block;
border-radius: 12px;
padding: 2px 10px;
font-size: 0.85em;
font-weight: 700;
margin-left: 6px;
box-shadow: 0 1px 4px rgba(0,0,0,0.10);
vertical-align: middle;
}
.badge-think-on {
background: #A7C7E7;
color: #234567;
border: 1.5px solid #A7C7E7;
}
.badge-think-off {
background: #E0E0E0;
color: #555;
border: 1.5px solid #E0E0E0;
}
/* Model Type badge styles */
.badge-modeltype-instruct {
background: #B2F2E9;
color: #22796A;
border: 1.5px solid #B2F2E9;
}
.badge-modeltype-think {
background: #D6C8F7;
color: #5B4B8A;
border: 1.5px solid #D6C8F7;
}
.badge-modeltype-hybrid {
background: #FFE0B2;
color: #A67C52;
border: 1.5px solid #FFE0B2;
}
/* Type badge Open/Proprietary styles */
.badge-type-open {
background: #A8E6A3;
color: #225522;
border: 1.5px solid #A8E6A3;
}
.badge-type-proprietary {
background: #F7B2B7;
color: #7A2F34;
border: 1.5px solid #F7B2B7;
}
/* Sort button styles */
.sort-btn {
background: #23244a;
color: #F5F6F7;
border: 1px solid #1098F7;
border-radius: 6px;
font-size: 13px;
font-weight: 700;
margin-left: 4px;
margin-right: 2px;
padding: 2px 7px;
cursor: pointer;
transition: background 0.2s, color 0.2s;
}
.sort-btn:hover {
background: #1098F7;
color: #fff;
}
/* Custom CheckboxGroup and Dropdown styles for table theme */
.gr-checkbox-group, .gr-checkbox, .gr-checkbox-group label, .gr-checkbox input[type="checkbox"] {
background: #23244a !important;
color: #F5F6F7 !important;
border: 1.5px solid #1098F7 !important;
border-radius: 6px !important;
}
.gr-checkbox input[type="checkbox"]:checked {
background: #1a237e !important;
border-color: #ffd700 !important;
}
.gr-dropdown, .gr-input, select {
background: #23244a !important;
color: #F5F6F7 !important;
border: 1.5px solid #1098F7 !important;
border-radius: 6px !important;
}
/* Custom style for radar chart model selector's selected tags (only the tag area, not the dropdown list) */
.custom-dropdown .multiselect__tag {
background: #1098F7 !important;
color: #fff !important;
border: 1.5px solid #1098F7 !important;
box-shadow: 0 4px 16px #1098f755, 0 2px 8px #e5e7eb88 !important;
border-radius: 18px !important;
font-weight: 600 !important;
padding: 8px 20px !important;
margin: 2px 4px !important;
font-size: 1.08rem !important;
display: inline-block !important;
transition: background 0.2s, color 0.2s, box-shadow 0.2s, border 0.2s !important;
}
.gr-dropdown:focus, .gr-input:focus, select:focus {
border-color: #ffd700 !important;
outline: none !important;
}
@media (prefers-color-scheme: dark) {
.category-box,
.space-info-box,
.pretty-leaderboard-table,
.dark-container {
background: linear-gradient(135deg, #23244a 0%, #2a1859 100%) !important;
color: #f5f6f7 !important;
}
.space-info-box, .space-info-box * {
color: #f5f6f7 !important;
}
h3 a, h3 a:visited {
color: #f5f6f7 !important;
}
}
"""
# requirements_textbox and adaptor_class_textbox scroll/height control
custom_css += """
#requirements-textbox textarea {
overflow-y: auto !important;
resize: vertical;
height: 480px;
max-height: 480px;
}
#yml-textbox textarea {
overflow-y: auto !important;
resize: vertical;
height: 240px;
max-height: 240px;
}
/* No border textbox style for file upload status */
.no-border-textbox textarea {
border: none !important;
box-shadow: none !important;
background: transparent !important;
padding: 0 !important;
margin: 0 !important;
outline: none !important;
resize: none !important;
overflow: hidden !important;
}
.no-border-textbox .wrap {
background: transparent !important;
border: none !important;
box-shadow: none !important;
padding: 0 !important;
margin: 0 !important;
outline: none !important;
}
.no-border-textbox .prose {
background: transparent !important;
border: none !important;
box-shadow: none !important;
padding: 0 !important;
margin: 0 !important;
}
.no-border-textbox label {
display: none !important;
}
.no-border-textbox .gr-textbox {
border: none !important;
box-shadow: none !important;
background: transparent !important;
padding: 0 !important;
margin: 0 !important;
}
.no-border-textbox .gr-textbox > div {
border: none !important;
box-shadow: none !important;
background: transparent !important;
padding: 0 !important;
margin: 0 !important;
}
.no-border-textbox .gr-textbox > div > div {
border: none !important;
box-shadow: none !important;
background: transparent !important;
padding: 0 !important;
margin: 0 !important;
}
/* Ensure model name tooltips are hoverable */
.pretty-leaderboard-table td span[title] {
pointer-events: auto;
}
/* Tall file upload container to match lines=25 textbox height */
.tall-file-upload .file-upload-container {
min-height: 283px !important;
height: 283px !important;
}
.tall-file-upload .gr-file {
min-height: 283px !important;
height: 283px !important;
}
"""
def get_rank_badge(rank: int) -> str:
"""
Returns emoji for 1st, 2nd, 3rd, otherwise just the number.
"""
if rank == 1:
return '<span style="font-size:1.5em;" title="1st">🥇</span>'
elif rank == 2:
return '<span style="font-size:1.5em;" title="2nd">🥈</span>'
elif rank == 3:
return '<span style="font-size:1.5em;" title="3rd">🥉</span>'
else:
return f'<span style="font-size:1.2em;color:#a1a1aa;font-weight:500;">{rank}</span>'
def get_score_gauge(score: float) -> str:
"""
Returns HTML for an overall score gauge (progress bar style).
Robustly normalizes score to 0~100% regardless of input range (0~1 or 0~100).
"""
# Handle None/NaN
try:
score = float(score)
except (TypeError, ValueError):
score = 0.0
# Normalize: if score is 0~1, treat as normalized and scale to 0~100
if score is None or score != score: # NaN check
percent = 0.0
display_score = 0.0
elif score <= 1.0:
percent = score * 100
display_score = percent
else:
percent = score
display_score = score
# For scores above 95, adjust to 98~100% so the bar appears almost full
if percent >= 95:
percent = 98 + (min(percent, 100) - 95) * 0.4 # 95=98%, 100=100%
# Clip to 0~100
percent = min(max(percent, 0), 100)
display_score = min(max(display_score, 0), 100)
return f'''
<div class="score-bar" style="margin: 0.5em 0;">
<div class="score-bar-track">
<div class="score-bar-fill" style="width: {percent}%;"></div>
</div>
<span class="score-bar-value">{display_score:.3f}</span>
</div>
'''
from src.display.formatting import get_score_stars
def get_leaderboard_table_html(df, key="Category") -> str:
"""
Returns HTML for a pretty leaderboard table using badge and gauge.
Displays all columns in df, applying format_leaderboard_cell to each cell as needed.
key: "Category" or "Language" (default: "Category")
"""
import pandas as pd
from src.display.formatting import get_score_stars, get_type_badge, get_model_type_badge, get_output_badge, format_leaderboard_cell, get_display_model_name
# Build table header
html = ['<table class="pretty-leaderboard-table">']
html.append("<thead><tr>")
for col in df.columns:
html.append(f"<th>{col}</th>")
html.append("</tr></thead>")
html.append("<tbody>")
for idx, row in df.iterrows():
html.append("<tr>")
for col in df.columns:
cell = row[col]
# Special cell handling
if col == "Rank":
badge = get_rank_badge(cell)
html.append(f"<td>{badge}</td>")
elif col == "Model Name":
# Highlight top 1~3
rank = row.get("Rank", None)
highlight_style = ""
if rank == 1 or rank == "1":
highlight_style = "color: #ffd700; font-weight: bold; text-shadow: 0 0 4px #fff2;"
elif rank == 2 or rank == "2":
highlight_style = "color: #b0b0b0; font-weight: bold;"
elif rank == 3 or rank == "3":
highlight_style = "color: #cd7f32; font-weight: bold;"
else:
highlight_style = "color: #fff; font-weight: 600;"
display_name = get_display_model_name(str(cell))
link_value = row["Link"] if "Link" in row and pd.notna(row["Link"]) and str(row["Link"]).strip() != "" else None
if link_value:
clickable_name = f'<a href="{link_value}" target="_blank" style="color:inherit;">{display_name}</a>'
else:
clickable_name = display_name
html.append(f'<td><span style="{highlight_style}">{clickable_name}</span></td>')
elif col == "Model Type":
html.append(f"<td>{get_model_type_badge(row.get('Model Type', ''))}</td>")
elif col == "Type":
html.append(f"<td>{get_type_badge(row.get('Type', ''))}</td>")
elif col == "Think":
html.append(f"<td>{get_output_badge(row.get('Think', ''))}</td>")
elif col == "Overall":
# 별점
try:
unique_id = row.get("Model Name", None)
unique_id = unique_id.replace(" ", "_").replace("-", "_").replace("(", "_").replace(")", "_")
cell_html = get_score_stars(float(cell), unique_id=unique_id)
except Exception:
cell_html = str(cell)
html.append(f"<td>{cell_html}</td>")
else:
html.append(f"<td>{format_leaderboard_cell(cell, col, key)}</td>")
html.append("</tr>")
html.append("</tbody></table>")
table_html = "\n".join(html)
# Wrap in scrollable div for sticky header
return f'<div class="leaderboard-table-container" style="max-height:900px;overflow-y:auto;">{table_html}</div>'