From fb6816de00d456484721c3efb01552ff093de19a Mon Sep 17 00:00:00 2001
From: zwitschi
Date: Thu, 13 Nov 2025 21:18:32 +0100
Subject: [PATCH] Add form styles and update button classes for consistency
- Introduced a new CSS file for form styles (forms.css) to enhance form layout and design.
- Removed deprecated button styles from imports.css and updated button classes across templates to use the new utility classes.
- Updated various templates to reflect the new button styles, ensuring a consistent look and feel throughout the application.
- Refactored form-related styles in main.css and removed redundant styles from projects.css and scenarios.css.
- Ensured responsive design adjustments for form actions in smaller viewports.
---
static/css/forms.css | 102 ++++++++++++++++
static/css/imports.css | 12 --
static/css/main.css | 158 ++++++++++++++++++-------
static/css/projects.css | 38 +-----
static/css/scenarios.css | 59 +--------
templates/base.html | 5 +-
templates/exports/modal.html | 6 +-
templates/imports/ui.html | 4 +-
templates/login.html | 2 +-
templates/partials/import_upload.html | 6 +-
templates/projects/detail.html | 12 +-
templates/projects/form.html | 8 +-
templates/projects/list.html | 10 +-
templates/register.html | 2 +-
templates/scenarios/capex.html | 14 +--
templates/scenarios/detail.html | 10 +-
templates/scenarios/form.html | 8 +-
templates/scenarios/list.html | 16 +--
templates/scenarios/opex.html | 14 +--
templates/scenarios/profitability.html | 10 +-
20 files changed, 282 insertions(+), 214 deletions(-)
create mode 100644 static/css/forms.css
diff --git a/static/css/forms.css b/static/css/forms.css
new file mode 100644
index 0000000..33c571e
--- /dev/null
+++ b/static/css/forms.css
@@ -0,0 +1,102 @@
+.form {
+ display: flex;
+ flex-direction: column;
+ gap: 1.25rem;
+}
+
+.form-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
+ gap: 1.25rem;
+}
+
+.form-group {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+}
+
+.form-group label {
+ font-weight: 600;
+ color: var(--text);
+}
+
+.form-group input,
+.form-group select,
+.form-group textarea {
+ padding: 0.75rem 0.85rem;
+ border-radius: var(--radius-sm);
+ border: 1px solid var(--card-border);
+ background: rgba(8, 12, 19, 0.78);
+ color: var(--text);
+ transition: border-color 0.15s ease, background 0.2s ease,
+ box-shadow 0.2s ease;
+}
+
+.form-group textarea {
+ resize: vertical;
+ min-height: 120px;
+}
+
+.form-group input:focus,
+.form-group select:focus,
+.form-group textarea:focus {
+ outline: 2px solid var(--brand-2);
+ outline-offset: 1px;
+}
+
+.form-group input:disabled,
+.form-group select:disabled,
+.form-group textarea:disabled {
+ cursor: not-allowed;
+ opacity: 0.6;
+}
+
+.form-group--error input,
+.form-group--error select,
+.form-group--error textarea {
+ border-color: rgba(209, 75, 75, 0.6);
+ box-shadow: 0 0 0 1px rgba(209, 75, 75, 0.3);
+}
+
+.field-help {
+ margin: 0;
+ font-size: 0.85rem;
+ color: var(--color-text-subtle);
+}
+
+.field-error {
+ margin: 0;
+ font-size: 0.85rem;
+ color: var(--danger);
+}
+
+.form-actions {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.75rem;
+ justify-content: flex-end;
+}
+
+.form-fieldset {
+ border: 1px solid var(--color-border);
+ border-radius: var(--radius);
+ background: rgba(21, 27, 35, 0.85);
+ box-shadow: var(--shadow);
+ padding: 1.5rem;
+ display: flex;
+ flex-direction: column;
+ gap: 1.25rem;
+}
+
+.form-fieldset legend {
+ font-weight: 700;
+ padding: 0 0.5rem;
+ color: var(--text);
+}
+
+@media (max-width: 640px) {
+ .form-actions {
+ justify-content: stretch;
+ }
+}
diff --git a/static/css/imports.css b/static/css/imports.css
index 799ccec..0f3a281 100644
--- a/static/css/imports.css
+++ b/static/css/imports.css
@@ -35,18 +35,6 @@
gap: 0.5rem;
}
-.btn-ghost {
- background: transparent;
- border: none;
- cursor: pointer;
- padding: 0.25rem 0.5rem;
- color: var(--text-muted);
-}
-
-.btn-ghost:hover {
- color: var(--primary-color);
-}
-
.toast {
position: fixed;
right: 1rem;
diff --git a/static/css/main.css b/static/css/main.css
index f18c3a0..0fdb23f 100644
--- a/static/css/main.css
+++ b/static/css/main.css
@@ -19,11 +19,25 @@
--color-text-dark: #0f172a;
--color-text-strong: #111827;
--color-border: rgba(255, 255, 255, 0.08);
+ --card-border: rgba(255, 255, 255, 0.08);
--color-border-strong: rgba(255, 255, 255, 0.12);
--color-highlight: rgba(241, 178, 26, 0.08);
--color-panel-shadow: rgba(0, 0, 0, 0.25);
--color-panel-shadow-deep: rgba(0, 0, 0, 0.35);
--color-surface-alt: rgba(21, 27, 35, 0.7);
+ --btn-primary-bg: var(--brand-2);
+ --btn-primary-color: var(--color-text-dark);
+ --btn-primary-hover: var(--brand-3);
+ --btn-secondary-bg: rgba(21, 27, 35, 0.85);
+ --btn-secondary-hover: rgba(21, 27, 35, 0.95);
+ --btn-secondary-border: var(--color-border-strong);
+ --btn-secondary-color: var(--text);
+ --btn-danger-bg: var(--danger);
+ --btn-danger-color: #ffffff;
+ --btn-danger-hover: #e56a6a;
+ --btn-link-color: var(--brand-2);
+ --btn-link-hover: var(--brand-3);
+ --btn-ghost-color: var(--muted);
--space-2xs: 0.25rem;
--space-xs: 0.5rem;
--space-sm: 0.75rem;
@@ -887,36 +901,6 @@ a.sidebar-brand:focus {
font-size: var(--font-size-lg);
}
-.form-grid {
- display: grid;
- gap: var(--space-md);
- max-width: 480px;
-}
-
-.form-grid label {
- display: flex;
- flex-direction: column;
- gap: var(--space-sm);
- font-weight: 600;
- color: var(--text);
-}
-
-.form-grid input,
-.form-grid textarea,
-.form-grid select {
- padding: 0.6rem var(--space-sm);
- border: 1px solid var(--color-border-strong);
- border-radius: 8px;
- font-size: var(--font-size-base);
-}
-
-.form-grid input:focus,
-.form-grid textarea:focus,
-.form-grid select:focus {
- outline: 2px solid var(--brand-2);
- outline-offset: 1px;
-}
-
.btn {
display: inline-flex;
align-items: center;
@@ -924,37 +908,121 @@ a.sidebar-brand:focus {
gap: 0.5rem;
padding: 0.65rem 1.25rem;
border-radius: 999px;
- border: none;
+ border: 1px solid var(--btn-secondary-border);
cursor: pointer;
font-weight: 600;
- background-color: var(--brand);
- color: var(--color-text-dark);
+ background-color: var(--btn-secondary-bg);
+ color: var(--btn-secondary-color);
text-decoration: none;
- transition: transform 0.15s ease, box-shadow 0.15s ease;
+ transition: transform 0.15s ease, box-shadow 0.15s ease,
+ background-color 0.2s ease, border-color 0.2s ease;
}
.btn:hover,
.btn:focus {
transform: translateY(-1px);
box-shadow: 0 4px 10px var(--color-panel-shadow);
+ background-color: var(--btn-secondary-hover);
}
-.btn.primary {
- background-color: var(--brand-2);
- color: var(--color-text-dark);
+.btn--primary,
+.btn.primary,
+.btn.btn-primary {
+ background-color: var(--btn-primary-bg);
+ border-color: transparent;
+ color: var(--btn-primary-color);
}
+.btn--primary:hover,
+.btn--primary:focus,
.btn.primary:hover,
-.btn.primary:focus {
- background-color: var(--brand-3);
+.btn.primary:focus,
+.btn.btn-primary:hover,
+.btn.btn-primary:focus {
+ background-color: var(--btn-primary-hover);
}
-.btn.btn-link {
- background: var(--brand);
- color: var(--color-text-dark);
- text-decoration: none;
- border: 1px solid var(--brand);
- margin-bottom: 0.5rem;
+.btn--secondary,
+.btn.secondary,
+.btn.btn-secondary {
+ background-color: var(--btn-secondary-bg);
+ border-color: var(--btn-secondary-border);
+ color: var(--btn-secondary-color);
+}
+
+.btn--secondary:hover,
+.btn--secondary:focus,
+.btn.secondary:hover,
+.btn.secondary:focus,
+.btn.btn-secondary:hover,
+.btn.btn-secondary:focus {
+ background-color: var(--btn-secondary-hover);
+}
+
+.btn--danger,
+.btn.danger,
+.btn.btn-danger {
+ background-color: var(--btn-danger-bg);
+ border-color: transparent;
+ color: var(--btn-danger-color);
+}
+
+.btn--danger:hover,
+.btn--danger:focus,
+.btn.danger:hover,
+.btn.danger:focus,
+.btn.btn-danger:hover,
+.btn.btn-danger:focus {
+ background-color: var(--btn-danger-hover);
+}
+
+.btn--link,
+.btn.btn-link,
+.btn.link {
+ padding: 0.25rem 0;
+ border: none;
+ background: transparent;
+ color: var(--btn-link-color);
+ margin: 0;
+ box-shadow: none;
+}
+
+.btn--link:hover,
+.btn--link:focus,
+.btn.btn-link:hover,
+.btn.btn-link:focus,
+.btn.link:hover,
+.btn.link:focus {
+ transform: none;
+ box-shadow: none;
+ color: var(--btn-link-hover);
+ text-decoration: underline;
+}
+
+.btn--ghost,
+.btn.btn-ghost {
+ background: transparent;
+ border: 1px solid transparent;
+ color: var(--btn-ghost-color);
+}
+
+.btn--ghost:hover,
+.btn--ghost:focus,
+.btn.btn-ghost:hover,
+.btn.btn-ghost:focus {
+ background: rgba(255, 255, 255, 0.1);
+ border-color: rgba(255, 255, 255, 0.2);
+}
+
+.btn--icon {
+ padding: 0.4rem;
+ border-radius: 50%;
+ line-height: 0;
+}
+
+.btn--icon:hover,
+.btn--icon:focus {
+ transform: none;
}
.result-output {
diff --git a/static/css/projects.css b/static/css/projects.css
index 6a2fe08..52c838d 100644
--- a/static/css/projects.css
+++ b/static/css/projects.css
@@ -108,7 +108,7 @@
flex-wrap: wrap;
}
-.project-card__links .btn-link {
+.project-card__links .btn--link {
padding: 3px 4px;
border-radius: 8px;
}
@@ -342,7 +342,7 @@
flex-wrap: wrap;
}
-.scenario-item__actions .btn-link {
+.scenario-item__actions .btn--link {
padding: 0;
}
@@ -421,37 +421,3 @@
max-width: 70%;
}
}
-
-.form {
- display: flex;
- flex-direction: column;
- gap: 1.25rem;
-}
-
-.form-grid {
- display: grid;
- grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
- gap: 1.25rem;
-}
-
-.form-group {
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
-}
-
-.form-group input,
-.form-group select,
-.form-group textarea {
- padding: 0.75rem 0.85rem;
- border-radius: var(--radius-sm);
- border: 1px solid var(--card-border);
- background: rgba(8, 12, 19, 0.75);
- color: var(--text);
-}
-
-.form-actions {
- display: flex;
- gap: 0.75rem;
- justify-content: flex-end;
-}
diff --git a/static/css/scenarios.css b/static/css/scenarios.css
index a9b0d38..a2c5637 100644
--- a/static/css/scenarios.css
+++ b/static/css/scenarios.css
@@ -120,63 +120,6 @@
margin: 0;
}
-.scenario-form .form-grid {
- display: grid;
- grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
- gap: 1.25rem;
-}
-
-.scenario-form .form-group {
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
-}
-
-.scenario-form .form-group label {
- font-weight: 600;
- color: var(--text);
-}
-
-.scenario-form .form-group input,
-.scenario-form .form-group select,
-.scenario-form .form-group textarea {
- padding: 0.75rem 0.85rem;
- border-radius: var(--radius-sm);
- border: 1px solid var(--card-border);
- background: rgba(8, 12, 19, 0.78);
- color: var(--text);
-}
-
-.scenario-form .form-group textarea {
- resize: vertical;
-}
-
-.scenario-form .form-group input:focus,
-.scenario-form .form-group select:focus,
-.scenario-form .form-group textarea:focus {
- outline: 2px solid var(--brand-2);
- outline-offset: 1px;
-}
-
-.form-group--error input,
-.form-group--error select,
-.form-group--error textarea {
- border-color: rgba(209, 75, 75, 0.6);
- box-shadow: 0 0 0 1px rgba(209, 75, 75, 0.3);
-}
-
-.field-help {
- margin: 0;
- font-size: 0.85rem;
- color: var(--color-text-subtle);
-}
-
-.field-error {
- margin: 0;
- font-size: 0.85rem;
- color: var(--danger);
-}
-
.table-responsive {
width: 100%;
overflow-x: auto;
@@ -396,7 +339,7 @@
flex-wrap: wrap;
}
-.scenario-item__actions .btn-link {
+.scenario-item__actions .btn--link {
padding: 0;
}
diff --git a/templates/base.html b/templates/base.html
index ff699f3..3108982 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -4,8 +4,9 @@
{% block title %}CalMiner{% endblock %}
-
-
+
+
+
{% block head_extra %}{% endblock %}
diff --git a/templates/exports/modal.html b/templates/exports/modal.html
index 7f1a107..4122e17 100644
--- a/templates/exports/modal.html
+++ b/templates/exports/modal.html
@@ -9,7 +9,7 @@
Export {{ dataset|capitalize }}
@@ -40,10 +40,10 @@
>
diff --git a/templates/imports/ui.html b/templates/imports/ui.html
index c583047..bb2324e 100644
--- a/templates/imports/ui.html
+++ b/templates/imports/ui.html
@@ -24,8 +24,8 @@
{% include "partials/import_preview_table.html" %}
-
-
+
+
diff --git a/templates/login.html b/templates/login.html
index 106648e..bff5388 100644
--- a/templates/login.html
+++ b/templates/login.html
@@ -26,7 +26,7 @@
-
+
Don't have an account? Register here
Forgot password?
diff --git a/templates/partials/import_upload.html b/templates/partials/import_upload.html
index e0879a1..fcd9290 100644
--- a/templates/partials/import_upload.html
+++ b/templates/partials/import_upload.html
@@ -9,7 +9,7 @@
-
-
+
+
{{ feedback("import-upload-feedback", hidden=True, role="alert") }}
diff --git a/templates/projects/detail.html b/templates/projects/detail.html
index f0eeae1..1f301ab 100644
--- a/templates/projects/detail.html
+++ b/templates/projects/detail.html
@@ -17,9 +17,9 @@
{{ project.operation_type.value.replace('_', ' ') | title }}
@@ -99,7 +99,7 @@
Scenarios
Project scenarios inherit pricing and provide entry points to profitability planning.
- Add Scenario
+ Add Scenario
{% if scenarios %}
diff --git a/templates/scenarios/form.html b/templates/scenarios/form.html
index d8fc304..5ab8a4d 100644
--- a/templates/scenarios/form.html
+++ b/templates/scenarios/form.html
@@ -32,8 +32,8 @@
Scenarios inherit pricing defaults from {{ project.name }}.
@@ -145,8 +145,8 @@
{% endblock %}
diff --git a/templates/scenarios/list.html b/templates/scenarios/list.html
index 70eecfd..6cc8b93 100644
--- a/templates/scenarios/list.html
+++ b/templates/scenarios/list.html
@@ -18,8 +18,8 @@
Assumption sets and calculators for {{ project.name }}
@@ -91,7 +91,7 @@
Scenario Portfolio
Each scenario below inherits pricing defaults and links directly into calculators.
- Add Scenario
+ Add Scenario
{% if scenarios %}