From 2e6207bb0b30b0d61bdbeb534d734b7bb470bea7 Mon Sep 17 00:00:00 2001 From: "Janus C. H. Knudsen" Date: Tue, 13 Jan 2026 00:09:46 +0100 Subject: [PATCH] Reorganizes and optimizes shared CSS components Consolidates UI components into a centralized components.css file Removes duplicate styles across multiple CSS files Adds utility classes in a new utilities.css file Reduces overall CSS complexity and improves maintainability Removes quick-stats.css and redistributes its styles Updates layout and stylesheet references accordingly --- .claude/settings.local.json | 3 +- PTWork.code-workspace | 2 +- .../Components/CashApproval/Default.cshtml | 4 +- .../Components/CashBalance/Default.cshtml | 4 +- .../Components/PeriodInfo/Default.cshtml | 4 +- .../Components/PeriodRevenue/Default.cshtml | 5 +- .../ReconciliationNote/Default.cshtml | 4 +- .../Components/AttentionList/Default.cshtml | 7 +- .../Components/BookingList/Default.cshtml | 11 +- .../NotificationList/Default.cshtml | 11 +- .../Components/QuickStatList/Default.cshtml | 7 +- .../Features/Dashboard/Pages/Index.cshtml | 4 +- .../Features/_Shared/Pages/_Layout.cshtml | 5 +- .../reports/css-analysis-report.html | 233 ++++++---- PlanTempus.Application/reports/css-stats.json | 191 ++++---- .../reports/purgecss-report.json | 103 +++-- PlanTempus.Application/tmpclaude-7b53-cwd | 1 + .../wwwroot/css/COMPONENT-CATALOG.md | 26 +- .../wwwroot/css/account.css | 75 +-- PlanTempus.Application/wwwroot/css/auth.css | 164 +------ .../wwwroot/css/bookings.css | 1 + PlanTempus.Application/wwwroot/css/cash.css | 126 +---- .../wwwroot/css/components.css | 434 ++++++++++++++++++ .../wwwroot/css/employees.css | 55 +-- PlanTempus.Application/wwwroot/css/page.css | 49 +- .../wwwroot/css/quick-stats.css | 38 -- PlanTempus.Application/wwwroot/css/stats.css | 30 ++ .../wwwroot/css/utilities.css | 118 +++++ .../wwwroot/css/waitlist.css | 48 +- tmpclaude-6265-cwd | 1 + tmpclaude-6f72-cwd | 1 + tmpclaude-878e-cwd | 1 + tmpclaude-8eac-cwd | 1 + 33 files changed, 971 insertions(+), 796 deletions(-) create mode 100644 PlanTempus.Application/tmpclaude-7b53-cwd create mode 100644 PlanTempus.Application/wwwroot/css/components.css delete mode 100644 PlanTempus.Application/wwwroot/css/quick-stats.css create mode 100644 PlanTempus.Application/wwwroot/css/utilities.css create mode 100644 tmpclaude-6265-cwd create mode 100644 tmpclaude-6f72-cwd create mode 100644 tmpclaude-878e-cwd create mode 100644 tmpclaude-8eac-cwd diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 8bc6931..822b0ef 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -6,7 +6,8 @@ "Bash(dotnet build:*)", "Bash(find:*)", "Bash(tree:*)", - "Bash(npm run analyze-css:*)" + "Bash(npm run analyze-css:*)", + "Bash(node:*)" ] } } diff --git a/PTWork.code-workspace b/PTWork.code-workspace index cf7dd46..fd2c04e 100644 --- a/PTWork.code-workspace +++ b/PTWork.code-workspace @@ -9,6 +9,6 @@ ], "settings": { "liveServer.settings.port": 5501, - "liveServer.settings.multiRootWorkspaceName": "PlanTempus" + "liveServer.settings.multiRootWorkspaceName": "Calendar" } } \ No newline at end of file diff --git a/PlanTempus.Application/Features/CashRegister/Components/CashApproval/Default.cshtml b/PlanTempus.Application/Features/CashRegister/Components/CashApproval/Default.cshtml index 1be609a..109dfe5 100644 --- a/PlanTempus.Application/Features/CashRegister/Components/CashApproval/Default.cshtml +++ b/PlanTempus.Application/Features/CashRegister/Components/CashApproval/Default.cshtml @@ -1,7 +1,5 @@ - - Afslut dagen - + Afslut dagen diff --git a/PlanTempus.Application/Features/CashRegister/Components/CashBalance/Default.cshtml b/PlanTempus.Application/Features/CashRegister/Components/CashBalance/Default.cshtml index d6f3cc1..beb8052 100644 --- a/PlanTempus.Application/Features/CashRegister/Components/CashBalance/Default.cshtml +++ b/PlanTempus.Application/Features/CashRegister/Components/CashBalance/Default.cshtml @@ -1,7 +1,5 @@ - - Kontanter i kassen - + Kontanter i kassen diff --git a/PlanTempus.Application/Features/CashRegister/Components/PeriodInfo/Default.cshtml b/PlanTempus.Application/Features/CashRegister/Components/PeriodInfo/Default.cshtml index 8956a97..4571d8c 100644 --- a/PlanTempus.Application/Features/CashRegister/Components/PeriodInfo/Default.cshtml +++ b/PlanTempus.Application/Features/CashRegister/Components/PeriodInfo/Default.cshtml @@ -1,7 +1,5 @@ - - Periodeoplysninger - + Periodeoplysninger Periode diff --git a/PlanTempus.Application/Features/CashRegister/Components/PeriodRevenue/Default.cshtml b/PlanTempus.Application/Features/CashRegister/Components/PeriodRevenue/Default.cshtml index aac8bde..b2a5cf0 100644 --- a/PlanTempus.Application/Features/CashRegister/Components/PeriodRevenue/Default.cshtml +++ b/PlanTempus.Application/Features/CashRegister/Components/PeriodRevenue/Default.cshtml @@ -1,8 +1,5 @@ - - Periodens omsætning - Systemtal vs. kontrol - + Periodens omsætning diff --git a/PlanTempus.Application/Features/CashRegister/Components/ReconciliationNote/Default.cshtml b/PlanTempus.Application/Features/CashRegister/Components/ReconciliationNote/Default.cshtml index bda7473..b7d1936 100644 --- a/PlanTempus.Application/Features/CashRegister/Components/ReconciliationNote/Default.cshtml +++ b/PlanTempus.Application/Features/CashRegister/Components/ReconciliationNote/Default.cshtml @@ -1,7 +1,5 @@ - - Note til afstemning - + Note til afstemning diff --git a/PlanTempus.Application/Features/Dashboard/Components/AttentionList/Default.cshtml b/PlanTempus.Application/Features/Dashboard/Components/AttentionList/Default.cshtml index 19b9d54..77f5360 100644 --- a/PlanTempus.Application/Features/Dashboard/Components/AttentionList/Default.cshtml +++ b/PlanTempus.Application/Features/Dashboard/Components/AttentionList/Default.cshtml @@ -1,12 +1,7 @@ @model PlanTempus.Application.Features.Dashboard.Components.AttentionListViewModel - - - - @Model.Title - - + @Model.Title @foreach (var attentionKey in Model.AttentionKeys) diff --git a/PlanTempus.Application/Features/Dashboard/Components/BookingList/Default.cshtml b/PlanTempus.Application/Features/Dashboard/Components/BookingList/Default.cshtml index 71acecf..3c46b91 100644 --- a/PlanTempus.Application/Features/Dashboard/Components/BookingList/Default.cshtml +++ b/PlanTempus.Application/Features/Dashboard/Components/BookingList/Default.cshtml @@ -1,13 +1,10 @@ @model PlanTempus.Application.Features.Dashboard.Components.BookingListViewModel - - - - @Model.Title - - Se alle - + + @Model.Title + Se alle + Nu: @Model.CurrentTime diff --git a/PlanTempus.Application/Features/Dashboard/Components/NotificationList/Default.cshtml b/PlanTempus.Application/Features/Dashboard/Components/NotificationList/Default.cshtml index 9b5b5ab..73a739d 100644 --- a/PlanTempus.Application/Features/Dashboard/Components/NotificationList/Default.cshtml +++ b/PlanTempus.Application/Features/Dashboard/Components/NotificationList/Default.cshtml @@ -1,13 +1,10 @@ @model PlanTempus.Application.Features.Dashboard.Components.NotificationListViewModel - - - - @Model.Title - - @Model.ActionText - + + @Model.Title + @Model.ActionText + @foreach (var notificationKey in Model.NotificationKeys) diff --git a/PlanTempus.Application/Features/Dashboard/Components/QuickStatList/Default.cshtml b/PlanTempus.Application/Features/Dashboard/Components/QuickStatList/Default.cshtml index 62d0e35..c309c10 100644 --- a/PlanTempus.Application/Features/Dashboard/Components/QuickStatList/Default.cshtml +++ b/PlanTempus.Application/Features/Dashboard/Components/QuickStatList/Default.cshtml @@ -1,12 +1,7 @@ @model PlanTempus.Application.Features.Dashboard.Components.QuickStatListViewModel - - - - @Model.Title - - + @Model.Title @foreach (var statKey in Model.StatKeys) diff --git a/PlanTempus.Application/Features/Dashboard/Pages/Index.cshtml b/PlanTempus.Application/Features/Dashboard/Pages/Index.cshtml index ad4c940..fd12e17 100644 --- a/PlanTempus.Application/Features/Dashboard/Pages/Index.cshtml +++ b/PlanTempus.Application/Features/Dashboard/Pages/Index.cshtml @@ -50,9 +50,7 @@ - - Hurtige handlinger - + Hurtige handlinger diff --git a/PlanTempus.Application/Features/_Shared/Pages/_Layout.cshtml b/PlanTempus.Application/Features/_Shared/Pages/_Layout.cshtml index 75a0e00..d694710 100644 --- a/PlanTempus.Application/Features/_Shared/Pages/_Layout.cshtml +++ b/PlanTempus.Application/Features/_Shared/Pages/_Layout.cshtml @@ -7,8 +7,12 @@ + + + + @@ -21,7 +25,6 @@ - diff --git a/PlanTempus.Application/reports/css-analysis-report.html b/PlanTempus.Application/reports/css-analysis-report.html index c2e18ad..64ebc53 100644 --- a/PlanTempus.Application/reports/css-analysis-report.html +++ b/PlanTempus.Application/reports/css-analysis-report.html @@ -152,19 +152,19 @@
Total CSS Size
-
132.81 KB
+
134.17 KB
CSS Files
-
21
+
22
Total Lines
-
6.033
+
6.124
Unused CSS Rules
-
61
+
87
@@ -186,34 +186,44 @@ auth.css - 23.66 KB - 1144 - 169 - 173 - 571 - 46 + 20.41 KB + 994 + 145 + 149 + 488 + 43 cash.css - 19.38 KB - 898 - 132 - 135 - 415 - 42 + 16.75 KB + 782 + 114 + 117 + 359 + 39 employees.css - 15.55 KB - 722 - 105 - 108 - 345 + 15.02 KB + 694 + 100 + 103 + 327 37 + + components.css + 9.23 KB + 426 + 63 + 63 + 185 + 39 + + design-tokens.css 9.02 KB @@ -226,12 +236,12 @@ account.css - 8.83 KB - 402 - 60 - 63 - 173 - 31 + 7.31 KB + 335 + 47 + 50 + 146 + 30 @@ -245,13 +255,13 @@ - page.css - 6.00 KB - 276 - 38 - 40 - 117 - 35 + stats.css + 5.87 KB + 262 + 34 + 36 + 93 + 30 @@ -265,29 +275,29 @@ - waitlist.css - 5.55 KB - 251 - 30 - 30 - 131 + page.css + 5.07 KB + 231 31 + 33 + 92 + 33 - stats.css - 5.18 KB - 232 - 30 - 32 - 78 - 27 + waitlist.css + 4.63 KB + 211 + 25 + 25 + 101 + 28 bookings.css - 4.27 KB - 176 + 4.34 KB + 177 28 28 75 @@ -364,6 +374,16 @@ 8 + + utilities.css + 2.03 KB + 119 + 24 + 24 + 44 + 9 + + notifications.css 1.67 KB @@ -384,16 +404,6 @@ 6 - - quick-stats.css - 0.88 KB - 39 - 4 - 4 - 15 - 11 - - @@ -422,6 +432,27 @@ +
+

