Annie Voigt
Claude Opus 5
feat: bcc-ui-theme 0.1.0 — shared Gradio theme + stylesheet for the fleet
89e8390
Raw History Blame Contribute Delete
6.48 kB
"""The shared stylesheet.
Three rules govern what belongs here.
1. **Fleet-wide fixes, not per-app taste.** Every line of CSS in the fleet today
is a workaround for a gradio default (dropdown height, JSON-pane height), and
each is written out separately in each repo. Those belong here, once.
2. **Nothing that removes information.** In particular this stylesheet does not
hide the gradio footer. DecoupleRpy_Agent does, via eleven lines of escalating
selectors plus injected JavaScript that also forces light mode — see
``FOOTER_CSS`` below for why that is offered separately and opt-in.
3. **Classes the provenance pattern needs** (``docs/design/provenance-panel.md``
in the orchestrator), so a panel styled here looks the same in every app.
Everything is scoped under ``.gradio-container`` so an embedded app cannot leak
styles into a host page.
"""
from __future__ import annotations
from ._palette import DARK, LIGHT
CSS = f"""
/* ==========================================================================
bcc-ui-theme — shared stylesheet
Colour lives in the theme object; this file is layout, affordance and the
provenance/caveat classes. Tokens are re-declared here only where a plain
CSS rule needs them (gradio's own variables do not reach these selectors).
========================================================================== */
.gradio-container {{
--bcc-subdued: {LIGHT["subdued"]};
--bcc-border: {LIGHT["border"]};
--bcc-border-control: {LIGHT["border_control"]};
--bcc-focus: {LIGHT["focus"]};
--bcc-panel: {LIGHT["panel"]};
--bcc-danger: {LIGHT["danger"]};
--bcc-accent: {LIGHT["accent"]};
}}
.dark .gradio-container, .gradio-container.dark, .dark {{
--bcc-subdued: {DARK["subdued"]};
--bcc-border: {DARK["border"]};
--bcc-border-control: {DARK["border_control"]};
--bcc-focus: {DARK["focus"]};
--bcc-panel: {DARK["panel"]};
--bcc-danger: {DARK["danger"]};
--bcc-accent: {DARK["accent"]};
}}
/* --- 1. Fleet-wide gradio fixes -------------------------------------------
1a. Dropdown listbox height. Lifted verbatim from pdac-subtype-agent, where
a registry-length dataset list ran off the bottom of the viewport. */
.gradio-container ul[role="listbox"],
.gradio-container .wrap-inner + ul,
.gradio-container .options {{
max-height: 16rem;
overflow-y: auto;
}}
/* 1b. Bounded result panes. Opt-in by class, because a global cap on every
code block would clip short ones for no reason. Apply with
`gr.Code(..., elem_classes="bcc-scroll")`. pdac-genomics-agent needs this:
without a cap the page height tracks payload size (~300,000px on a
full-panel query before abridgement). max_lines does not do it — gradio
6.18 ignores that argument on gr.Code. */
.gradio-container .bcc-scroll .cm-editor,
.gradio-container .bcc-scroll .cm-scroller,
.gradio-container .bcc-scroll pre {{
max-height: 460px;
overflow: auto;
}}
/* 1c. Tables bounded the same way, for the same reason. */
.gradio-container .bcc-scroll table {{
display: block;
max-height: 420px;
overflow: auto;
}}
/* --- 2. Accessibility ------------------------------------------------------
A visible focus indicator on every keyboard-reachable control (WCAG 2.2
SC 2.4.7 / 2.4.11). gradio's default ring is low contrast on both of our
backgrounds. :focus-visible so a mouse click does not draw it. */
.gradio-container :focus-visible {{
outline: 2px solid var(--bcc-focus);
outline-offset: 2px;
border-radius: 2px;
}}
/* Never let a control's boundary rest on colour alone at <3:1. */
.gradio-container input[type="text"],
.gradio-container input[type="number"],
.gradio-container textarea,
.gradio-container select {{
border-color: var(--bcc-border-control);
}}
/* --- 3. Provenance pattern -------------------------------------------------
See docs/design/provenance-panel.md (pdac-analysis-orchestrator). These
classes exist so the three panels read identically in every app. */
/* The standing line that introduces the panels. */
.gradio-container .bcc-provenance-intro p {{
color: var(--bcc-subdued);
font-size: 0.9em;
margin: 0.25rem 0 0.5rem;
}}
/* The group of accordions itself — set off from the answer above it. */
.gradio-container .bcc-provenance {{
border-left: 3px solid var(--bcc-border);
padding-left: 0.75rem;
}}
/* A panel's own sub-caption ("what this panel contains"). */
.gradio-container .bcc-panel-note p {{
color: var(--bcc-subdued);
font-size: 0.875em;
margin: 0 0 0.5rem;
}}
/* Monospace inside the Code-used panel, so a tool call reads as a call. */
.gradio-container .bcc-panel-code code,
.gradio-container .bcc-panel-code pre {{
font-size: 0.875em;
}}
/* The caveat, next to the result it qualifies — not in a header, not inside a
collapsed accordion. Deliberately loud enough to be read and quiet enough
not to look like a failure: a caveat is not an error. */
.gradio-container .bcc-caveat {{
border-left: 4px solid var(--bcc-danger);
background: var(--bcc-panel);
padding: 0.6rem 0.9rem;
border-radius: 4px;
margin: 0.5rem 0;
}}
.gradio-container .bcc-caveat p {{
margin: 0.2rem 0;
}}
/* The paired action ("re-run on the registered cohort to get grounded=true").
The rule in the doc is that a caveat never appears without one. */
.gradio-container .bcc-caveat-action p {{
color: var(--bcc-subdued);
font-size: 0.9em;
}}
/* --- 4. Restraint ----------------------------------------------------------
Long prose in a research UI is unreadable at full window width. */
.gradio-container .bcc-prose {{
max-width: 72ch;
}}
"""
FOOTER_CSS = """
/* OPT-IN, not part of CSS. Hides the gradio footer.
DecoupleRpy_Agent does this today and may want to keep doing it; it is kept
out of the shared stylesheet because hiding attribution is a decision each
app should make deliberately rather than inherit.
NOTE this is the CSS half only. DecoupleRpy also injects JavaScript that
strips the `dark` class and rewrites the URL to `?__theme=light`, which
overrides the user's own theme choice on that one app. That JS is NOT
reproduced here and should be removed, not ported: with this theme the app
renders correctly in both modes, so there is nothing left for it to fix. */
.gradio-container footer,
.gradio-container .built-with-gradio {
display: none !important;
}
"""