| """Hugging Face design options for Prefab review builds.""" |
|
|
| from __future__ import annotations |
|
|
| import base64 |
| from pathlib import Path |
| from typing import Literal, get_args |
|
|
| HFDesign = Literal["hub-classic", "spaces-gradient", "dataset-studio"] |
| HF_DESIGNS = get_args(HFDesign) |
|
|
| HF_FONT_STYLESHEET = ( |
| "https://fonts.googleapis.com/css2?" |
| "family=IBM+Plex+Mono:wght@400;600&" |
| "family=Source+Sans+3:wght@400;600;700&display=swap" |
| ) |
| HF_RESOURCE_DOMAINS = ( |
| "https://fonts.googleapis.com", |
| "https://fonts.gstatic.com", |
| ) |
|
|
| _LOGO = Path(__file__).with_name("assets") / "huggingface-logo.svg" |
| HF_LOGO_DATA_URI = ( |
| "data:image/svg+xml;base64," |
| + base64.b64encode(_LOGO.read_bytes()).decode("ascii") |
| ) |
|
|
| HF_DESIGN_CSS = """ |
| .hf-design { |
| --hf-yellow: #ffd21e; |
| --hf-amber: #f59e0b; |
| --hf-orange: #ff9d0b; |
| --hf-blue: #3b82f6; |
| --hf-violet: #7c3aed; |
| --hf-gray-50: #f9fafb; |
| --hf-gray-100: #f3f4f6; |
| --hf-gray-200: #e5e7eb; |
| --hf-gray-300: #d1d5db; |
| --hf-gray-400: #9ca3af; |
| --hf-gray-500: #6b7280; |
| --hf-gray-700: #374151; |
| --hf-gray-850: #141c2e; |
| --hf-gray-925: #101623; |
| --hf-gray-950: #0b0f19; |
| --hf-canvas: var(--hf-gray-50); |
| --hf-surface: #fff; |
| --hf-surface-soft: var(--hf-gray-50); |
| --hf-line: var(--hf-gray-200); |
| --hf-text: #111827; |
| --hf-muted: var(--hf-gray-500); |
| --dispatch-accent: #b45309; |
| --dispatch-live: #10b981; |
| --dispatch-panel: var(--hf-surface-soft); |
| min-height: 800px; |
| padding: 24px; |
| background: var(--hf-canvas); |
| color: var(--hf-text); |
| font-family: "Source Sans 3", "Source Sans Pro", ui-sans-serif, system-ui, sans-serif; |
| } |
| .dark .hf-design { |
| --hf-canvas: var(--hf-gray-950); |
| --hf-surface: var(--hf-gray-925); |
| --hf-surface-soft: var(--hf-gray-850); |
| --hf-line: #263044; |
| --hf-text: #e5e7eb; |
| --hf-muted: #9ca3af; |
| --dispatch-accent: #fbbf24; |
| --dispatch-live: #34d399; |
| } |
| .hf-design .dispatch-sheet { |
| width: min(100%, 920px); |
| height: 800px; |
| border-color: var(--hf-line); |
| border-radius: 14px; |
| background: var(--hf-surface); |
| box-shadow: 0 1px 2px rgb(15 23 42 / .04), 0 10px 32px rgb(15 23 42 / .08); |
| } |
| .dark .hf-design .dispatch-sheet { |
| box-shadow: 0 18px 50px rgb(0 0 0 / .28); |
| } |
| .hf-design .dispatch-header { |
| padding: 22px 30px 18px; |
| } |
| .hf-design .dispatch-body { |
| padding: 0 30px; |
| } |
| .hf-design .dispatch-footer-log { |
| padding-right: 30px; |
| padding-left: 30px; |
| } |
| .hf-design .dispatch-session { |
| padding-right: 30px; |
| padding-left: 30px; |
| } |
| .hf-design .dispatch-kicker, |
| .hf-design .dispatch-section-label, |
| .hf-design .dispatch-time, |
| .hf-design .dispatch-source, |
| .hf-design .dispatch-meta, |
| .hf-design .dispatch-log-line, |
| .hf-design .dispatch-query-toggle, |
| .hf-design .dispatch-status, |
| .hf-design .dispatch-stat, |
| .hf-design .dispatch-trace, |
| .hf-design .dispatch-log-toggle-button { |
| font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace; |
| } |
| .hf-brand { |
| min-width: 0; |
| flex: none; |
| align-items: center; |
| } |
| .hf-brand-logo { |
| width: 32px; |
| height: 30px; |
| flex: none; |
| object-fit: contain; |
| } |
| .hf-brand-copy { |
| min-width: 0; |
| } |
| .hf-brand-name { |
| color: var(--hf-text); |
| font-size: 16px; |
| font-weight: 700; |
| line-height: 1; |
| } |
| .hf-brand-product { |
| margin-top: 4px; |
| color: var(--hf-muted); |
| font-family: "IBM Plex Mono", ui-monospace, monospace; |
| font-size: 9px; |
| letter-spacing: .09em; |
| line-height: 1; |
| text-transform: uppercase; |
| } |
| .hf-design .dispatch-status-controls { |
| gap: 10px; |
| } |
| .hf-design .dispatch-stat { |
| color: var(--hf-muted); |
| font-size: 10px; |
| letter-spacing: 0; |
| text-transform: none; |
| } |
| .hf-design .dispatch-status { |
| min-height: 26px; |
| border: 1px solid transparent; |
| border-radius: 7px; |
| font-weight: 600; |
| letter-spacing: 0; |
| } |
| .hf-design .dispatch-status-running { |
| border-color: #fde68a; |
| background: #fffbeb; |
| color: #92400e; |
| } |
| .dark .hf-design .dispatch-status-running { |
| border-color: rgb(245 158 11 / .28); |
| background: rgb(245 158 11 / .12); |
| color: #fbbf24; |
| } |
| .hf-design .dispatch-status-complete { |
| border-color: #bbf7d0; |
| background: #f0fdf4; |
| color: #047857; |
| } |
| .dark .hf-design .dispatch-status-complete { |
| border-color: rgb(16 185 129 / .28); |
| background: rgb(16 185 129 / .12); |
| color: #34d399; |
| } |
| .hf-design .dispatch-status-failed { |
| border-color: #fecaca; |
| background: #fef2f2; |
| color: #b91c1c; |
| } |
| .dark .hf-design .dispatch-status-failed { |
| border-color: rgb(239 68 68 / .28); |
| background: rgb(239 68 68 / .12); |
| color: #fca5a5; |
| } |
| .hf-design .dispatch-header-separator, |
| .hf-design .dispatch-event, |
| .hf-design .dispatch-footer { |
| border-color: var(--hf-line); |
| } |
| .hf-design .dispatch-section-label { |
| color: var(--hf-muted); |
| font-size: 10px; |
| font-weight: 600; |
| letter-spacing: .08em; |
| } |
| .hf-design .dispatch-headline, |
| .hf-design .dispatch-query, |
| .hf-design .dispatch-current-copy, |
| .hf-design .dispatch-event-message { |
| font-family: "Source Sans 3", "Source Sans Pro", ui-sans-serif, system-ui, sans-serif; |
| } |
| .hf-design .dispatch-headline { |
| color: var(--hf-text); |
| font-size: clamp(26px, 4vw, 34px); |
| font-weight: 700; |
| letter-spacing: -.025em; |
| } |
| .hf-design .dispatch-query { |
| color: var(--hf-muted); |
| font-size: 14px; |
| } |
| .hf-design .dispatch-markdown-report, |
| .hf-design .dispatch-log { |
| border-color: var(--hf-line); |
| background: var(--hf-surface-soft); |
| } |
| .hf-design .dispatch-time, |
| .hf-design .dispatch-log-line, |
| .hf-design .dispatch-trace, |
| .hf-design .dispatch-meta { |
| color: var(--hf-muted); |
| } |
| .hf-design .dispatch-current-copy { |
| color: var(--hf-text); |
| font-size: 20px; |
| font-weight: 400; |
| } |
| .hf-design .dispatch-event-message { |
| color: var(--hf-text); |
| } |
| .hf-design .dispatch-source { |
| font-weight: 600; |
| } |
| .hf-design .dispatch-rule { |
| background: var(--hf-line); |
| } |
| .hf-design .dispatch-footer { |
| background: var(--hf-surface); |
| } |
| .hf-design .dispatch-log-toggle-button { |
| color: var(--hf-muted); |
| } |
| |
| /* Option A: closest to the neutral Hub list and profile surfaces. */ |
| .hf-hub-classic { |
| background: |
| linear-gradient(180deg, var(--hf-surface) 0 68px, var(--hf-canvas) 68px); |
| } |
| .hf-hub-classic .dispatch-sheet { |
| border-radius: 12px; |
| } |
| .hf-hub-classic .dispatch-header { |
| border-top: 3px solid var(--hf-yellow); |
| } |
| .hf-hub-classic .dispatch-current-block { |
| margin-top: 20px; |
| padding: 18px; |
| border: 1px solid var(--hf-line); |
| border-radius: 11px; |
| background: var(--hf-surface); |
| box-shadow: 0 1px 3px rgb(15 23 42 / .05); |
| } |
| .hf-hub-classic .dispatch-history { |
| margin-top: 18px; |
| } |
| .hf-hub-classic .dispatch-report-action { |
| border-color: var(--hf-line); |
| background: var(--hf-surface); |
| color: var(--hf-text); |
| } |
| |
| /* Option B: borrows the colorful featured-card language from Spaces. */ |
| .hf-spaces-gradient { |
| --dispatch-accent: #7c3aed; |
| background: |
| radial-gradient(circle at 15% 15%, rgb(255 210 30 / .14), transparent 28%), |
| radial-gradient(circle at 85% 5%, rgb(99 102 241 / .16), transparent 30%), |
| var(--hf-canvas); |
| } |
| .dark .hf-spaces-gradient { |
| --dispatch-accent: #c4b5fd; |
| } |
| .hf-spaces-gradient .dispatch-sheet { |
| overflow: hidden; |
| border-color: rgb(99 102 241 / .22); |
| border-radius: 20px; |
| } |
| .hf-spaces-gradient .dispatch-header { |
| position: relative; |
| background: |
| linear-gradient(135deg, rgb(255 210 30 / .12), rgb(99 102 241 / .10) 55%, rgb(236 72 153 / .08)); |
| } |
| .dark .hf-spaces-gradient .dispatch-header { |
| background: |
| linear-gradient(135deg, rgb(245 158 11 / .12), rgb(79 70 229 / .18) 55%, rgb(190 24 93 / .12)); |
| } |
| .hf-spaces-gradient .dispatch-header::after { |
| content: ""; |
| position: absolute; |
| right: -50px; |
| bottom: -80px; |
| width: 180px; |
| height: 180px; |
| border: 28px solid rgb(255 210 30 / .16); |
| border-radius: 999px; |
| pointer-events: none; |
| } |
| .hf-spaces-gradient .dispatch-current-block { |
| margin-top: 22px; |
| padding: 22px; |
| overflow: hidden; |
| border-radius: 15px; |
| background: linear-gradient(135deg, #34469b, #4f46e5 52%, #7c3aed); |
| box-shadow: 0 12px 28px rgb(79 70 229 / .22); |
| } |
| .hf-spaces-gradient .dispatch-current-block .dispatch-time, |
| .hf-spaces-gradient .dispatch-current-block .dispatch-source, |
| .hf-spaces-gradient .dispatch-current-block .dispatch-current-copy { |
| color: #fff; |
| } |
| .hf-spaces-gradient .dispatch-current-block .dispatch-time { |
| opacity: .7; |
| } |
| .hf-spaces-gradient .dispatch-current-block .dispatch-live-dot { |
| background: var(--hf-yellow); |
| } |
| .hf-spaces-gradient .dispatch-current-block .dispatch-rule { |
| background: rgb(255 255 255 / .25); |
| } |
| .hf-spaces-gradient .dispatch-current-block .dispatch-rule-running::after, |
| .hf-spaces-gradient .dispatch-current-block .dispatch-rule-completed { |
| background: var(--hf-yellow); |
| } |
| .hf-spaces-gradient .dispatch-report-action { |
| border-color: rgb(99 102 241 / .28); |
| background: rgb(99 102 241 / .08); |
| color: var(--dispatch-accent); |
| } |
| |
| /* Option C: a compact, structured workspace inspired by dataset browsing. */ |
| .hf-dataset-studio { |
| --dispatch-accent: #2563eb; |
| padding: 0; |
| background: var(--hf-surface); |
| } |
| .dark .hf-dataset-studio { |
| --dispatch-accent: #60a5fa; |
| } |
| .hf-dataset-studio .dispatch-sheet { |
| width: min(100%, 1040px); |
| height: 820px; |
| border-radius: 0; |
| box-shadow: none; |
| } |
| .hf-dataset-studio .dispatch-header { |
| padding: 20px 28px 16px; |
| border-bottom: 1px solid var(--hf-line); |
| background: var(--hf-surface); |
| } |
| .hf-dataset-studio .dispatch-header-separator { |
| display: none; |
| } |
| .hf-dataset-studio .dispatch-query-wrap { |
| margin-top: 18px; |
| padding: 18px 20px; |
| border: 1px solid var(--hf-line); |
| border-radius: 10px; |
| background: var(--hf-surface-soft); |
| } |
| .hf-dataset-studio .dispatch-headline { |
| font-size: clamp(23px, 3vw, 29px); |
| } |
| .hf-dataset-studio .dispatch-body { |
| padding: 18px 28px; |
| background: |
| linear-gradient(90deg, var(--hf-surface-soft) 0 4px, transparent 4px); |
| } |
| .hf-dataset-studio .dispatch-current-block { |
| margin-top: 0; |
| padding: 18px 18px 20px; |
| border: 1px solid var(--hf-line); |
| border-radius: 9px; |
| background: var(--hf-surface); |
| } |
| .hf-dataset-studio .dispatch-current-meta { |
| padding-bottom: 10px; |
| border-bottom: 1px solid var(--hf-line); |
| } |
| .hf-dataset-studio .dispatch-current { |
| margin-top: 14px; |
| } |
| .hf-dataset-studio .dispatch-history { |
| margin-top: 18px; |
| padding: 16px 18px; |
| border: 1px solid var(--hf-line); |
| border-radius: 9px; |
| background: var(--hf-surface); |
| } |
| .hf-dataset-studio .dispatch-event { |
| margin-top: 8px; |
| padding: 10px 12px; |
| border: 1px solid var(--hf-line); |
| border-radius: 7px; |
| background: var(--hf-surface-soft); |
| opacity: 1; |
| } |
| .hf-dataset-studio .dispatch-event + .dispatch-event { |
| margin-top: 8px; |
| } |
| .hf-dataset-studio .dispatch-footer { |
| background: var(--hf-surface-soft); |
| } |
| |
| @media (max-width: 720px) { |
| .hf-design { |
| min-height: 800px; |
| padding: 0; |
| } |
| .hf-design .dispatch-sheet { |
| height: 800px; |
| border-radius: 0; |
| } |
| .hf-design .dispatch-header { |
| padding: 18px 18px 16px; |
| } |
| .hf-design .dispatch-body { |
| padding-right: 18px; |
| padding-left: 18px; |
| } |
| .hf-design .dispatch-footer-log, |
| .hf-design .dispatch-session { |
| padding-right: 18px; |
| padding-left: 18px; |
| } |
| .hf-brand-name { |
| font-size: 15px; |
| } |
| .hf-spaces-gradient .dispatch-current-block, |
| .hf-hub-classic .dispatch-current-block { |
| padding: 17px; |
| } |
| .hf-dataset-studio .dispatch-query-wrap { |
| padding: 14px; |
| } |
| } |
| """ |
|
|
|
|
| def design_css_class(design: HFDesign) -> str: |
| return f"dispatch-app hf-design hf-{design}" |
|
|
|
|
| def validate_design(design: str) -> HFDesign: |
| if design not in HF_DESIGNS: |
| choices = ", ".join(HF_DESIGNS) |
| raise ValueError(f"Unknown design {design!r}; expected one of: {choices}") |
| return design |
|
|