utilities.css

+

+ + 23 unused rules + + + Original: 1001 | After purge: 784 + +

+ +
+ Show unused selectors +
+ .flex-center
.flex-between
.flex-start
.flex-end
.flex-column
.flex-1
.flex-shrink-0
.text-truncate
.text-center
.text-right
.text-secondary
.text-muted
.text-mono
.gap-2
.gap-3
.gap-4
.gap-6
.gap-8
.mt-auto
.mb-0
.sr-only
.w-full
.min-w-0 + +
+
+ +
+

design-system.css

@@ -443,6 +474,27 @@

+
+

components.css

+

+ + 7 unused rules + + + Original: 8905 | After purge: 8780 + +

+ +
+ Show unused selectors +
+ swp-btn.social
swp-btn.social:hover
swp-btn.social img
swp-plan-badge.free
swp-avatar.size-xs
swp-avatar.size-sm
swp-avatar.size-lg + +
+
+ +
+

bookings.css

@@ -450,7 +502,7 @@ 6 unused rules - Original: 3924 | After purge: 3756 + Original: 3998 | After purge: 3830

@@ -507,27 +559,6 @@ swp-booking-status.in-progress
-
-

auth.css

-

- - 4 unused rules - - - Original: 23887 | After purge: 23816 - -

- -
- Show unused selectors -
- swp-btn.social
swp-btn.social:hover
swp-btn.social img
swp-plan-badge.free - -
-
- -
-

stats.css

@@ -535,7 +566,7 @@ swp-booking-status.in-progress 3 unused rules - Original: 5298 | After purge: 5229 + Original: 6010 | After purge: 5941

@@ -557,7 +588,7 @@ swp-stat-card.red swp-stat-value 2 unused rules - Original: 8829 | After purge: 8777 + Original: 7277 | After purge: 7225

@@ -599,7 +630,7 @@ swp-stat-card.red swp-stat-value 1 unused rules - Original: 19816 | After purge: 19778 + Original: 17121 | After purge: 17083

@@ -620,7 +651,7 @@ swp-stat-card.red swp-stat-value 0 unused rules - Original: 5686 | After purge: 5686 + Original: 4737 | After purge: 4737

✅ No unused CSS found!

@@ -665,19 +696,6 @@ swp-stat-card.red swp-stat-value

✅ No unused CSS found!

-
-

quick-stats.css

-

- - 0 unused rules - - - Original: 899 | After purge: 899 - -

-

✅ No unused CSS found!

-
-

page.css

@@ -685,7 +703,7 @@ swp-stat-card.red swp-stat-value 0 unused rules - Original: 6140 | After purge: 6140 + Original: 5193 | After purge: 5193

✅ No unused CSS found!

@@ -711,7 +729,7 @@ swp-stat-card.red swp-stat-value 0 unused rules - Original: 15923 | After purge: 15923 + Original: 15383 | After purge: 15383

✅ No unused CSS found!

@@ -743,6 +761,19 @@ swp-stat-card.red swp-stat-value

✅ No unused CSS found!

+
+

auth.css

+

+ + 0 unused rules + + + Original: 20895 | After purge: 20895 + +

+

✅ No unused CSS found!

+
+

app-layout.css

@@ -769,7 +800,7 @@ swp-stat-card.red swp-stat-value -

Report generated: 12.1.2026, 21.57.11

+

Report generated: 12.1.2026, 23.25.14

