Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions sl/SL_Menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,12 @@ def render_icon_button_css():
Keeps icon-only action buttons visually consistent across all Streamlit views.
"""
button_selectors = [
'[class*="st-key-toolbar_new_popover"] [data-testid="stPopoverButton"]',
'[class*="st-key-toolbar_mgmt_popover"] [data-testid="stPopoverButton"]',
'[class*="st-key-toolbar_report_popover"] [data-testid="stPopoverButton"]',
# st.popover's `key=` doesn't get reflected as a "st-key-*" class
# anywhere in its rendered DOM (unlike st.button/st.expander), so a
# per-key selector like the ones below can never match it - every
# popover trigger in this app is one of these three toolbar icons,
# so targeting the testid directly covers all of them.
'[data-testid="stPopoverButton"]',
'[class*="st-key-toolbar_today_btn"] button',
'[class*="st-key-toolbar_planning_btn"] button',
'[class*="st-key-toolbar_email_btn"] button',
Expand Down Expand Up @@ -113,7 +116,7 @@ def render_icon_button_css():
align-items: center !important;
justify-content: center !important;
gap: 0 !important;
color: #3f3f3f !important;
color: var(--tc-icon-color, #3f3f3f) !important;
font-family: Arial, Helvetica, sans-serif !important;
font-size: 20px !important;
font-weight: 700 !important;
Expand Down
284 changes: 284 additions & 0 deletions sl/style_claude.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
/* ==========================================================================
TimeControl - Claude Style
==========================================================================
Warm, editorial palette inspired by the Claude Desktop app: a soft cream
page background, a warm charcoal ink for text, and a terracotta/clay
accent for interactive elements, in place of the usual cool blues/grays.

Custom properties live on :root (not .stApp) because several Streamlit
components (popover panels, select/date dropdowns) render into a portal
appended directly to <body>, outside .stApp's own subtree - a variable
defined only on .stApp would never reach them.
========================================================================== */

:root {
--tc-bg: #F5F4EE;
--tc-bg-elevated: #FFFFFF;
--tc-bg-input: #FFFFFF;
--tc-bg-hover: #ECE9DF;
--tc-text: #3D3929;
--tc-text-muted: #83817D;
--tc-border: #E0DCD0;
--tc-accent: #CC785C;
--tc-accent-hover: #B15E42;
--tc-icon-color: #6B6960;
--tc-code-text: #AF5A3F;
}

/* Global Font & Background */
.stApp {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
background-color: var(--tc-bg);
color: var(--tc-text);
}

/* Native Streamlit chrome: the fixed header bar (Deploy/hamburger menu) and
the toolbar/decoration strip sit outside .stApp's own background, so they
otherwise stay on Streamlit's default white/gray regardless of the rest
of the page. */
header[data-testid="stHeader"],
[data-testid="stToolbar"],
[data-testid="stDecoration"] {
background-color: var(--tc-bg) !important;
color: var(--tc-text);
}

header[data-testid="stHeader"] svg {
fill: var(--tc-icon-color) !important;
}

/* Headings */
h1, h2, h3 {
font-weight: 700;
color: var(--tc-text);
letter-spacing: -0.02em;
}

h1 {
font-size: 2.0rem;
padding-bottom: 0.5rem;
border-bottom: 1px solid var(--tc-border);
margin-bottom: 1.5rem;
padding-top: 0.1rem;
}

h1::before {
content: "⏱️";
margin-right: 0.5rem;
}

h2 {
font-size: 1.6rem;
}

h3 {
font-size: 1.35rem;
}

h4 {
font-size: 1.15rem;
}

h5, h6 {
font-size: 1.0rem;
}

/* Widget labels, captions and help tooltips */
[data-testid="stWidgetLabel"] p,
[data-testid="stCaptionContainer"],
[data-testid="stCaptionContainer"] p,
[data-testid="stMarkdownContainer"] small {
color: var(--tc-text-muted) !important;
}

[data-testid="stTooltipIcon"] {
color: var(--tc-text-muted) !important;
}

/* Buttons - regular, form-submit and popover triggers all need the same
treatment so none of them fall back to Streamlit's own default styling. */
.stButton button,
[data-testid="stFormSubmitButton"] button,
[data-testid="stPopoverButton"] {
border-radius: 10px;
font-weight: 600;
border: 1px solid var(--tc-border);
background-color: var(--tc-bg-elevated);
color: var(--tc-text);
transition: all 0.2s ease-in-out;
box-shadow: 0 1px 2px rgba(61, 57, 41, 0.06);
}

.stButton button:hover,
[data-testid="stFormSubmitButton"] button:hover,
[data-testid="stPopoverButton"]:hover {
border-color: var(--tc-accent);
color: var(--tc-accent-hover);
background-color: var(--tc-bg-hover);
transform: translateY(-1px);
box-shadow: 0 4px 10px rgba(61, 57, 41, 0.10);
}

.stButton button:active,
[data-testid="stFormSubmitButton"] button:active {
transform: translateY(0);
box-shadow: none;
}

.stButton button:disabled,
.stButton button:disabled:hover {
opacity: 0.5;
color: var(--tc-text-muted) !important;
border-color: var(--tc-border) !important;
background-color: var(--tc-bg-elevated) !important;
transform: none;
box-shadow: none;
}

/* Primary-type buttons (e.g. "Add Task") get the terracotta treatment to
read as the clear call-to-action, matching Claude's own send/primary
button color. */
[data-testid="stBaseButton-primary"] {
background-color: var(--tc-accent) !important;
border-color: var(--tc-accent) !important;
color: #FFFFFF !important;
}

[data-testid="stBaseButton-primary"]:hover {
background-color: var(--tc-accent-hover) !important;
border-color: var(--tc-accent-hover) !important;
color: #FFFFFF !important;
}

/* The dropdown card a popover opens (toolbar's New/Management/Reporting
menus) - rendered in a body-level portal, stayed on Streamlit's default
white/gray otherwise. */
[data-testid="stPopoverBody"],
[data-testid="stPopoverBody"] > div {
background-color: var(--tc-bg-elevated) !important;
border: 1px solid var(--tc-border) !important;
color: var(--tc-text);
}

/* Input Fields */
.stTextInput input,
.stNumberInput input,
.stTextArea textarea,
.stDateInput input,
.stSelectbox div[data-baseweb="select"] > div {
border-radius: 8px;
border: 1px solid var(--tc-border);
background-color: var(--tc-bg-input);
color: var(--tc-text);
}

.stTextInput input:focus,
.stNumberInput input:focus,
.stTextArea textarea:focus {
border-color: var(--tc-accent) !important;
box-shadow: 0 0 0 1px var(--tc-accent) !important;
}

.stTextInput input::placeholder,
.stTextArea textarea::placeholder {
color: var(--tc-text-muted);
opacity: 1;
}

[data-testid="stNumberInputStepDown"],
[data-testid="stNumberInputStepUp"] {
background-color: var(--tc-bg-hover) !important;
border-color: var(--tc-border) !important;
color: var(--tc-text) !important;
}

/* Select / date-input dropdown popups also render in a body-level portal
via BaseWeb, so they need the same background rendered explicitly. The
plain [data-baseweb="popover"] wrapper (and the unlabeled div directly
inside it) is what shows a card behind the calendar/menu content - the
inner listbox/menu/calendar elements need their own override too. */
[data-baseweb="popover"],
[data-baseweb="popover"] > div,
[data-baseweb="popover"] [role="listbox"],
[data-baseweb="menu"],
[data-baseweb="calendar"] {
background-color: var(--tc-bg-elevated) !important;
color: var(--tc-text) !important;
}

[data-baseweb="popover"] li[role="option"],
[data-baseweb="menu"] li {
color: var(--tc-text) !important;
}

[data-baseweb="popover"] li[role="option"]:hover,
[data-baseweb="menu"] li:hover {
background-color: var(--tc-bg-hover) !important;
}

/* The date-input calendar's month/year header bar and weekday-initials row
keep Streamlit's default secondary-background grey regardless of theme;
[role="presentation"] reaches the weekday row, .st-c7 is the shared class
between it and the header bar just above it. Out-of-month filler day
cells render their fill via a ::after pseudo-element rather than their
own background, so they need a separate override. */
[data-baseweb="calendar"] [role="presentation"],
[data-baseweb="calendar"] .st-c7 {
background-color: transparent !important;
}

[data-baseweb="calendar"] [role="gridcell"]::after {
background-color: transparent !important;
}

/* Checkbox */
[data-testid="stCheckbox"] label p {
color: var(--tc-text) !important;
}

/* Expander */
[data-testid="stExpander"] {
border: 1px solid var(--tc-border);
border-radius: 10px;
background-color: var(--tc-bg-elevated);
overflow: hidden;
}

[data-testid="stExpander"] summary {
color: var(--tc-text) !important;
}

[data-testid="stExpander"] summary:hover {
background-color: var(--tc-bg-hover);
}

/* Divider */
hr {
border-color: var(--tc-border) !important;
}

/* Alerts (st.info/success/warning/error) */
[data-testid="stAlert"] {
background-color: var(--tc-bg-elevated);
border-radius: 8px;
border: 1px solid var(--tc-border);
}

/* Inline code and code blocks */
code {
background-color: var(--tc-bg-hover) !important;
color: var(--tc-code-text) !important;
}

/* Report Box */
.report-box {
background-color: #FFFFFF;
padding: 20px;
border-radius: 12px;
font-family: 'SF Mono', 'Menlo', 'Monaco', 'Courier New', monospace;
font-size: 0.9em;
white-space: pre-wrap;
border: 1px solid var(--tc-border);
box-shadow: inset 0 1px 3px rgba(61, 57, 41, 0.06);
color: var(--tc-text);
}
Loading
Loading