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
This commit is contained in:
Janus C. H. Knudsen 2026-01-13 00:09:46 +01:00
parent 15579acba8
commit 2e6207bb0b
33 changed files with 971 additions and 796 deletions

View file

@ -152,19 +152,19 @@
<div class="summary">
<div class="stat-card">
<div class="stat-label">Total CSS Size</div>
<div class="stat-value">132.81 KB</div>
<div class="stat-value">134.17 KB</div>
</div>
<div class="stat-card info">
<div class="stat-label">CSS Files</div>
<div class="stat-value">21</div>
<div class="stat-value">22</div>
</div>
<div class="stat-card info">
<div class="stat-label">Total Lines</div>
<div class="stat-value">6.033</div>
<div class="stat-value">6.124</div>
</div>
<div class="stat-card warning">
<div class="stat-label">Unused CSS Rules</div>
<div class="stat-value">61</div>
<div class="stat-value">87</div>
</div>
</div>
@ -186,34 +186,44 @@
<tr>
<td><strong>auth.css</strong></td>
<td>23.66 KB</td>
<td>1144</td>
<td>169</td>
<td>173</td>
<td>571</td>
<td>46</td>
<td>20.41 KB</td>
<td>994</td>
<td>145</td>
<td>149</td>
<td>488</td>
<td>43</td>
</tr>
<tr>
<td><strong>cash.css</strong></td>
<td>19.38 KB</td>
<td>898</td>
<td>132</td>
<td>135</td>
<td>415</td>
<td>42</td>
<td>16.75 KB</td>
<td>782</td>
<td>114</td>
<td>117</td>
<td>359</td>
<td>39</td>
</tr>
<tr>
<td><strong>employees.css</strong></td>
<td>15.55 KB</td>
<td>722</td>
<td>105</td>
<td>108</td>
<td>345</td>
<td>15.02 KB</td>
<td>694</td>
<td>100</td>
<td>103</td>
<td>327</td>
<td>37</td>
</tr>
<tr>
<td><strong>components.css</strong></td>
<td>9.23 KB</td>
<td>426</td>
<td>63</td>
<td>63</td>
<td>185</td>
<td>39</td>
</tr>
<tr>
<td><strong>design-tokens.css</strong></td>
<td>9.02 KB</td>
@ -226,12 +236,12 @@
<tr>
<td><strong>account.css</strong></td>
<td>8.83 KB</td>
<td>402</td>
<td>60</td>
<td>63</td>
<td>173</td>
<td>31</td>
<td>7.31 KB</td>
<td>335</td>
<td>47</td>
<td>50</td>
<td>146</td>
<td>30</td>
</tr>
<tr>
@ -245,13 +255,13 @@
</tr>
<tr>
<td><strong>page.css</strong></td>
<td>6.00 KB</td>
<td>276</td>
<td>38</td>
<td>40</td>
<td>117</td>
<td>35</td>
<td><strong>stats.css</strong></td>
<td>5.87 KB</td>
<td>262</td>
<td>34</td>
<td>36</td>
<td>93</td>
<td>30</td>
</tr>
<tr>
@ -265,29 +275,29 @@
</tr>
<tr>
<td><strong>waitlist.css</strong></td>
<td>5.55 KB</td>
<td>251</td>
<td>30</td>
<td>30</td>
<td>131</td>
<td><strong>page.css</strong></td>
<td>5.07 KB</td>
<td>231</td>
<td>31</td>
<td>33</td>
<td>92</td>
<td>33</td>
</tr>
<tr>
<td><strong>stats.css</strong></td>
<td>5.18 KB</td>
<td>232</td>
<td>30</td>
<td>32</td>
<td>78</td>
<td>27</td>
<td><strong>waitlist.css</strong></td>
<td>4.63 KB</td>
<td>211</td>
<td>25</td>
<td>25</td>
<td>101</td>
<td>28</td>
</tr>
<tr>
<td><strong>bookings.css</strong></td>
<td>4.27 KB</td>
<td>176</td>
<td>4.34 KB</td>
<td>177</td>
<td>28</td>
<td>28</td>
<td>75</td>
@ -364,6 +374,16 @@
<td>8</td>
</tr>
<tr>
<td><strong>utilities.css</strong></td>
<td>2.03 KB</td>
<td>119</td>
<td>24</td>
<td>24</td>
<td>44</td>
<td>9</td>
</tr>
<tr>
<td><strong>notifications.css</strong></td>
<td>1.67 KB</td>
@ -384,16 +404,6 @@
<td>6</td>
</tr>
<tr>
<td><strong>quick-stats.css</strong></td>
<td>0.88 KB</td>
<td>39</td>
<td>4</td>
<td>4</td>
<td>15</td>
<td>11</td>
</tr>
</tbody>
</table>
</section>
@ -422,6 +432,27 @@
</div>
<div class="file-detail">
<h3>utilities.css</h3>
<p>
<span class="badge badge-warning">
23 unused rules
</span>
<span style="margin-left: 10px; color: #666;">
Original: 1001 | After purge: 784
</span>
</p>
<details>
<summary>Show unused selectors</summary>
<div class="rejected-list">
.flex-center<br>.flex-between<br>.flex-start<br>.flex-end<br>.flex-column<br>.flex-1<br>.flex-shrink-0<br>.text-truncate<br>.text-center<br>.text-right<br>.text-secondary<br>.text-muted<br>.text-mono<br>.gap-2<br>.gap-3<br>.gap-4<br>.gap-6<br>.gap-8<br>.mt-auto<br>.mb-0<br>.sr-only<br>.w-full<br>.min-w-0
</div>
</details>
</div>
<div class="file-detail">
<h3>design-system.css</h3>
<p>
@ -443,6 +474,27 @@
</div>
<div class="file-detail">
<h3>components.css</h3>
<p>
<span class="badge badge-success">
7 unused rules
</span>
<span style="margin-left: 10px; color: #666;">
Original: 8905 | After purge: 8780
</span>
</p>
<details>
<summary>Show unused selectors</summary>
<div class="rejected-list">
swp-btn.social<br>swp-btn.social:hover<br>swp-btn.social img<br>swp-plan-badge.free<br>swp-avatar.size-xs<br>swp-avatar.size-sm<br>swp-avatar.size-lg
</div>
</details>
</div>
<div class="file-detail">
<h3>bookings.css</h3>
<p>
@ -450,7 +502,7 @@
6 unused rules
</span>
<span style="margin-left: 10px; color: #666;">
Original: 3924 | After purge: 3756
Original: 3998 | After purge: 3830
</span>
</p>
@ -507,27 +559,6 @@ swp-booking-status.in-progress
</div>
<div class="file-detail">
<h3>auth.css</h3>
<p>
<span class="badge badge-success">
4 unused rules
</span>
<span style="margin-left: 10px; color: #666;">
Original: 23887 | After purge: 23816
</span>
</p>
<details>
<summary>Show unused selectors</summary>
<div class="rejected-list">
swp-btn.social<br>swp-btn.social:hover<br>swp-btn.social img<br>swp-plan-badge.free
</div>
</details>
</div>
<div class="file-detail">
<h3>stats.css</h3>
<p>
@ -535,7 +566,7 @@ swp-booking-status.in-progress
3 unused rules
</span>
<span style="margin-left: 10px; color: #666;">
Original: 5298 | After purge: 5229
Original: 6010 | After purge: 5941
</span>
</p>
@ -557,7 +588,7 @@ swp-stat-card.red swp-stat-value
2 unused rules
</span>
<span style="margin-left: 10px; color: #666;">
Original: 8829 | After purge: 8777
Original: 7277 | After purge: 7225
</span>
</p>
@ -599,7 +630,7 @@ swp-stat-card.red swp-stat-value
1 unused rules
</span>
<span style="margin-left: 10px; color: #666;">
Original: 19816 | After purge: 19778
Original: 17121 | After purge: 17083
</span>
</p>
@ -620,7 +651,7 @@ swp-stat-card.red swp-stat-value
0 unused rules
</span>
<span style="margin-left: 10px; color: #666;">
Original: 5686 | After purge: 5686
Original: 4737 | After purge: 4737
</span>
</p>
<p style="color: #2e7d32; margin-top: 10px;">✅ No unused CSS found!</p>
@ -665,19 +696,6 @@ swp-stat-card.red swp-stat-value
<p style="color: #2e7d32; margin-top: 10px;">✅ No unused CSS found!</p>
</div>
<div class="file-detail">
<h3>quick-stats.css</h3>
<p>
<span class="badge badge-success">
0 unused rules
</span>
<span style="margin-left: 10px; color: #666;">
Original: 899 | After purge: 899
</span>
</p>
<p style="color: #2e7d32; margin-top: 10px;">✅ No unused CSS found!</p>
</div>
<div class="file-detail">
<h3>page.css</h3>
<p>
@ -685,7 +703,7 @@ swp-stat-card.red swp-stat-value
0 unused rules
</span>
<span style="margin-left: 10px; color: #666;">
Original: 6140 | After purge: 6140
Original: 5193 | After purge: 5193
</span>
</p>
<p style="color: #2e7d32; margin-top: 10px;">✅ No unused CSS found!</p>
@ -711,7 +729,7 @@ swp-stat-card.red swp-stat-value
0 unused rules
</span>
<span style="margin-left: 10px; color: #666;">
Original: 15923 | After purge: 15923
Original: 15383 | After purge: 15383
</span>
</p>
<p style="color: #2e7d32; margin-top: 10px;">✅ No unused CSS found!</p>
@ -743,6 +761,19 @@ swp-stat-card.red swp-stat-value
<p style="color: #2e7d32; margin-top: 10px;">✅ No unused CSS found!</p>
</div>
<div class="file-detail">
<h3>auth.css</h3>
<p>
<span class="badge badge-success">
0 unused rules
</span>
<span style="margin-left: 10px; color: #666;">
Original: 20895 | After purge: 20895
</span>
</p>
<p style="color: #2e7d32; margin-top: 10px;">✅ No unused CSS found!</p>
</div>
<div class="file-detail">
<h3>app-layout.css</h3>
<p>
@ -769,7 +800,7 @@ swp-stat-card.red swp-stat-value
</ul>
</section>
<p class="timestamp">Report generated: 12.1.2026, 21.57.11</p>
<p class="timestamp">Report generated: 12.1.2026, 23.25.14</p>
</div>
</body>
</html>

View file

@ -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
}
}

View file

@ -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",