diff --git a/PlanTempus.Application/reports/css-stats.json b/PlanTempus.Application/reports/css-stats.json index 023f2b1..18c7ca1 100644 --- a/PlanTempus.Application/reports/css-stats.json +++ b/PlanTempus.Application/reports/css-stats.json @@ -1,26 +1,26 @@ { "account.css": { - "lines": 402, - "size": "8.83 KB", - "sizeBytes": 9037, - "rules": 60, - "selectors": 63, - "properties": 173, - "uniqueColors": 13, + "lines": 335, + "size": "7.31 KB", + "sizeBytes": 7485, + "rules": 47, + "selectors": 50, + "properties": 146, + "uniqueColors": 12, "colors": [ "var(--color-text)", "var(--color-teal)", - "var(--color-background-alt)", - "var(--color-text-secondary)", "var(--color-surface)", - "var(--color-purple)", - "var(--color-amber)", "rgba(0, 0, 0, 0.08)", + "var(--color-background-alt)", "var(--color-border)", - "var(--color-blue)" + "var(--color-blue)", + "var(--color-text-secondary)", + "var(--color-background-hover)", + "var(--color-green)" ], "mediaQueries": 3, - "cssVariables": 31 + "cssVariables": 30 }, "app-layout.css": { "lines": 51, @@ -59,13 +59,13 @@ "cssVariables": 15 }, "auth.css": { - "lines": 1144, - "size": "23.66 KB", - "sizeBytes": 24232, - "rules": 169, - "selectors": 173, - "properties": 571, - "uniqueColors": 17, + "lines": 994, + "size": "20.41 KB", + "sizeBytes": 20895, + "rules": 145, + "selectors": 149, + "properties": 488, + "uniqueColors": 15, "colors": [ "var(--color-teal)", "#00695c", @@ -74,12 +74,12 @@ "var(--color-background)", "var(--color-text)", "var(--color-text-secondary)", - "var(--color-surface)", - "var(--color-border)", - "var(--color-purple)" + "var(--color-purple)", + "var(--color-green)", + "var(--color-surface)" ], "mediaQueries": 3, - "cssVariables": 46 + "cssVariables": 43 }, "base.css": { "lines": 119, @@ -99,9 +99,9 @@ "cssVariables": 8 }, "bookings.css": { - "lines": 176, - "size": "4.27 KB", - "sizeBytes": 4369, + "lines": 177, + "size": "4.34 KB", + "sizeBytes": 4443, "rules": 28, "selectors": 28, "properties": 75, @@ -122,13 +122,13 @@ "cssVariables": 27 }, "cash.css": { - "lines": 898, - "size": "19.38 KB", - "sizeBytes": 19850, - "rules": 132, - "selectors": 135, - "properties": 415, - "uniqueColors": 14, + "lines": 782, + "size": "16.75 KB", + "sizeBytes": 17155, + "rules": 114, + "selectors": 117, + "properties": 359, + "uniqueColors": 12, "colors": [ "var(--color-surface)", "var(--color-border)", @@ -142,7 +142,30 @@ "var(--color-background-hover)" ], "mediaQueries": 3, - "cssVariables": 42 + "cssVariables": 39 + }, + "components.css": { + "lines": 426, + "size": "9.23 KB", + "sizeBytes": 9447, + "rules": 63, + "selectors": 63, + "properties": 185, + "uniqueColors": 16, + "colors": [ + "var(--color-teal)", + "#00796b", + "var(--color-border)", + "var(--color-surface)", + "var(--color-text)", + "var(--color-background-hover)", + "var(--color-text-secondary)", + "var(--color-purple)", + "var(--color-background)", + "var(--color-text-muted)" + ], + "mediaQueries": 0, + "cssVariables": 39 }, "controls.css": { "lines": 149, @@ -251,12 +274,12 @@ "cssVariables": 32 }, "employees.css": { - "lines": 722, - "size": "15.55 KB", - "sizeBytes": 15923, - "rules": 105, - "selectors": 108, - "properties": 345, + "lines": 694, + "size": "15.02 KB", + "sizeBytes": 15383, + "rules": 100, + "selectors": 103, + "properties": 327, "uniqueColors": 15, "colors": [ "var(--color-text-secondary)", @@ -264,11 +287,11 @@ "var(--color-border)", "var(--color-teal)", "var(--color-surface)", - "rgba(0, 0, 0, 0.08)", "var(--color-background-alt)", "var(--color-background-hover)", "var(--color-purple)", - "var(--color-blue)" + "var(--color-blue)", + "var(--color-amber)" ], "mediaQueries": 3, "cssVariables": 37 @@ -291,41 +314,25 @@ "cssVariables": 8 }, "page.css": { - "lines": 276, - "size": "6.00 KB", - "sizeBytes": 6141, - "rules": 38, - "selectors": 40, - "properties": 117, + "lines": 231, + "size": "5.07 KB", + "sizeBytes": 5194, + "rules": 31, + "selectors": 33, + "properties": 92, "uniqueColors": 8, "colors": [ "var(--color-surface)", "var(--color-border)", "var(--color-text)", "var(--color-text-secondary)", - "var(--color-teal)", "var(--color-purple)", + "var(--color-teal)", "var(--color-background)", "var(--color-background-hover)" ], "mediaQueries": 2, - "cssVariables": 35 - }, - "quick-stats.css": { - "lines": 39, - "size": "0.88 KB", - "sizeBytes": 899, - "rules": 4, - "selectors": 4, - "properties": 15, - "uniqueColors": 3, - "colors": [ - "var(--color-background-alt)", - "var(--color-text)", - "var(--color-text-secondary)" - ], - "mediaQueries": 0, - "cssVariables": 11 + "cssVariables": 33 }, "sidebar.css": { "lines": 247, @@ -350,13 +357,13 @@ "cssVariables": 24 }, "stats.css": { - "lines": 232, - "size": "5.18 KB", - "sizeBytes": 5301, - "rules": 30, - "selectors": 32, - "properties": 78, - "uniqueColors": 14, + "lines": 262, + "size": "5.87 KB", + "sizeBytes": 6013, + "rules": 34, + "selectors": 36, + "properties": 93, + "uniqueColors": 15, "colors": [ "var(--color-surface)", "var(--color-border)", @@ -370,7 +377,7 @@ "var(--color-purple)" ], "mediaQueries": 2, - "cssVariables": 27 + "cssVariables": 30 }, "tabs.css": { "lines": 95, @@ -412,14 +419,29 @@ "mediaQueries": 0, "cssVariables": 20 }, + "utilities.css": { + "lines": 119, + "size": "2.03 KB", + "sizeBytes": 2080, + "rules": 24, + "selectors": 24, + "properties": 44, + "uniqueColors": 2, + "colors": [ + "var(--color-text-secondary)", + "var(--color-text-muted)" + ], + "mediaQueries": 0, + "cssVariables": 9 + }, "waitlist.css": { - "lines": 251, - "size": "5.55 KB", - "sizeBytes": 5686, - "rules": 30, - "selectors": 30, - "properties": 131, - "uniqueColors": 9, + "lines": 211, + "size": "4.63 KB", + "sizeBytes": 4737, + "rules": 25, + "selectors": 25, + "properties": 101, + "uniqueColors": 8, "colors": [ "var(--color-surface)", "var(--color-border)", @@ -428,10 +450,9 @@ "var(--color-text)", "var(--color-background-alt)", "var(--color-background)", - "var(--color-amber)", - "var(--color-background-hover)" + "var(--color-amber)" ], "mediaQueries": 0, - "cssVariables": 31 + "cssVariables": 28 } } \ No newline at end of file diff --git a/PlanTempus.Application/reports/purgecss-report.json b/PlanTempus.Application/reports/purgecss-report.json index b96102c..8832546 100644 --- a/PlanTempus.Application/reports/purgecss-report.json +++ b/PlanTempus.Application/reports/purgecss-report.json @@ -1,19 +1,49 @@ { "summary": { - "totalFiles": 21, - "totalOriginalSize": 132731, - "totalPurgedSize": 131811, - "totalRejected": 61, - "percentageRemoved": "0.05%", - "potentialSavings": 920 + "totalFiles": 22, + "totalOriginalSize": 132849, + "totalPurgedSize": 131658, + "totalRejected": 87, + "percentageRemoved": "0.07%", + "potentialSavings": 1191 }, "fileDetails": { "waitlist.css": { - "originalSize": 5686, - "purgedSize": 5686, + "originalSize": 4737, + "purgedSize": 4737, "rejectedCount": 0, "rejected": [] }, + "utilities.css": { + "originalSize": 1001, + "purgedSize": 784, + "rejectedCount": 23, + "rejected": [ + ".flex-center", + ".flex-between", + ".flex-start", + ".flex-end", + ".flex-column", + ".flex-1", + ".flex-shrink-0", + ".text-truncate", + ".text-center", + ".text-right", + ".text-secondary", + ".text-muted", + ".text-mono", + ".gap-2", + ".gap-3", + ".gap-4", + ".gap-6", + ".gap-8", + ".mt-auto", + ".mb-0", + ".sr-only", + ".w-full", + ".min-w-0" + ] + }, "topbar.css": { "originalSize": 3885, "purgedSize": 3885, @@ -27,8 +57,8 @@ "rejected": [] }, "stats.css": { - "originalSize": 5298, - "purgedSize": 5229, + "originalSize": 6010, + "purgedSize": 5941, "rejectedCount": 3, "rejected": [ "swp-stat-trend.up", @@ -42,15 +72,9 @@ "rejectedCount": 0, "rejected": [] }, - "quick-stats.css": { - "originalSize": 899, - "purgedSize": 899, - "rejectedCount": 0, - "rejected": [] - }, "page.css": { - "originalSize": 6140, - "purgedSize": 6140, + "originalSize": 5193, + "purgedSize": 5193, "rejectedCount": 0, "rejected": [] }, @@ -61,8 +85,8 @@ "rejected": [] }, "employees.css": { - "originalSize": 15923, - "purgedSize": 15923, + "originalSize": 15383, + "purgedSize": 15383, "rejectedCount": 0, "rejected": [] }, @@ -135,17 +159,31 @@ "rejectedCount": 0, "rejected": [] }, + "components.css": { + "originalSize": 8905, + "purgedSize": 8780, + "rejectedCount": 7, + "rejected": [ + "swp-btn.social", + "swp-btn.social:hover", + "swp-btn.social img", + "swp-plan-badge.free", + "swp-avatar.size-xs", + "swp-avatar.size-sm", + "swp-avatar.size-lg" + ] + }, "cash.css": { - "originalSize": 19816, - "purgedSize": 19778, + "originalSize": 17121, + "purgedSize": 17083, "rejectedCount": 1, "rejected": [ "swp-cash-stat.user swp-cash-stat-value" ] }, "bookings.css": { - "originalSize": 3924, - "purgedSize": 3756, + "originalSize": 3998, + "purgedSize": 3830, "rejectedCount": 6, "rejected": [ "swp-booking-item.inprogress", @@ -168,15 +206,10 @@ ] }, "auth.css": { - "originalSize": 23887, - "purgedSize": 23816, - "rejectedCount": 4, - "rejected": [ - "swp-btn.social", - "swp-btn.social:hover", - "swp-btn.social img", - "swp-plan-badge.free" - ] + "originalSize": 20895, + "purgedSize": 20895, + "rejectedCount": 0, + "rejected": [] }, "attentions.css": { "originalSize": 2524, @@ -197,8 +230,8 @@ "rejected": [] }, "account.css": { - "originalSize": 8829, - "purgedSize": 8777, + "originalSize": 7277, + "purgedSize": 7225, "rejectedCount": 2, "rejected": [ "swp-invoice-status.pending", diff --git a/PlanTempus.Application/tmpclaude-7b53-cwd b/PlanTempus.Application/tmpclaude-7b53-cwd new file mode 100644 index 0000000..b31e703 --- /dev/null +++ b/PlanTempus.Application/tmpclaude-7b53-cwd @@ -0,0 +1 @@ +/c/Users/Janus Knudsen/source/swp-repos/PlanTempus/PlanTempus.Application diff --git a/PlanTempus.Application/wwwroot/css/COMPONENT-CATALOG.md b/PlanTempus.Application/wwwroot/css/COMPONENT-CATALOG.md index 27ee15c..d1ae087 100644 --- a/PlanTempus.Application/wwwroot/css/COMPONENT-CATALOG.md +++ b/PlanTempus.Application/wwwroot/css/COMPONENT-CATALOG.md @@ -13,10 +13,32 @@ Reference for alle genbrugelige komponenter. **LAV ALDRIG EN NY KOMPONENT HVIS D | `swp-page-title` | Titel-wrapper med h1 og p | h1 + subtitle | | `swp-page-actions` | Action buttons i header | Flex gap | | `swp-card` | Standard card wrapper | Border, padding, rounded | -| `swp-card-header` | Card header | Flex, title + action | -| `swp-card-title` | Card titel med ikon | `... Text` | +| `swp-section-label` | Card section label | Uppercase, 11px, border-bottom | +| `swp-section-header` | Wrapper for label + action | Flex, space-between | +| `swp-section-action` | Action link i section header | Teal, clickable | | `swp-card-content` | Card indhold | Block | +### Card Header Eksempler + +**Simpel label (uden action):** +```html + + Kontakter + ... + +``` + +**Label med action:** +```html + + + Dagens bookinger + Se alle + + ... + +``` + --- ## Stats Components (stats.css) diff --git a/PlanTempus.Application/wwwroot/css/account.css b/PlanTempus.Application/wwwroot/css/account.css index 980e89c..c57e65b 100644 --- a/PlanTempus.Application/wwwroot/css/account.css +++ b/PlanTempus.Application/wwwroot/css/account.css @@ -3,6 +3,8 @@ * * For logged-in users to manage their subscription plan, * payment method, and view invoice history. + * + * Reuses: swp-btn, swp-plan-card, swp-plan-badge, swp-plan-action (components.css) */ /* =========================================== @@ -49,46 +51,7 @@ swp-plan-grid { } } -/* Plan card current state (extends auth.css) */ -swp-plan-card.current { - border-color: var(--color-teal); - box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-teal) 15%, transparent); -} - -swp-plan-badge.current { - background: color-mix(in srgb, var(--color-teal) 15%, transparent); - color: var(--color-teal); -} - -/* Disabled button for current plan */ -swp-plan-card.current swp-btn.secondary { - background: var(--color-background-alt); - color: var(--color-text-secondary); - cursor: default; - pointer-events: none; -} - -/* Enterprise plan styling */ -swp-plan-card.enterprise { - background: linear-gradient(135deg, var(--color-surface) 0%, color-mix(in srgb, var(--color-purple) 5%, var(--color-surface)) 100%); - border-color: var(--color-purple); -} - -swp-plan-badge.popular { - background: color-mix(in srgb, var(--color-amber) 15%, transparent); - color: var(--color-amber); -} - -/* Plan action buttons */ -swp-plan-action { - margin-top: auto; - padding-top: var(--card-padding); -} - -swp-plan-action swp-btn { - width: 100%; - justify-content: center; -} +/* Plan card/badge/action styles in components.css */ /* =========================================== BILLING GRID (2 columns) @@ -343,37 +306,7 @@ swp-download-btn i { font-size: 14px; } -/* =========================================== - BUTTONS (account-specific) - =========================================== */ -swp-btn.secondary { - background: var(--color-surface); - border: 1px solid var(--color-border); - color: var(--color-text); -} - -swp-btn.secondary:hover { - background: var(--color-background-hover); -} - -swp-btn.outline { - background: transparent; - border: 1px solid var(--color-teal); - color: var(--color-teal); -} - -swp-btn.outline:hover { - background: color-mix(in srgb, var(--color-teal) 10%, transparent); -} - -swp-btn.sm { - padding: var(--spacing-2) var(--spacing-3); - font-size: var(--font-size-xs); -} - -swp-btn.sm i { - font-size: 14px; -} +/* Button styles in components.css */ /* =========================================== RESPONSIVE diff --git a/PlanTempus.Application/wwwroot/css/auth.css b/PlanTempus.Application/wwwroot/css/auth.css index 714f7cb..eca5b86 100644 --- a/PlanTempus.Application/wwwroot/css/auth.css +++ b/PlanTempus.Application/wwwroot/css/auth.css @@ -3,6 +3,8 @@ * * Login, Signup, Password Reset etc. * Split-screen SaaS layout pattern + * + * Reuses: swp-btn, swp-plan-card, swp-plan-badge (components.css) */ /* =========================================== @@ -124,46 +126,13 @@ swp-selected-plan-header { } /* =========================================== - PLAN CARD (Selected Plan) + PLAN CONTENT (Auth-specific layout) + Plan card/badge base styles in components.css =========================================== */ -swp-plan-card { - display: flex; - flex-direction: column; - background: var(--color-surface); - border: 2px solid var(--color-border); - border-radius: var(--radius-xl); - padding: var(--spacing-10); - transition: all var(--transition-normal); -} - -swp-plan-card.selected { - border-color: var(--color-teal); - box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-teal) 15%, transparent); -} - swp-plan-badge { - display: inline-flex; - align-items: center; - gap: var(--spacing-2); - padding: var(--spacing-2) var(--spacing-3); - font-size: var(--font-size-xs); - font-weight: var(--font-weight-semibold); - text-transform: uppercase; - letter-spacing: 0.5px; - border-radius: var(--radius-pill); - width: fit-content; margin-bottom: var(--spacing-4); } -swp-plan-badge.selected { - background: color-mix(in srgb, var(--color-teal) 15%, transparent); - color: var(--color-teal); -} - -swp-plan-badge i { - font-size: 14px; -} - swp-plan-name { display: block; font-size: var(--font-size-2xl); @@ -589,52 +558,7 @@ swp-form-checkbox a:hover { text-decoration: underline; } -/* =========================================== - BUTTONS - =========================================== */ -swp-btn { - display: inline-flex; - align-items: center; - justify-content: center; - gap: var(--spacing-2); - padding: var(--spacing-3) var(--spacing-6); - font-size: var(--font-size-base); - font-weight: var(--font-weight-medium); - font-family: var(--font-family); - border-radius: var(--border-radius); - border: 1px solid transparent; - cursor: pointer; - transition: all var(--transition-fast); - text-decoration: none; -} - -swp-btn.primary { - background: var(--color-teal); - color: white; - border-color: var(--color-teal); -} - -swp-btn.primary:hover { - background: #00796b; - border-color: #00796b; -} - -swp-btn.primary:active { - transform: translateY(1px); -} - -swp-btn.full-width { - width: 100%; -} - -swp-btn.lg { - padding: var(--spacing-4) var(--spacing-8); - font-size: var(--font-size-lg); -} - -swp-btn i { - font-size: 18px; -} +/* Button base styles in components.css */ /* =========================================== AUTH FOOTER @@ -692,21 +616,7 @@ swp-social-buttons { gap: var(--spacing-3); } -swp-btn.social { - background: var(--color-background); - color: var(--color-text); - border-color: var(--color-border); -} - -swp-btn.social:hover { - background: var(--color-background-hover); - border-color: var(--color-text-muted); -} - -swp-btn.social img { - width: 20px; - height: 20px; -} +/* Social button styles in components.css */ /* =========================================== FORM MESSAGES @@ -819,72 +729,12 @@ swp-pricing-grid swp-plan-card.popular { transform: scale(1.02); } -swp-pricing-grid swp-plan-card.enterprise { - background: linear-gradient(135deg, var(--color-surface) 0%, color-mix(in srgb, var(--color-purple) 5%, var(--color-surface)) 100%); - border-color: var(--color-purple); -} - -swp-plan-badge.popular { - background: color-mix(in srgb, var(--color-teal) 15%, transparent); - color: var(--color-teal); -} - -swp-plan-badge.enterprise { - background: color-mix(in srgb, var(--color-purple) 15%, transparent); - color: var(--color-purple); -} - -swp-plan-badge.free { - background: color-mix(in srgb, var(--color-green) 15%, transparent); - color: var(--color-green); -} +/* Plan badge/button styles in components.css */ swp-pricing-grid swp-plan-action { margin-top: var(--spacing-6); } -/* Button styles for pricing */ -.swp-btn { - display: inline-flex; - align-items: center; - justify-content: center; - gap: var(--spacing-2); - padding: var(--spacing-3) var(--spacing-6); - font-size: var(--font-size-base); - font-weight: var(--font-weight-medium); - font-family: var(--font-family); - border-radius: var(--border-radius); - border: 1px solid transparent; - cursor: pointer; - transition: all var(--transition-fast); - text-decoration: none; -} - -.swp-btn.primary { - background: var(--color-teal); - color: white; - border-color: var(--color-teal); -} - -.swp-btn.primary:hover { - background: #00796b; - border-color: #00796b; -} - -.swp-btn.outline { - background: transparent; - color: var(--color-purple); - border-color: var(--color-purple); -} - -.swp-btn.outline:hover { - background: color-mix(in srgb, var(--color-purple) 10%, transparent); -} - -.swp-btn.full-width { - width: 100%; -} - swp-pricing-footer { margin-top: var(--spacing-12); text-align: center; diff --git a/PlanTempus.Application/wwwroot/css/bookings.css b/PlanTempus.Application/wwwroot/css/bookings.css index 5c867f2..e42de20 100644 --- a/PlanTempus.Application/wwwroot/css/bookings.css +++ b/PlanTempus.Application/wwwroot/css/bookings.css @@ -96,6 +96,7 @@ swp-booking-employee { gap: var(--spacing-3); } +/* TODO: Consider using swp-avatar.size-xs from components.css instead */ swp-booking-employee swp-avatar-small { width: 24px; height: 24px; diff --git a/PlanTempus.Application/wwwroot/css/cash.css b/PlanTempus.Application/wwwroot/css/cash.css index 1dfcb14..1bc8f62 100644 --- a/PlanTempus.Application/wwwroot/css/cash.css +++ b/PlanTempus.Application/wwwroot/css/cash.css @@ -3,6 +3,7 @@ * * Filter bar, stats, table, forms, and difference box * Reuses: swp-sticky-header, swp-header-content (page.css) + * Reuses: swp-btn, swp-status-badge, swp-card-footer (components.css) */ /* =========================================== @@ -321,67 +322,14 @@ swp-cash-table-footer { color: var(--color-text-secondary); } -/* =========================================== - STATUS BADGE - =========================================== */ +/* Status badge styles in components.css */ + /* Center status column */ swp-cash-th:nth-child(9), swp-cash-td:nth-child(9) { text-align: center; } -swp-status-badge { - display: inline-flex; - align-items: center; - gap: var(--spacing-3); - padding: var(--spacing-2) var(--spacing-5); - font-size: var(--font-size-xs); - font-weight: var(--font-weight-medium); - border-radius: var(--radius-pill); -} - -swp-status-badge::before { - content: ''; - width: 6px; - height: 6px; - border-radius: var(--radius-full); - background: currentColor; -} - -/* Status variants */ -swp-status-badge.approved, -swp-status-badge.active { - background: color-mix(in srgb, var(--color-green) 15%, transparent); - color: var(--color-green); -} - -swp-status-badge.draft, -swp-status-badge.invited { - background: color-mix(in srgb, var(--color-amber) 15%, transparent); - color: #b45309; -} - -/* Role variants */ -swp-status-badge.owner { - background: color-mix(in srgb, var(--color-teal) 15%, transparent); - color: var(--color-teal); -} - -swp-status-badge.admin { - background: color-mix(in srgb, var(--color-purple) 15%, transparent); - color: var(--color-purple); -} - -swp-status-badge.leader { - background: color-mix(in srgb, var(--color-blue) 15%, transparent); - color: var(--color-blue); -} - -swp-status-badge.employee { - background: var(--color-background-alt); - color: var(--color-text-secondary); -} - /* =========================================== TWO-COLUMN GRID (Detail View) =========================================== */ @@ -774,78 +722,14 @@ swp-checkbox-field label { line-height: var(--line-height-normal); } -/* =========================================== - CARD FOOTER (Actions) - =========================================== */ -swp-card-footer { - display: flex; - justify-content: space-between; - align-items: center; - padding: var(--spacing-8) var(--spacing-10); - background: var(--color-background-alt); - border-top: 1px solid var(--color-border); - margin: var(--spacing-10) calc(-1 * var(--spacing-5)) calc(-1 * var(--spacing-5)); - border-radius: 0 0 var(--border-radius-lg) var(--border-radius-lg); -} +/* Card footer base styles in components.css */ swp-actions-right { display: flex; gap: var(--spacing-5); } -/* =========================================== - BUTTONS - =========================================== */ -swp-btn { - display: inline-flex; - align-items: center; - gap: var(--spacing-3); - padding: var(--spacing-5) var(--spacing-8); - font-size: var(--font-size-md); - font-weight: var(--font-weight-medium); - font-family: var(--font-family); - border-radius: var(--radius-md); - cursor: pointer; - transition: all var(--transition-fast); - border: none; -} - -swp-btn i { - font-size: var(--font-size-lg); -} - -swp-btn.primary { - background: var(--color-teal); - color: white; -} - -swp-btn.primary:hover { - opacity: 0.9; -} - -swp-btn.primary:disabled { - background: var(--color-border); - cursor: not-allowed; -} - -swp-btn.secondary { - background: var(--color-surface); - border: 1px solid var(--color-border); - color: var(--color-text); -} - -swp-btn.secondary:hover { - background: var(--color-background-hover); -} - -swp-btn.ghost { - background: transparent; - color: var(--color-text-secondary); -} - -swp-btn.ghost:hover { - color: var(--color-text); -} +/* Button styles in components.css */ /* =========================================== SYSTEM NOTE diff --git a/PlanTempus.Application/wwwroot/css/components.css b/PlanTempus.Application/wwwroot/css/components.css new file mode 100644 index 0000000..bd0ac48 --- /dev/null +++ b/PlanTempus.Application/wwwroot/css/components.css @@ -0,0 +1,434 @@ +/** + * UI Components - Shared reusable components + * + * This file contains all shared UI components used across the application. + * Feature files should NOT define these components - only use them. + * + * Components: + * - swp-btn (buttons) + * - swp-status-badge (status/role badges) + * - swp-plan-card (subscription plan cards) + * - swp-avatar (user avatars with size variants) + * - swp-icon-btn (icon-only buttons) + * - swp-card (content cards with section-label/footer) + * - swp-section-label (card section headers) + * - swp-section-header (section header with action link) + * - swp-section-action (action link in section header) + */ + +/* =========================================== + BUTTONS (swp-btn) + =========================================== */ +swp-btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: var(--spacing-2); + padding: var(--spacing-3) var(--spacing-6); + font-size: var(--font-size-base); + font-weight: var(--font-weight-medium); + font-family: var(--font-family); + border-radius: var(--radius-md); + border: 1px solid transparent; + cursor: pointer; + transition: all var(--transition-fast); + text-decoration: none; +} + +swp-btn i { + font-size: 18px; +} + +/* Primary button */ +swp-btn.primary { + background: var(--color-teal); + color: white; + border-color: var(--color-teal); +} + +swp-btn.primary:hover { + background: #00796b; + border-color: #00796b; +} + +swp-btn.primary:active { + transform: translateY(1px); +} + +swp-btn.primary:disabled { + background: var(--color-border); + border-color: var(--color-border); + cursor: not-allowed; +} + +/* Secondary button */ +swp-btn.secondary { + background: var(--color-surface); + border: 1px solid var(--color-border); + color: var(--color-text); +} + +swp-btn.secondary:hover { + background: var(--color-background-hover); +} + +/* Ghost button */ +swp-btn.ghost { + background: transparent; + color: var(--color-text-secondary); +} + +swp-btn.ghost:hover { + color: var(--color-text); +} + +/* Outline button */ +swp-btn.outline { + background: transparent; + border: 1px solid var(--color-teal); + color: var(--color-teal); +} + +swp-btn.outline:hover { + background: color-mix(in srgb, var(--color-teal) 10%, transparent); +} + +swp-btn.outline.purple { + border-color: var(--color-purple); + color: var(--color-purple); +} + +swp-btn.outline.purple:hover { + background: color-mix(in srgb, var(--color-purple) 10%, transparent); +} + +/* Social button */ +swp-btn.social { + background: var(--color-background); + color: var(--color-text); + border-color: var(--color-border); +} + +swp-btn.social:hover { + background: var(--color-background-hover); + border-color: var(--color-text-muted); +} + +swp-btn.social img { + width: 20px; + height: 20px; +} + +/* Size variants */ +swp-btn.sm { + padding: var(--spacing-2) var(--spacing-3); + font-size: var(--font-size-xs); +} + +swp-btn.sm i { + font-size: 14px; +} + +swp-btn.lg { + padding: var(--spacing-4) var(--spacing-8); + font-size: var(--font-size-lg); +} + +/* Full width */ +swp-btn.full-width { + width: 100%; +} + +/* =========================================== + STATUS BADGES (swp-status-badge) + =========================================== */ +swp-status-badge { + display: inline-flex; + align-items: center; + gap: var(--spacing-3); + padding: var(--spacing-2) var(--spacing-5); + font-size: var(--font-size-xs); + font-weight: var(--font-weight-medium); + border-radius: var(--radius-pill); +} + +swp-status-badge::before { + content: ''; + width: 6px; + height: 6px; + border-radius: var(--radius-full); + background: currentColor; +} + +/* Status variants */ +swp-status-badge.approved, +swp-status-badge.active { + background: color-mix(in srgb, var(--color-green) 15%, transparent); + color: var(--color-green); +} + +swp-status-badge.draft, +swp-status-badge.invited { + background: color-mix(in srgb, var(--color-amber) 15%, transparent); + color: #b45309; +} + +/* Role variants */ +swp-status-badge.owner { + background: color-mix(in srgb, var(--color-teal) 15%, transparent); + color: var(--color-teal); +} + +swp-status-badge.admin { + background: color-mix(in srgb, var(--color-purple) 15%, transparent); + color: var(--color-purple); +} + +swp-status-badge.leader { + background: color-mix(in srgb, var(--color-blue) 15%, transparent); + color: var(--color-blue); +} + +swp-status-badge.employee { + background: var(--color-background-alt); + color: var(--color-text-secondary); +} + +/* =========================================== + PLAN CARDS (swp-plan-card) + =========================================== */ +swp-plan-card { + display: flex; + flex-direction: column; + background: var(--color-surface); + border: 2px solid var(--color-border); + border-radius: var(--radius-xl); + padding: var(--spacing-10); + transition: all var(--transition-normal); +} + +swp-plan-card.selected, +swp-plan-card.current { + border-color: var(--color-teal); + box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-teal) 15%, transparent); +} + +swp-plan-card.popular { + border-color: var(--color-amber); +} + +swp-plan-card.enterprise { + background: linear-gradient(135deg, var(--color-surface) 0%, color-mix(in srgb, var(--color-purple) 5%, var(--color-surface)) 100%); + border-color: var(--color-purple); +} + +/* Disabled button for current plan */ +swp-plan-card.current swp-btn.secondary { + background: var(--color-background-alt); + color: var(--color-text-secondary); + cursor: default; + pointer-events: none; +} + +/* Plan badge */ +swp-plan-badge { + display: inline-flex; + align-items: center; + gap: var(--spacing-2); + padding: var(--spacing-2) var(--spacing-3); + font-size: var(--font-size-xs); + font-weight: var(--font-weight-semibold); + text-transform: uppercase; + letter-spacing: 0.5px; + border-radius: var(--radius-pill); + width: fit-content; +} + +swp-plan-badge.current, +swp-plan-badge.selected { + background: color-mix(in srgb, var(--color-teal) 15%, transparent); + color: var(--color-teal); +} + +swp-plan-badge.popular { + background: color-mix(in srgb, var(--color-amber) 15%, transparent); + color: var(--color-amber); +} + +swp-plan-badge.enterprise { + background: color-mix(in srgb, var(--color-purple) 15%, transparent); + color: var(--color-purple); +} + +swp-plan-badge.free { + background: color-mix(in srgb, var(--color-green) 15%, transparent); + color: var(--color-green); +} + +swp-plan-badge i { + font-size: 14px; +} + +/* Plan action */ +swp-plan-action { + margin-top: auto; + padding-top: var(--card-padding); +} + +swp-plan-action swp-btn { + width: 100%; +} + +/* =========================================== + AVATARS (swp-avatar) + =========================================== */ +swp-avatar { + border-radius: 50%; + background: var(--color-teal); + color: white; + display: flex; + align-items: center; + justify-content: center; + font-weight: var(--font-weight-semibold); + flex-shrink: 0; +} + +/* Default size (md = 40px) */ +swp-avatar { + width: 40px; + height: 40px; + font-size: var(--font-size-sm); +} + +/* Size variants */ +swp-avatar.size-xs { + width: 24px; + height: 24px; + font-size: 10px; +} + +swp-avatar.size-sm { + width: 36px; + height: 36px; + font-size: var(--font-size-xs); +} + +swp-avatar.size-lg { + width: 80px; + height: 80px; + font-size: var(--font-size-2xl); +} + +/* Color variants */ +swp-avatar.purple { + background: var(--color-purple); +} + +swp-avatar.blue { + background: var(--color-blue); +} + +swp-avatar.amber { + background: var(--color-amber); +} + +swp-avatar.teal { + background: var(--color-teal); +} + +/* =========================================== + ICON BUTTONS (swp-icon-btn) + =========================================== */ +swp-icon-btn { + width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; + border-radius: var(--radius-md); + background: transparent; + border: none; + color: var(--color-text-secondary); + cursor: pointer; + transition: all var(--transition-fast); +} + +swp-icon-btn:hover { + background: var(--color-background-alt); + color: var(--color-text); +} + +swp-icon-btn.danger:hover { + background: color-mix(in srgb, var(--color-red) 10%, transparent); + color: var(--color-red); +} + +swp-icon-btn i { + font-size: 18px; +} + +/* =========================================== + CARDS (swp-card) + =========================================== */ +swp-card { + display: block; + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--border-radius-lg); + padding: var(--card-padding); +} + +/* Section label - simple card header */ +swp-section-label { + display: block; + font-size: var(--font-size-xs); + font-weight: var(--font-weight-semibold); + color: var(--color-text); + text-transform: uppercase; + letter-spacing: 0.5px; + padding-bottom: var(--spacing-4); + border-bottom: 1px solid var(--color-border); + margin-bottom: var(--spacing-6); +} + +/* Section header - wrapper when action link is needed */ +swp-section-header { + display: flex; + justify-content: space-between; + align-items: center; + padding-bottom: var(--spacing-4); + border-bottom: 1px solid var(--color-border); + margin-bottom: var(--spacing-6); +} + +swp-section-header swp-section-label { + padding-bottom: 0; + border-bottom: none; + margin-bottom: 0; +} + +swp-section-action { + font-size: var(--font-size-sm); + color: var(--color-teal); + cursor: pointer; + transition: opacity var(--transition-fast); +} + +swp-section-action:hover { + opacity: 0.8; +} + +swp-card-content { + display: block; +} + +swp-card-footer { + display: flex; + justify-content: space-between; + align-items: center; + padding: var(--spacing-6) var(--card-padding); + background: var(--color-background-alt); + border-top: 1px solid var(--color-border); + margin: var(--spacing-6) calc(-1 * var(--card-padding)) calc(-1 * var(--card-padding)); + border-radius: 0 0 var(--border-radius-lg) var(--border-radius-lg); +} diff --git a/PlanTempus.Application/wwwroot/css/employees.css b/PlanTempus.Application/wwwroot/css/employees.css index a9cc30f..976604a 100644 --- a/PlanTempus.Application/wwwroot/css/employees.css +++ b/PlanTempus.Application/wwwroot/css/employees.css @@ -3,7 +3,8 @@ * * Employees-specific styling only. * Reuses: swp-stat-card (stats.css), swp-stats-row (stats.css), swp-tab-bar (tabs.css), - * swp-btn (cash.css), swp-status-badge (cash.css), swp-row-toggle (cash.css), + * swp-btn, swp-status-badge, swp-icon-btn, swp-card, swp-section-label (components.css), + * swp-row-toggle (cash.css), * swp-sticky-header, swp-header-content (page.css), * swp-toggle-slider, swp-checkbox-list (controls.css) * @@ -57,8 +58,8 @@ swp-users-progress-bar { swp-employee-table-card { display: block; background: var(--color-surface); - border-radius: var(--radius-lg); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08); + border: 1px solid var(--color-border); + border-radius: var(--border-radius-lg); overflow: hidden; } @@ -195,33 +196,7 @@ swp-table-actions { justify-content: flex-end; } -swp-icon-btn { - width: 32px; - height: 32px; - display: flex; - align-items: center; - justify-content: center; - border-radius: var(--radius-md); - background: transparent; - border: none; - color: var(--color-text-secondary); - cursor: pointer; - transition: all var(--transition-fast); -} - -swp-icon-btn:hover { - background: var(--color-background-alt); - color: var(--color-text); -} - -swp-icon-btn.danger:hover { - background: color-mix(in srgb, var(--color-red) 10%, transparent); - color: var(--color-red); -} - -swp-icon-btn i { - font-size: 18px; -} +/* Icon button styles in components.css */ /* =========================================== PERMISSIONS MATRIX @@ -452,7 +427,7 @@ swp-edit-row { } swp-edit-label { - font-size: var(--font-size-sm); + font-size: var(--font-size-md); color: var(--color-text-secondary); } @@ -477,16 +452,7 @@ swp-edit-value:focus { border-color: var(--color-teal); } -/* Section label in cards */ -swp-section-label { - display: block; - font-size: var(--font-size-sm); - font-weight: var(--font-weight-semibold); - color: var(--color-text); - margin-bottom: var(--spacing-6); - padding-bottom: var(--spacing-4); - border-bottom: 1px solid var(--color-border); -} +/* swp-section-label is now in components.css */ /* =========================================== VIEW CONTAINERS (List/Detail swap) @@ -532,12 +498,7 @@ swp-detail-grid > div { gap: var(--spacing-8); } -swp-detail-grid swp-card { - background: var(--color-surface); - border: 1px solid var(--color-border); - border-radius: var(--radius-lg); - padding: var(--card-padding); -} +/* swp-card base styles in components.css */ @media (max-width: 900px) { swp-detail-grid { diff --git a/PlanTempus.Application/wwwroot/css/page.css b/PlanTempus.Application/wwwroot/css/page.css index d04259e..36b83dd 100644 --- a/PlanTempus.Application/wwwroot/css/page.css +++ b/PlanTempus.Application/wwwroot/css/page.css @@ -78,54 +78,9 @@ swp-page-actions { } /* =========================================== - CARDS + CARD CONTENT GRIDS (Page-specific) + Base card styles in components.css =========================================== */ -swp-card { - display: block; - background: var(--color-surface); - border: 1px solid var(--color-border); - border-radius: var(--border-radius-lg); - padding: var(--card-padding); -} - -swp-card-header { - display: flex; - align-items: center; - justify-content: space-between; - margin: calc(-1 * var(--card-padding)) calc(-1 * var(--card-padding)) var(--spacing-5) calc(-1 * var(--card-padding)); - padding: var(--spacing-4) var(--card-padding); - border-bottom: 1px solid var(--color-border); -} - -swp-card-title { - display: flex; - align-items: center; - gap: var(--spacing-2); - font-size: var(--font-size-base); - font-weight: var(--font-weight-semibold); - color: var(--color-text); -} - -swp-card-title i { - font-size: var(--font-size-xl); - color: var(--color-text-secondary); -} - -swp-card-action { - font-size: var(--font-size-md); - color: var(--color-teal); - cursor: pointer; - transition: opacity var(--transition-fast); -} - -swp-card-action:hover { - opacity: 0.8; -} - -swp-card-content { - display: block; -} - /* Card content with grid lists - auto-detect via :has() */ swp-card-content:has(> swp-booking-list), swp-card-content:has(> swp-notification-list), diff --git a/PlanTempus.Application/wwwroot/css/quick-stats.css b/PlanTempus.Application/wwwroot/css/quick-stats.css deleted file mode 100644 index b077e7d..0000000 --- a/PlanTempus.Application/wwwroot/css/quick-stats.css +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Quick Stats CSS - * - * Styling for quick stats components in sidebar - */ - -/* =========================================== - QUICK STATS CONTAINER - =========================================== */ -swp-quick-stats { - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: var(--card-gap); -} - -/* =========================================== - QUICK STAT ITEM - =========================================== */ -swp-quick-stat { - display: flex; - flex-direction: column; - gap: var(--spacing-2); - padding: var(--card-padding); - background: var(--color-background-alt); - border-radius: var(--radius-md); -} - -swp-quick-stat swp-stat-value { - font-size: var(--font-size-xl); - font-weight: var(--font-weight-semibold); - font-family: var(--font-mono); - color: var(--color-text); -} - -swp-quick-stat swp-stat-label { - font-size: var(--font-size-xs); - color: var(--color-text-secondary); -} diff --git a/PlanTempus.Application/wwwroot/css/stats.css b/PlanTempus.Application/wwwroot/css/stats.css index bf79a14..b613486 100644 --- a/PlanTempus.Application/wwwroot/css/stats.css +++ b/PlanTempus.Application/wwwroot/css/stats.css @@ -208,6 +208,36 @@ swp-stat-item swp-stat-label { margin-top: 0; } +/* =========================================== + QUICK STATS (Sidebar Variant) + =========================================== */ +swp-quick-stats { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: var(--card-gap); +} + +swp-quick-stat { + display: flex; + flex-direction: column; + gap: var(--spacing-2); + padding: var(--card-padding); + background: var(--color-background-alt); + border-radius: var(--radius-md); +} + +swp-quick-stat swp-stat-value { + font-size: var(--font-size-xl); + font-weight: var(--font-weight-semibold); + font-family: var(--font-mono); + color: var(--color-text); +} + +swp-quick-stat swp-stat-label { + font-size: var(--font-size-xs); + color: var(--color-text-secondary); +} + /* =========================================== RESPONSIVE =========================================== */ diff --git a/PlanTempus.Application/wwwroot/css/utilities.css b/PlanTempus.Application/wwwroot/css/utilities.css new file mode 100644 index 0000000..5ad5ebc --- /dev/null +++ b/PlanTempus.Application/wwwroot/css/utilities.css @@ -0,0 +1,118 @@ +/** + * Utilities - Common utility classes + * + * Reusable utility classes for common patterns. + * Use sparingly - prefer semantic component styles. + */ + +/* =========================================== + FLEXBOX UTILITIES + =========================================== */ +.flex-center { + display: flex; + align-items: center; + justify-content: center; +} + +.flex-between { + display: flex; + justify-content: space-between; + align-items: center; +} + +.flex-start { + display: flex; + align-items: center; + justify-content: flex-start; +} + +.flex-end { + display: flex; + align-items: center; + justify-content: flex-end; +} + +.flex-column { + display: flex; + flex-direction: column; +} + +.flex-1 { + flex: 1; +} + +.flex-shrink-0 { + flex-shrink: 0; +} + +/* =========================================== + TEXT UTILITIES + =========================================== */ +.text-truncate { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.text-center { + text-align: center; +} + +.text-right { + text-align: right; +} + +.text-secondary { + font-size: var(--font-size-sm); + color: var(--color-text-secondary); +} + +.text-muted { + color: var(--color-text-muted); +} + +.text-mono { + font-family: var(--font-mono); +} + +/* =========================================== + SPACING UTILITIES + =========================================== */ +.gap-2 { gap: var(--spacing-2); } +.gap-3 { gap: var(--spacing-3); } +.gap-4 { gap: var(--spacing-4); } +.gap-6 { gap: var(--spacing-6); } +.gap-8 { gap: var(--spacing-8); } + +.mt-auto { margin-top: auto; } +.mb-0 { margin-bottom: 0; } + +/* =========================================== + VISIBILITY UTILITIES + =========================================== */ +.hidden { + display: none !important; +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +/* =========================================== + WIDTH UTILITIES + =========================================== */ +.w-full { + width: 100%; +} + +.min-w-0 { + min-width: 0; +} diff --git a/PlanTempus.Application/wwwroot/css/waitlist.css b/PlanTempus.Application/wwwroot/css/waitlist.css index 792f774..bc942b1 100644 --- a/PlanTempus.Application/wwwroot/css/waitlist.css +++ b/PlanTempus.Application/wwwroot/css/waitlist.css @@ -2,6 +2,8 @@ * Waitlist CSS * * Styling for waitlist mini card and drawer items + * + * Reuses: swp-btn, swp-avatar (components.css) */ /* =========================================== @@ -84,19 +86,7 @@ swp-waitlist-customer { gap: var(--spacing-6); } -swp-waitlist-customer swp-avatar { - width: 40px; - height: 40px; - border-radius: var(--radius-full); - background: var(--color-teal); - color: white; - display: flex; - align-items: center; - justify-content: center; - font-size: var(--font-size-base); - font-weight: var(--font-weight-semibold); - flex-shrink: 0; -} +/* Avatar base styles in components.css */ swp-waitlist-customer-info { flex: 1; @@ -191,39 +181,9 @@ swp-waitlist-actions { border-top: 1px solid var(--color-border); } +/* Button base styles in components.css */ swp-waitlist-actions swp-btn { flex: 1; - display: inline-flex; - align-items: center; - justify-content: center; - gap: var(--spacing-2); - padding: var(--spacing-4) var(--spacing-6); - font-size: var(--font-size-sm); - font-weight: var(--font-weight-medium); - font-family: var(--font-family); - border-radius: var(--radius-md); - cursor: pointer; - transition: all var(--transition-fast); - border: none; -} - -swp-waitlist-actions swp-btn.secondary { - background: var(--color-surface); - border: 1px solid var(--color-border); - color: var(--color-text); -} - -swp-waitlist-actions swp-btn.secondary:hover { - background: var(--color-background-hover); -} - -swp-waitlist-actions swp-btn.primary { - background: var(--color-teal); - color: white; -} - -swp-waitlist-actions swp-btn.primary:hover { - opacity: 0.9; } /* =========================================== diff --git a/tmpclaude-6265-cwd b/tmpclaude-6265-cwd new file mode 100644 index 0000000..d4d98fc --- /dev/null +++ b/tmpclaude-6265-cwd @@ -0,0 +1 @@ +/c/Users/Janus Knudsen/source/swp-repos/PlanTempus diff --git a/tmpclaude-6f72-cwd b/tmpclaude-6f72-cwd new file mode 100644 index 0000000..d4d98fc --- /dev/null +++ b/tmpclaude-6f72-cwd @@ -0,0 +1 @@ +/c/Users/Janus Knudsen/source/swp-repos/PlanTempus diff --git a/tmpclaude-878e-cwd b/tmpclaude-878e-cwd new file mode 100644 index 0000000..d4d98fc --- /dev/null +++ b/tmpclaude-878e-cwd @@ -0,0 +1 @@ +/c/Users/Janus Knudsen/source/swp-repos/PlanTempus diff --git a/tmpclaude-8eac-cwd b/tmpclaude-8eac-cwd new file mode 100644 index 0000000..d4d98fc --- /dev/null +++ b/tmpclaude-8eac-cwd @@ -0,0 +1 @@ +/c/Users/Janus Knudsen/source/swp-repos/PlanTempus