generated from john/python-template
UI style refresh: Final cleanup
This commit is contained in:
@@ -4,10 +4,16 @@ from transcription.ui.components.app_shell import NAV_ITEMS
|
||||
from transcription.ui.components.app_shell import render_app_shell
|
||||
from transcription.ui.components.app_shell import render_navigation_header
|
||||
from transcription.ui.components.document_panzoom import render_document_panzoom
|
||||
from transcription.ui.components.primitives import destructive_button
|
||||
from transcription.ui.components.primitives import render_empty_state
|
||||
from transcription.ui.components.primitives import section_header_row
|
||||
|
||||
__all__ = [
|
||||
"NAV_ITEMS",
|
||||
"destructive_button",
|
||||
"render_app_shell",
|
||||
"render_document_panzoom",
|
||||
"render_empty_state",
|
||||
"render_navigation_header",
|
||||
"section_header_row",
|
||||
]
|
||||
|
||||
@@ -17,3 +17,22 @@ def render_empty_state(message: str, *, italic: bool = False, extra_classes: str
|
||||
if italic:
|
||||
classes = f"{classes} italic"
|
||||
ui.label(message).classes(f"{classes} {extra_classes}".strip())
|
||||
|
||||
|
||||
def destructive_button(
|
||||
label: str,
|
||||
*,
|
||||
on_click,
|
||||
icon: str,
|
||||
variant: str = "outlined",
|
||||
extra_classes: str = "",
|
||||
):
|
||||
"""Render a standardized destructive action button."""
|
||||
button = ui.button(label, on_click=on_click, icon=icon)
|
||||
if variant == "solid":
|
||||
button.props("unelevated color=negative")
|
||||
else:
|
||||
button.props("outlined color=negative")
|
||||
if extra_classes:
|
||||
button.classes(extra_classes)
|
||||
return button
|
||||
|
||||
@@ -10,6 +10,7 @@ from uuid import UUID
|
||||
from nicegui import ui
|
||||
|
||||
from transcription.ui.components.cards import archival_card
|
||||
from transcription.ui.components.primitives import render_empty_state
|
||||
from transcription.ui.components.table.common import build_table
|
||||
|
||||
|
||||
@@ -41,7 +42,7 @@ def render_documents_table(rows: Sequence[DocumentTableRow]) -> None:
|
||||
"""Render documents table and open detail page when clicking a row."""
|
||||
if not rows:
|
||||
with archival_card(extra_classes="p-8 text-center"):
|
||||
ui.label("No documents in repository yet.").classes("text-xs ui-text-muted")
|
||||
render_empty_state("No documents in repository yet.")
|
||||
return
|
||||
|
||||
build_table(
|
||||
|
||||
@@ -12,6 +12,7 @@ from uuid import UUID
|
||||
from nicegui import ui
|
||||
|
||||
from transcription.ui.components.cards import archival_card
|
||||
from transcription.ui.components.primitives import render_empty_state
|
||||
from .common import build_table
|
||||
|
||||
|
||||
@@ -57,7 +58,7 @@ def render_jobs_table(rows: Sequence[JobTableRow]) -> None:
|
||||
"""Render jobs table and open a detail page when clicking a row."""
|
||||
if not rows:
|
||||
with archival_card(extra_classes="p-8 text-center"):
|
||||
ui.label("No active or historical processing jobs found.").classes("text-xs ui-text-muted")
|
||||
render_empty_state("No active or historical processing jobs found.")
|
||||
return
|
||||
|
||||
build_table(
|
||||
|
||||
@@ -10,6 +10,7 @@ from uuid import UUID
|
||||
from nicegui import ui
|
||||
|
||||
from transcription.ui.components.cards import archival_card
|
||||
from transcription.ui.components.primitives import render_empty_state
|
||||
from transcription.ui.components.table.common import build_table
|
||||
|
||||
|
||||
@@ -41,7 +42,7 @@ def render_people_table(rows: Sequence[PersonTableRow]) -> None:
|
||||
"""Render people table and open detail page when clicking a row."""
|
||||
if not rows:
|
||||
with archival_card(extra_classes="p-8 text-center"):
|
||||
ui.label("No person records found in repository.").classes("text-xs ui-text-muted")
|
||||
render_empty_state("No person records found in repository.")
|
||||
return
|
||||
|
||||
build_table(
|
||||
|
||||
@@ -10,6 +10,7 @@ from uuid import UUID
|
||||
from nicegui import ui
|
||||
|
||||
from transcription.ui.components.cards import archival_card
|
||||
from transcription.ui.components.primitives import render_empty_state
|
||||
from transcription.ui.components.table.common import build_table
|
||||
|
||||
|
||||
@@ -41,7 +42,7 @@ def render_sources_table(rows: Sequence[SourceTableRow]) -> None:
|
||||
"""Render sources table and open detail page when clicking a row."""
|
||||
if not rows:
|
||||
with archival_card(extra_classes="p-8 text-center"):
|
||||
ui.label("No source file records found.").classes("text-xs ui-text-muted")
|
||||
render_empty_state("No source file records found.")
|
||||
return
|
||||
|
||||
build_table(
|
||||
|
||||
@@ -21,6 +21,7 @@ from transcription.ui.components.cards import archival_card
|
||||
from transcription.ui.components.data_display import archival_badge
|
||||
from transcription.ui.components.data_display import metadata_row
|
||||
from transcription.ui.components.error_presenter import show_error
|
||||
from transcription.ui.components.primitives import destructive_button
|
||||
from transcription.ui.components.primitives import render_empty_state
|
||||
from transcription.ui.components.primitives import section_header_row
|
||||
from transcription.ui.components.table.documents import DocumentTableRow
|
||||
@@ -222,11 +223,12 @@ def register_page() -> None:
|
||||
on_click=lambda: ui.navigate.to(f"/documents/{document.id}/edit"),
|
||||
icon="edit",
|
||||
).classes("ui-btn-primary text-xs")
|
||||
ui.button(
|
||||
destructive_button(
|
||||
"Delete",
|
||||
on_click=lambda: ui.navigate.to(f"/documents/{document.id}/delete"),
|
||||
icon="delete",
|
||||
).props("outlined color=negative text-xs")
|
||||
extra_classes="text-xs",
|
||||
)
|
||||
|
||||
# High-Density Bento Grid Layout
|
||||
with ui.grid().classes("w-full grid-cols-12 gap-4"):
|
||||
@@ -587,11 +589,12 @@ def register_page() -> None:
|
||||
ui.navigate.to("/documents")
|
||||
|
||||
with ui.row().classes("w-full items-center gap-2 mt-2"):
|
||||
ui.button(
|
||||
destructive_button(
|
||||
"Delete document permanently",
|
||||
on_click=submit_delete,
|
||||
icon="delete_forever",
|
||||
).props("unelevated color=negative")
|
||||
variant="solid",
|
||||
)
|
||||
ui.button("Cancel", on_click=lambda: ui.navigate.to(f"/documents/{document.id}"), icon="arrow_back").props(
|
||||
"flat"
|
||||
)
|
||||
@@ -19,6 +19,7 @@ from transcription.ui.components.cards import archival_card
|
||||
from transcription.ui.components.data_display import archival_badge
|
||||
from transcription.ui.components.data_display import metadata_row
|
||||
from transcription.ui.components.error_presenter import show_error
|
||||
from transcription.ui.components.primitives import destructive_button
|
||||
from transcription.ui.components.primitives import render_empty_state
|
||||
from transcription.ui.components.primitives import section_header_row
|
||||
from transcription.ui.components.table.jobs import render_jobs_table
|
||||
@@ -224,11 +225,12 @@ def register_page() -> None: # noqa: PLR0915
|
||||
page_header(f"Job Record: {job.id}")
|
||||
with ui.row().classes("items-center gap-2"):
|
||||
archival_badge(job.status.value.upper())
|
||||
ui.button(
|
||||
destructive_button(
|
||||
"Delete Job",
|
||||
on_click=lambda: ui.navigate.to(f"/jobs/{job.id}/delete"),
|
||||
icon="delete",
|
||||
).props("outlined color=negative text-xs")
|
||||
extra_classes="text-xs",
|
||||
)
|
||||
|
||||
with ui.grid().classes("w-full grid-cols-1 md:grid-cols-2 gap-4"):
|
||||
with archival_card(title="Execution Logistics"):
|
||||
@@ -314,7 +316,10 @@ def register_page() -> None: # noqa: PLR0915
|
||||
ui.navigate.to("/jobs")
|
||||
|
||||
with ui.row().classes("w-full items-center gap-2 mt-2"):
|
||||
ui.button("Delete job permanently", on_click=submit_delete, icon="delete_forever").props(
|
||||
"unelevated color=negative"
|
||||
destructive_button(
|
||||
"Delete job permanently",
|
||||
on_click=submit_delete,
|
||||
icon="delete_forever",
|
||||
variant="solid",
|
||||
)
|
||||
ui.button("Cancel", on_click=lambda: ui.navigate.to(f"/jobs/{job.id}"), icon="arrow_back").props("flat")
|
||||
@@ -22,6 +22,7 @@ from transcription.ui.components.app_shell import render_navigation_header
|
||||
from transcription.ui.components.cards import archival_card
|
||||
from transcription.ui.components.data_display import metadata_row
|
||||
from transcription.ui.components.error_presenter import show_error
|
||||
from transcription.ui.components.primitives import destructive_button
|
||||
from transcription.ui.components.primitives import render_empty_state
|
||||
from transcription.ui.components.primitives import section_header_row
|
||||
from transcription.ui.components.table.people import PersonTableRow, render_people_table
|
||||
@@ -241,11 +242,12 @@ def register_page() -> None: # noqa: PLR0915
|
||||
on_click=lambda: ui.navigate.to(f"/people/{person.id}/edit"),
|
||||
icon="edit",
|
||||
).classes("ui-btn-primary text-xs")
|
||||
ui.button(
|
||||
destructive_button(
|
||||
"Delete",
|
||||
on_click=lambda: ui.navigate.to(f"/people/{person.id}/delete"),
|
||||
icon="delete",
|
||||
).props("outlined color=negative text-xs")
|
||||
extra_classes="text-xs",
|
||||
)
|
||||
|
||||
with ui.grid().classes("w-full grid-cols-12 gap-4"):
|
||||
with ui.column().classes("col-span-12 lg:col-span-4"):
|
||||
@@ -467,9 +469,10 @@ def register_page() -> None: # noqa: PLR0915
|
||||
ui.navigate.to("/people")
|
||||
|
||||
with ui.row().classes("w-full items-center gap-2 mt-2"):
|
||||
ui.button(
|
||||
destructive_button(
|
||||
"Delete person permanently",
|
||||
on_click=submit_delete,
|
||||
icon="delete_forever",
|
||||
).props("unelevated color=negative")
|
||||
variant="solid",
|
||||
)
|
||||
ui.button("Cancel", on_click=lambda: ui.navigate.to(f"/people/{person.id}"), icon="arrow_back").props("flat")
|
||||
@@ -209,6 +209,26 @@ input:focus-visible,
|
||||
color: var(--theme-secondary);
|
||||
}
|
||||
|
||||
.ui-page-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ui-page-title {
|
||||
color: var(--theme-text);
|
||||
font-family: "Iowan Old Style", "Palatino Linotype", "Book Antiqua", Palatino, serif;
|
||||
font-size: 1.75rem;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.ui-page-subtitle {
|
||||
color: var(--theme-text-muted);
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.ui-table {
|
||||
border: 1px solid var(--theme-border);
|
||||
color: var(--theme-text);
|
||||
|
||||
@@ -1,35 +1,33 @@
|
||||
from nicegui import ui
|
||||
|
||||
# Exact Palette & Typography Constants from UI Design Specification
|
||||
# Runtime bridge for Quasar color slots. Visual ownership remains in theme.css tokens/classes.
|
||||
THEME_COLORS = {
|
||||
"primary": "#2D5A4C", # Library Green
|
||||
"secondary": "#E2C7A8", # Aged Sepia
|
||||
"positive": "#2D5A4C",
|
||||
"accent": "#E2C7A8",
|
||||
"dark": "#2B2D2C", # Matte Slate
|
||||
"negative": "#A83232",
|
||||
"primary": "#5e6572",
|
||||
"secondary": "#7d98a1",
|
||||
"accent": "#a9b4c2",
|
||||
"dark": "#1c2321",
|
||||
"positive": "#7d98a1",
|
||||
"negative": "#1c2321",
|
||||
"info": "#7d98a1",
|
||||
"warning": "#a9b4c2",
|
||||
}
|
||||
|
||||
# Typography Macros
|
||||
STYLE_SERIF_HEADER = "font-family: 'Georgia', 'Times New Roman', serif;"
|
||||
STYLE_SANS_BODY = "font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;"
|
||||
_THEME_APPLIED = False
|
||||
|
||||
|
||||
def apply_archival_theme() -> None:
|
||||
"""Configures global NiceGUI theme variables and injects custom global styles."""
|
||||
ui.colors(**THEME_COLORS)
|
||||
"""Apply runtime color slots once; visual styling is defined in theme.css."""
|
||||
global _THEME_APPLIED
|
||||
if _THEME_APPLIED:
|
||||
return
|
||||
|
||||
# Global body rules: Archival Cream (#FAF9F6) background, Iron Ink (#333333) text
|
||||
ui.query("body").style(
|
||||
f"background-color: #FAF9F6; color: #333333; {STYLE_SANS_BODY}"
|
||||
)
|
||||
ui.colors(**THEME_COLORS)
|
||||
_THEME_APPLIED = True
|
||||
|
||||
|
||||
def page_header(title: str, subtitle: str | None = None) -> None:
|
||||
"""Standardized page title component with Archival Serif styling."""
|
||||
with ui.column().classes("gap-0 pb-2 border-b border-[#6B6A65]/30 w-full"):
|
||||
ui.label(title).style(
|
||||
f"{STYLE_SERIF_HEADER} font-size: 1.75rem; font-weight: 700; color: #333333;"
|
||||
)
|
||||
"""Standardized page title component using semantic classes."""
|
||||
with ui.column().classes("ui-page-header"):
|
||||
ui.label(title).classes("ui-page-title")
|
||||
if subtitle:
|
||||
ui.label(subtitle).classes("text-xs text-[#6B6A65]")
|
||||
ui.label(subtitle).classes("ui-page-subtitle")
|
||||
Reference in New Issue
Block a user