@necrolab/dashboard 0.5.12 → 0.5.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/.playwright-mcp/verification-accounts-desktop.png +0 -0
  2. package/.playwright-mcp/verification-tasks-desktop.png +0 -0
  3. package/.playwright-mcp/verification-tasks-mobile.png +0 -0
  4. package/README.md +21 -0
  5. package/docs/plans/2026-02-08-tailwind-consolidation-results.md +476 -0
  6. package/docs/plans/2026-02-08-tailwind-consolidation.md +2416 -0
  7. package/package.json +1 -1
  8. package/src/App.vue +2 -163
  9. package/src/assets/css/components/buttons.scss +43 -95
  10. package/src/assets/css/components/forms.scss +10 -28
  11. package/src/assets/css/components/search-groups.scss +80 -0
  12. package/src/assets/css/components/tables.scss +0 -8
  13. package/src/assets/css/main.scss +2 -43
  14. package/src/components/Editors/Account/Account.vue +14 -220
  15. package/src/components/Editors/Account/AccountCreator.vue +0 -4
  16. package/src/components/Editors/Account/AccountView.vue +0 -1
  17. package/src/components/Editors/Account/CreateAccount.vue +36 -107
  18. package/src/components/Editors/Profile/CreateProfile.vue +46 -135
  19. package/src/components/Editors/Profile/Profile.vue +10 -213
  20. package/src/components/Editors/Profile/ProfileView.vue +0 -1
  21. package/src/components/Filter/Filter.vue +14 -17
  22. package/src/components/Filter/FilterPreview.vue +0 -6
  23. package/src/components/Table/Row.vue +1 -1
  24. package/src/components/Table/Table.vue +2 -16
  25. package/src/components/Tasks/CreateTaskAXS.vue +45 -104
  26. package/src/components/Tasks/CreateTaskTM.vue +58 -96
  27. package/src/components/Tasks/Task.vue +22 -209
  28. package/src/components/Tasks/TaskView.vue +5 -4
  29. package/src/components/Tasks/ViewTask.vue +201 -214
  30. package/src/components/icons/Copy.vue +6 -0
  31. package/src/components/icons/index.js +3 -1
  32. package/src/components/ui/ActionButtonGroup.vue +70 -0
  33. package/src/components/ui/FormField.vue +74 -0
  34. package/src/components/ui/InfoRow.vue +100 -0
  35. package/src/components/ui/Modal.vue +6 -47
  36. package/src/components/ui/Navbar.vue +15 -43
  37. package/src/components/ui/ReconnectIndicator.vue +4 -4
  38. package/src/components/ui/SectionCard.vue +24 -0
  39. package/src/components/ui/Splash.vue +1 -6
  40. package/src/components/ui/StatusBadge.vue +37 -0
  41. package/src/components/ui/controls/CountryChooser.vue +14 -58
  42. package/src/components/ui/controls/atomic/Dropdown.vue +16 -24
  43. package/src/components/ui/controls/atomic/MultiDropdown.vue +7 -1
  44. package/src/components/ui/controls/atomic/Switch.vue +13 -29
  45. package/src/composables/useCopyToClipboard.js +25 -0
  46. package/src/composables/useRowSelection.js +48 -0
  47. package/src/views/Accounts.vue +0 -81
  48. package/src/views/Console.vue +4 -21
  49. package/src/views/Editor.vue +48 -138
  50. package/src/views/FilterBuilder.vue +0 -23
  51. package/src/views/Login.vue +14 -63
  52. package/src/views/Profiles.vue +0 -82
  53. package/src/views/Tasks.vue +3 -24
  54. package/tailwind.config.js +47 -5
@@ -0,0 +1,2416 @@
1
+ # Tailwind CSS Consolidation & Vue Cleanup Implementation Plan
2
+
3
+ > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
4
+
5
+ **Goal:** Achieve near-zero CSS in Vue files with perfect Tailwind usage, extract all duplicate components, consolidate theme, and remove all "ghetto" hacks.
6
+
7
+ **Architecture:** Multi-phase refactoring starting with foundational theme tokens, then systematic CSS cleanup, component extraction, and comprehensive verification. Each phase is independently testable with clear rollback points.
8
+
9
+ **Tech Stack:** Vue 3, Tailwind CSS 3.4, Pinia, Vite, OKLCH color system
10
+
11
+ **Supported Devices:** iPad Pro, Desktop, iPhone Portrait (iPhone landscape forces rotation)
12
+
13
+ ---
14
+
15
+ ## Phase 1: Theme Token Consolidation (Foundation)
16
+
17
+ ### Task 1.1: Extend Tailwind Color Tokens
18
+
19
+ **Files:**
20
+ - Modify: `tailwind.config.js:30-77`
21
+
22
+ **Step 1: Add extended dark scale for rgba replacements**
23
+
24
+ Add these values to the `dark` color scale in tailwind.config.js:
25
+
26
+ ```javascript
27
+ dark: {
28
+ // ... existing values
29
+ 350: "oklch(0.1900 0 0 / <alpha-value>)", // rgba(26, 27, 30) replacement
30
+ 450: "oklch(0.2200 0 0 / <alpha-value>)", // rgba(35, 36, 41) replacement
31
+ 475: "oklch(0.2350 0 0 / <alpha-value>)", // rgba(46, 47, 52) replacement
32
+ 625: "oklch(0.2950 0 0 / <alpha-value>)", // rgba(61, 62, 68) replacement
33
+ 675: "oklch(0.3200 0 0 / <alpha-value>)", // rgba(68, 69, 75) replacement
34
+ }
35
+ ```
36
+
37
+ **Step 2: Add semantic error colors**
38
+
39
+ Add after the `red` scale:
40
+
41
+ ```javascript
42
+ error: {
43
+ 300: "oklch(0.72 0.15 25 / <alpha-value>)", // Light error ~#EE8282
44
+ 400: "oklch(0.66 0.18 25 / <alpha-value>)", // Medium error
45
+ 500: "oklch(0.60 0.20 25 / <alpha-value>)", // Base error
46
+ }
47
+ ```
48
+
49
+ **Step 3: Add overlay colors**
50
+
51
+ Add after `accent`:
52
+
53
+ ```javascript
54
+ overlay: {
55
+ dark: "oklch(0.08 0 0 / 0.85)", // Modal backdrop
56
+ darker: "oklch(0.06 0 0 / 0.90)", // Darker overlay
57
+ }
58
+ ```
59
+
60
+ **Step 4: Add semantic text/bg tokens**
61
+
62
+ Add after `border`:
63
+
64
+ ```javascript
65
+ // Semantic tokens for better DX
66
+ 'text-primary': 'oklch(0.90 0 0 / <alpha-value>)', // light-300
67
+ 'text-secondary': 'oklch(0.82 0 0 / <alpha-value>)', // light-400
68
+ 'text-muted': 'oklch(0.65 0 0 / <alpha-value>)', // light-500
69
+ 'text-disabled': 'oklch(0.50 0 0 / <alpha-value>)', // light-600
70
+
71
+ 'bg-base': 'oklch(0.1822 0 0 / <alpha-value>)', // dark-300
72
+ 'bg-elevated': 'oklch(0.2046 0 0 / <alpha-value>)', // dark-400
73
+ 'bg-input': 'oklch(0.2603 0 0 / <alpha-value>)', // dark-500
74
+
75
+ 'border-focus': 'oklch(0.72 0.15 145 / <alpha-value>)', // accent.green
76
+ 'primary': 'oklch(0.72 0.15 145 / <alpha-value>)', // accent.green
77
+ ```
78
+
79
+ **Step 5: Verify config**
80
+
81
+ Run: `npm run dev`
82
+ Expected: No errors, dev server starts successfully
83
+
84
+ **Step 6: Commit**
85
+
86
+ ```bash
87
+ git add tailwind.config.js
88
+ git commit -m "feat: extend Tailwind color tokens for theme consolidation
89
+
90
+ - Add dark scale extensions (350, 450, 475, 625, 675)
91
+ - Add semantic error colors
92
+ - Add overlay colors for modals
93
+ - Add semantic text/bg/border tokens for better DX"
94
+ ```
95
+
96
+ ---
97
+
98
+ ### Task 1.2: Extend Shadow System
99
+
100
+ **Files:**
101
+ - Modify: `tailwind.config.js:135-138`
102
+
103
+ **Step 1: Replace boxShadow extend section**
104
+
105
+ ```javascript
106
+ boxShadow: {
107
+ 'card': '0 4px 12px rgba(0, 0, 0, 0.2)',
108
+ 'button': '0 1px 2px rgba(0, 0, 0, 0.2)',
109
+ 'sm': '0 1px 2px rgba(0, 0, 0, 0.1)',
110
+ 'md': '0 2px 4px rgba(0, 0, 0, 0.1)',
111
+ 'lg': '0 4px 12px rgba(0, 0, 0, 0.3)',
112
+ 'xl': '0 6px 16px rgba(0, 0, 0, 0.3)',
113
+ 'dropdown': '0 20px 25px -5px rgba(0, 0, 0, 0.4), 0 10px 10px -5px rgba(0, 0, 0, 0.2)',
114
+ 'input-inset': 'inset 0 2px 4px rgba(0, 0, 0, 0.4)',
115
+ }
116
+ ```
117
+
118
+ **Step 2: Add border radius extensions**
119
+
120
+ Add after `boxShadow`:
121
+
122
+ ```javascript
123
+ borderRadius: {
124
+ 'xs': '3px',
125
+ }
126
+ ```
127
+
128
+ **Step 3: Add backdrop blur extensions**
129
+
130
+ Add after `borderRadius`:
131
+
132
+ ```javascript
133
+ backdropBlur: {
134
+ 'xs': '4px',
135
+ 'sm': '8px',
136
+ }
137
+ ```
138
+
139
+ **Step 4: Add font size extensions**
140
+
141
+ Add after `backdropBlur`:
142
+
143
+ ```javascript
144
+ fontSize: {
145
+ 'xxs': '0.625rem', // 10px
146
+ 'xxxs': '0.5625rem', // 9px
147
+ }
148
+ ```
149
+
150
+ **Step 5: Verify config**
151
+
152
+ Run: `npm run dev`
153
+ Expected: No errors, dev server restarts successfully
154
+
155
+ **Step 6: Commit**
156
+
157
+ ```bash
158
+ git add tailwind.config.js
159
+ git commit -m "feat: extend Tailwind design tokens
160
+
161
+ - Add shadow system (sm, md, lg, xl, dropdown, input-inset)
162
+ - Add border-radius-xs (3px)
163
+ - Add backdrop-blur-xs, backdrop-blur-sm
164
+ - Add font-size xxs, xxxs for small UI elements"
165
+ ```
166
+
167
+ ---
168
+
169
+ ## Phase 2: Remove iPhone Landscape Support
170
+
171
+ ### Task 2.1: Clean Up App.vue iPhone Landscape Code
172
+
173
+ **Files:**
174
+ - Modify: `src/App.vue`
175
+
176
+ **Step 1: Read current App.vue**
177
+
178
+ Run: Read `src/App.vue`
179
+
180
+ **Step 2: Remove iPhone landscape lock overlay**
181
+
182
+ Find and remove:
183
+ - `.landscape-lock` class styles (lines ~739-796)
184
+ - `.landscape-lock-content` styles
185
+ - `LandscapeLockIcon` component
186
+ - All iPhone landscape detection logic in script section
187
+ - All `showLandscapeLock` reactive refs and watchers
188
+
189
+ **Step 3: Remove mobile-landscape breakpoint styles**
190
+
191
+ Search for `@media` queries containing:
192
+ - `mobile-landscape`
193
+ - `(orientation: landscape) and (max-height: 500px)`
194
+
195
+ Remove all iPhone-specific landscape overrides.
196
+
197
+ **Step 4: Test app loads**
198
+
199
+ Run: `npm run dev`
200
+ Navigate to: `http://localhost:5173`
201
+ Expected: App loads normally, no landscape lock on iPhone
202
+
203
+ **Step 5: Commit**
204
+
205
+ ```bash
206
+ git add src/App.vue
207
+ git commit -m "refactor: remove iPhone landscape support
208
+
209
+ - Remove landscape lock overlay component
210
+ - Remove landscape detection logic
211
+ - Remove mobile-landscape media queries
212
+ - Users on iPhone landscape are now forced to rotate via CSS"
213
+ ```
214
+
215
+ ---
216
+
217
+ ### Task 2.2: Update Tailwind Config - Remove Landscape Breakpoints
218
+
219
+ **Files:**
220
+ - Modify: `tailwind.config.js:92-116`
221
+
222
+ **Step 1: Remove mobile-landscape breakpoint**
223
+
224
+ Remove from screens:
225
+
226
+ ```javascript
227
+ "mobile-landscape": {
228
+ raw: "(max-width: 896px) and (orientation: landscape) and (max-height: 500px)"
229
+ }
230
+ ```
231
+
232
+ **Step 2: Update comments**
233
+
234
+ Update screen section comment to:
235
+
236
+ ```javascript
237
+ // Supported devices: iPad Pro, Desktop, iPhone Portrait
238
+ // iPhone landscape forces rotation to portrait
239
+ ```
240
+
241
+ **Step 3: Verify no landscape references**
242
+
243
+ Run: `grep -r "mobile-landscape" src/`
244
+ Expected: No results (or only in comments)
245
+
246
+ **Step 4: Commit**
247
+
248
+ ```bash
249
+ git add tailwind.config.js
250
+ git commit -m "refactor: remove mobile-landscape breakpoint
251
+
252
+ - Remove mobile-landscape from Tailwind screens
253
+ - Update comments to reflect supported devices
254
+ - iPhone landscape no longer supported"
255
+ ```
256
+
257
+ ---
258
+
259
+ ## Phase 3: Component Extraction (High Value)
260
+
261
+ ### Task 3.1: Create StatusBadge Component
262
+
263
+ **Files:**
264
+ - Create: `src/components/ui/StatusBadge.vue`
265
+ - Test: Manual testing in Account.vue, Profile.vue
266
+
267
+ **Step 1: Create StatusBadge component**
268
+
269
+ ```vue
270
+ <script setup>
271
+ import { defineProps } from 'vue'
272
+ import CheckmarkIcon from '@/assets/icons/checkmark.svg'
273
+ import CloseXIcon from '@/assets/icons/close-x.svg'
274
+
275
+ const props = defineProps({
276
+ enabled: {
277
+ type: Boolean,
278
+ required: true
279
+ },
280
+ size: {
281
+ type: String,
282
+ default: 'small',
283
+ validator: (value) => ['small', 'large'].includes(value)
284
+ }
285
+ })
286
+
287
+ const sizeClasses = {
288
+ small: 'w-6 h-6',
289
+ large: 'w-[26px] h-[26px]'
290
+ }
291
+
292
+ const enabledClasses = 'bg-accent-green/20 border-accent-green/30'
293
+ const disabledClasses = 'bg-red-500/20 border-red-500/30'
294
+ </script>
295
+
296
+ <template>
297
+ <div
298
+ :class="[
299
+ 'flex items-center justify-center rounded-full border-2 transition-all duration-200',
300
+ enabled ? enabledClasses : disabledClasses,
301
+ sizeClasses[size]
302
+ ]"
303
+ >
304
+ <CheckmarkIcon v-if="enabled" class="w-3 h-3 text-accent-green" />
305
+ <CloseXIcon v-else class="w-3 h-3 text-red-500" />
306
+ </div>
307
+ </template>
308
+ ```
309
+
310
+ **Step 2: Test component in isolation**
311
+
312
+ Create temporary test in a view to verify rendering:
313
+ - Enabled state
314
+ - Disabled state
315
+ - Small size
316
+ - Large size
317
+
318
+ **Step 3: Commit**
319
+
320
+ ```bash
321
+ git add src/components/ui/StatusBadge.vue
322
+ git commit -m "feat: create StatusBadge component
323
+
324
+ - Supports enabled/disabled states
325
+ - Supports small/large sizes
326
+ - Uses Tailwind classes exclusively
327
+ - Replaces 360+ lines of duplicated CSS"
328
+ ```
329
+
330
+ ---
331
+
332
+ ### Task 3.2: Replace StatusBadge in Account.vue
333
+
334
+ **Files:**
335
+ - Modify: `src/components/Editors/Account/Account.vue`
336
+
337
+ **Step 1: Import StatusBadge**
338
+
339
+ Add to imports:
340
+
341
+ ```javascript
342
+ import StatusBadge from '@/components/ui/StatusBadge.vue'
343
+ ```
344
+
345
+ **Step 2: Replace enabled badge markup**
346
+
347
+ Find lines with class `enabled-badge` or `disabled-badge` and replace with:
348
+
349
+ ```vue
350
+ <StatusBadge :enabled="account.enabled" size="small" />
351
+ ```
352
+
353
+ **Step 3: Remove old badge styles**
354
+
355
+ Remove from `<style scoped>`:
356
+ - `.enabled-badge` class (lines ~60-105)
357
+ - `.disabled-badge` class
358
+
359
+ **Step 4: Test in browser**
360
+
361
+ Run: `npm run dev`
362
+ Navigate to Accounts page
363
+ Expected: Badges render correctly, enabled/disabled states work
364
+
365
+ **Step 5: Commit**
366
+
367
+ ```bash
368
+ git add src/components/Editors/Account/Account.vue
369
+ git commit -m "refactor: use StatusBadge component in Account.vue
370
+
371
+ - Replace custom badge markup with StatusBadge component
372
+ - Remove ~100 lines of duplicated CSS"
373
+ ```
374
+
375
+ ---
376
+
377
+ ### Task 3.3: Replace StatusBadge in Profile.vue
378
+
379
+ **Files:**
380
+ - Modify: `src/components/Editors/Profile/Profile.vue`
381
+
382
+ **Step 1: Import StatusBadge**
383
+
384
+ **Step 2: Replace badge markup**
385
+
386
+ **Step 3: Remove badge styles**
387
+
388
+ **Step 4: Test in browser**
389
+
390
+ **Step 5: Commit**
391
+
392
+ ```bash
393
+ git add src/components/Editors/Profile/Profile.vue
394
+ git commit -m "refactor: use StatusBadge component in Profile.vue"
395
+ ```
396
+
397
+ ---
398
+
399
+ ### Task 3.4: Replace StatusBadge in CreateAccount.vue
400
+
401
+ **Files:**
402
+ - Modify: `src/components/Editors/Account/CreateAccount.vue`
403
+
404
+ **Step 1-5:** Same as Task 3.3
405
+
406
+ **Step 6: Commit**
407
+
408
+ ```bash
409
+ git add src/components/Editors/Account/CreateAccount.vue
410
+ git commit -m "refactor: use StatusBadge component in CreateAccount.vue"
411
+ ```
412
+
413
+ ---
414
+
415
+ ### Task 3.5: Replace StatusBadge in CreateProfile.vue
416
+
417
+ **Files:**
418
+ - Modify: `src/components/Editors/Profile/CreateProfile.vue`
419
+
420
+ **Step 1-5:** Same as Task 3.3
421
+
422
+ **Step 6: Commit**
423
+
424
+ ```bash
425
+ git add src/components/Editors/Profile/CreateProfile.vue
426
+ git commit -m "refactor: use StatusBadge component in CreateProfile.vue"
427
+ ```
428
+
429
+ ---
430
+
431
+ ### Task 3.6: Create useRowSelection Composable
432
+
433
+ **Files:**
434
+ - Create: `src/composables/useRowSelection.js`
435
+
436
+ **Step 1: Create composable file**
437
+
438
+ ```javascript
439
+ /**
440
+ * useRowSelection - Composable for handling row selection via double-click/tap
441
+ *
442
+ * Provides consistent double-click and double-tap behavior for table rows.
443
+ * Prevents selection when clicking on buttons or checkboxes.
444
+ *
445
+ * @param {Function} toggleCallback - Function to call when row is double-clicked/tapped
446
+ * @returns {Object} Event handlers for @dblclick, @touchstart, @touchend
447
+ */
448
+ export function useRowSelection(toggleCallback) {
449
+ let lastTapTime = 0
450
+ const DOUBLE_TAP_DELAY = 300
451
+
452
+ const handleDoubleClick = (event) => {
453
+ // Don't trigger on button or checkbox clicks
454
+ if (event.target.closest('button') || event.target.closest('.checkbox')) {
455
+ return
456
+ }
457
+ toggleCallback()
458
+ }
459
+
460
+ const handleTouchStart = (event) => {
461
+ const currentTime = Date.now()
462
+ const tapGap = currentTime - lastTapTime
463
+
464
+ if (tapGap < DOUBLE_TAP_DELAY && tapGap > 0) {
465
+ // Don't trigger on button or checkbox taps
466
+ if (!event.target.closest('button') && !event.target.closest('.checkbox')) {
467
+ event.preventDefault()
468
+ toggleCallback()
469
+ }
470
+ }
471
+ lastTapTime = currentTime
472
+ }
473
+
474
+ const handleTouchEnd = (event) => {
475
+ // Prevent default touch behavior on buttons/checkboxes
476
+ if (event.target.closest('button') || event.target.closest('.checkbox')) {
477
+ return
478
+ }
479
+ }
480
+
481
+ return {
482
+ handleDoubleClick,
483
+ handleTouchStart,
484
+ handleTouchEnd
485
+ }
486
+ }
487
+ ```
488
+
489
+ **Step 2: Commit**
490
+
491
+ ```bash
492
+ git add src/composables/useRowSelection.js
493
+ git commit -m "feat: create useRowSelection composable
494
+
495
+ - Handles double-click and double-tap for row selection
496
+ - Prevents selection on button/checkbox clicks
497
+ - Replaces 105 lines of duplicated logic"
498
+ ```
499
+
500
+ ---
501
+
502
+ ### Task 3.7: Use useRowSelection in Task.vue
503
+
504
+ **Files:**
505
+ - Modify: `src/components/Tasks/Task.vue`
506
+
507
+ **Step 1: Import composable**
508
+
509
+ ```javascript
510
+ import { useRowSelection } from '@/composables/useRowSelection'
511
+ ```
512
+
513
+ **Step 2: Use composable in setup**
514
+
515
+ Replace manual event handler logic with:
516
+
517
+ ```javascript
518
+ const { handleDoubleClick, handleTouchStart, handleTouchEnd } = useRowSelection(() => {
519
+ emit('toggle', props.task)
520
+ })
521
+ ```
522
+
523
+ **Step 3: Update template event handlers**
524
+
525
+ Replace existing `@dblclick`, `@touchstart`, `@touchend` with:
526
+
527
+ ```vue
528
+ <tr
529
+ @dblclick="handleDoubleClick"
530
+ @touchstart="handleTouchStart"
531
+ @touchend="handleTouchEnd"
532
+ >
533
+ ```
534
+
535
+ **Step 4: Remove old event handler code**
536
+
537
+ Delete manual double-tap logic (lines ~511-544)
538
+
539
+ **Step 5: Test in browser**
540
+
541
+ Navigate to Tasks page
542
+ Test: Double-click row → should select task
543
+ Test: Double-tap on mobile → should select task
544
+ Test: Click button → should NOT select task
545
+
546
+ **Step 6: Commit**
547
+
548
+ ```bash
549
+ git add src/components/Tasks/Task.vue
550
+ git commit -m "refactor: use useRowSelection composable in Task.vue
551
+
552
+ - Replace manual double-tap logic with composable
553
+ - Remove ~35 lines of duplicated code"
554
+ ```
555
+
556
+ ---
557
+
558
+ ### Task 3.8: Use useRowSelection in Account.vue
559
+
560
+ **Files:**
561
+ - Modify: `src/components/Editors/Account/Account.vue`
562
+
563
+ **Step 1-6:** Same as Task 3.7, adapted for Account component
564
+
565
+ **Step 7: Commit**
566
+
567
+ ```bash
568
+ git add src/components/Editors/Account/Account.vue
569
+ git commit -m "refactor: use useRowSelection composable in Account.vue"
570
+ ```
571
+
572
+ ---
573
+
574
+ ### Task 3.9: Use useRowSelection in Profile.vue
575
+
576
+ **Files:**
577
+ - Modify: `src/components/Editors/Profile/Profile.vue`
578
+
579
+ **Step 1-6:** Same as Task 3.7, adapted for Profile component
580
+
581
+ **Step 7: Commit**
582
+
583
+ ```bash
584
+ git add src/components/Editors/Profile/Profile.vue
585
+ git commit -m "refactor: use useRowSelection composable in Profile.vue"
586
+ ```
587
+
588
+ ---
589
+
590
+ ### Task 3.10: Create useCopyToClipboard Composable
591
+
592
+ **Files:**
593
+ - Create: `src/composables/useCopyToClipboard.js`
594
+
595
+ **Step 1: Create composable**
596
+
597
+ ```javascript
598
+ import { useUIStore } from '@/stores/ui'
599
+
600
+ /**
601
+ * useCopyToClipboard - Composable for copying text with user feedback
602
+ *
603
+ * @returns {Object} Copy function with success notification
604
+ */
605
+ export function useCopyToClipboard() {
606
+ const ui = useUIStore()
607
+
608
+ const copy = (text, message = 'Copied to clipboard') => {
609
+ if (!text) return
610
+
611
+ navigator.clipboard.writeText(text)
612
+ .then(() => {
613
+ ui.showSuccess(message)
614
+ })
615
+ .catch((err) => {
616
+ ui.showError('Failed to copy')
617
+ console.error('Copy failed:', err)
618
+ })
619
+ }
620
+
621
+ return { copy }
622
+ }
623
+ ```
624
+
625
+ **Step 2: Commit**
626
+
627
+ ```bash
628
+ git add src/composables/useCopyToClipboard.js
629
+ git commit -m "feat: create useCopyToClipboard composable
630
+
631
+ - Provides copy to clipboard with success notification
632
+ - Handles errors gracefully
633
+ - DRY principle for clipboard operations"
634
+ ```
635
+
636
+ ---
637
+
638
+ ### Task 3.11: Use useCopyToClipboard in Task.vue
639
+
640
+ **Files:**
641
+ - Modify: `src/components/Tasks/Task.vue`
642
+
643
+ **Step 1: Import and use composable**
644
+
645
+ ```javascript
646
+ import { useCopyToClipboard } from '@/composables/useCopyToClipboard'
647
+
648
+ const { copy } = useCopyToClipboard()
649
+ ```
650
+
651
+ **Step 2: Replace manual copy logic**
652
+
653
+ Replace `navigator.clipboard.writeText()` calls with:
654
+
655
+ ```javascript
656
+ copy(task.id, 'Copied task ID')
657
+ ```
658
+
659
+ **Step 3: Remove old copy code**
660
+
661
+ **Step 4: Test**
662
+
663
+ Click copy button → should copy and show success notification
664
+
665
+ **Step 5: Commit**
666
+
667
+ ```bash
668
+ git add src/components/Tasks/Task.vue
669
+ git commit -m "refactor: use useCopyToClipboard composable in Task.vue"
670
+ ```
671
+
672
+ ---
673
+
674
+ ### Task 3.12: Use useCopyToClipboard in ViewTask.vue
675
+
676
+ **Files:**
677
+ - Modify: `src/components/Tasks/ViewTask.vue`
678
+
679
+ **Step 1-5:** Same as Task 3.11
680
+
681
+ **Step 6: Commit**
682
+
683
+ ```bash
684
+ git add src/components/Tasks/ViewTask.vue
685
+ git commit -m "refactor: use useCopyToClipboard composable in ViewTask.vue"
686
+ ```
687
+
688
+ ---
689
+
690
+ ### Task 3.13: Use useCopyToClipboard in Account.vue
691
+
692
+ **Files:**
693
+ - Modify: `src/components/Editors/Account/Account.vue`
694
+
695
+ **Step 1-5:** Same as Task 3.11
696
+
697
+ **Step 6: Commit**
698
+
699
+ ```bash
700
+ git add src/components/Editors/Account/Account.vue
701
+ git commit -m "refactor: use useCopyToClipboard composable in Account.vue"
702
+ ```
703
+
704
+ ---
705
+
706
+ ## Phase 4: High-Priority CSS Cleanup
707
+
708
+ ### Task 4.1: Clean Up App.vue Global Styles
709
+
710
+ **Files:**
711
+ - Modify: `src/App.vue`
712
+
713
+ **Step 1: Read current App.vue styles**
714
+
715
+ Run: Read `src/App.vue` focusing on `<style>` section
716
+
717
+ **Step 2: Remove global !important overrides**
718
+
719
+ Find and remove/replace:
720
+ - `html, body` with !important on overflow, width, height, touch-action (lines ~679-688)
721
+ - Replace with proper overflow utilities on specific elements
722
+ - Global `* { touch-action: manipulation !important }` (lines ~699-702)
723
+ - Remove entirely, use `touch-manipulation` class where needed
724
+
725
+ **Step 3: Convert .layout to Tailwind**
726
+
727
+ Replace:
728
+
729
+ ```css
730
+ .layout {
731
+ min-height: 90vh;
732
+ height: 100vh !important;
733
+ }
734
+ ```
735
+
736
+ With template classes:
737
+
738
+ ```vue
739
+ <div class="layout min-h-screen h-screen">
740
+ ```
741
+
742
+ Remove CSS block.
743
+
744
+ **Step 4: Simplify component-container responsive padding**
745
+
746
+ Replace:
747
+
748
+ ```css
749
+ .component-container {
750
+ padding-left: 1rem;
751
+ padding-right: 1rem;
752
+ }
753
+ @media (min-width: 480px) {
754
+ .component-container {
755
+ padding-left: 1rem;
756
+ padding-right: 1rem;
757
+ }
758
+ }
759
+ /* etc */
760
+ ```
761
+
762
+ With template classes:
763
+
764
+ ```vue
765
+ <div class="component-container px-4 xs:px-4 md:px-2 lg:px-6 xl:px-10">
766
+ ```
767
+
768
+ Remove CSS block.
769
+
770
+ **Step 5: Keep necessary animations**
771
+
772
+ Keep page transition animations (enter-active, leave-active) as they're legitimate custom CSS.
773
+
774
+ **Step 6: Test app**
775
+
776
+ Run: `npm run dev`
777
+ Test: Scroll behavior, touch behavior, layout sizing
778
+ Expected: No visual changes, no layout breaks
779
+
780
+ **Step 7: Commit**
781
+
782
+ ```bash
783
+ git add src/App.vue
784
+ git commit -m "refactor: clean up App.vue global styles
785
+
786
+ - Remove global !important overrides
787
+ - Convert .layout to Tailwind classes
788
+ - Convert .component-container to responsive Tailwind classes
789
+ - Remove ~100 lines of CSS
790
+ - Keep page transition animations"
791
+ ```
792
+
793
+ ---
794
+
795
+ ### Task 4.2: Clean Up Navbar.vue
796
+
797
+ **Files:**
798
+ - Modify: `src/components/ui/Navbar.vue`
799
+
800
+ **Step 1: Read Navbar.vue styles**
801
+
802
+ Run: Read `src/components/ui/Navbar.vue` lines 112-275
803
+
804
+ **Step 2: Convert background to Tailwind**
805
+
806
+ Replace:
807
+
808
+ ```css
809
+ background: oklch(0.1822 0 0 / 0.95);
810
+ backdrop-filter: blur(12px);
811
+ ```
812
+
813
+ With class:
814
+
815
+ ```vue
816
+ class="bg-dark-300/95 backdrop-blur"
817
+ ```
818
+
819
+ **Step 3: Remove SVG force normalization**
820
+
821
+ Replace:
822
+
823
+ ```css
824
+ svg {
825
+ width: 20px !important;
826
+ height: 20px !important;
827
+ }
828
+ ```
829
+
830
+ With template classes on SVG components:
831
+
832
+ ```vue
833
+ <SomeIcon class="w-5 h-5" />
834
+ ```
835
+
836
+ **Step 4: Convert .navbar-link height**
837
+
838
+ Replace:
839
+
840
+ ```css
841
+ .navbar-link {
842
+ height: 40px;
843
+ border-bottom: 2px solid transparent;
844
+ }
845
+ ```
846
+
847
+ With:
848
+
849
+ ```vue
850
+ class="navbar-link h-10 border-b-2 border-transparent"
851
+ ```
852
+
853
+ **Step 5: Replace icon centering hack**
854
+
855
+ Replace:
856
+
857
+ ```css
858
+ position: absolute;
859
+ top: 50%;
860
+ left: 50%;
861
+ transform: translate(-50%, -50%);
862
+ ```
863
+
864
+ With:
865
+
866
+ ```vue
867
+ class="flex items-center justify-center"
868
+ ```
869
+
870
+ **Step 6: Fix .force-z z-index**
871
+
872
+ Replace:
873
+
874
+ ```css
875
+ .force-z {
876
+ z-index: 20000;
877
+ }
878
+ ```
879
+
880
+ With:
881
+
882
+ ```vue
883
+ class="z-max"
884
+ ```
885
+
886
+ (Already in tailwind.config.js as 9999)
887
+
888
+ **Step 7: Convert notch pseudo-element**
889
+
890
+ The notch handling (`::before` with absolute positioning) is iPhone-specific.
891
+ Since we removed iPhone landscape support, simplify or remove.
892
+
893
+ **Step 8: Test navbar**
894
+
895
+ Run: `npm run dev`
896
+ Test: Navigation icons, responsive behavior, SVG sizing, z-index layering
897
+ Expected: Identical visual appearance
898
+
899
+ **Step 9: Commit**
900
+
901
+ ```bash
902
+ git add src/components/ui/Navbar.vue
903
+ git commit -m "refactor: clean up Navbar.vue styles
904
+
905
+ - Convert background to Tailwind classes
906
+ - Remove SVG !important overrides, use classes
907
+ - Convert height/border to Tailwind utilities
908
+ - Replace absolute positioning with flexbox
909
+ - Fix z-index using Tailwind token
910
+ - Remove ~120 lines of CSS"
911
+ ```
912
+
913
+ ---
914
+
915
+ ### Task 4.3: Clean Up Modal.vue
916
+
917
+ **Files:**
918
+ - Modify: `src/components/ui/Modal.vue`
919
+
920
+ **Step 1: Read Modal.vue styles**
921
+
922
+ Run: Read `src/components/ui/Modal.vue` lines 57-138
923
+
924
+ **Step 2: Replace .modal-mask styles**
925
+
926
+ Replace:
927
+
928
+ ```css
929
+ .modal-mask {
930
+ position: fixed;
931
+ z-index: 25000;
932
+ top: 0;
933
+ left: 0;
934
+ width: 100%;
935
+ height: 100%;
936
+ background-color: rgba(17, 17, 17, 0.85);
937
+ backdrop-filter: blur(4px);
938
+ display: flex;
939
+ padding-top: 3.5rem;
940
+ }
941
+ ```
942
+
943
+ With template classes:
944
+
945
+ ```vue
946
+ <div class="modal-mask fixed inset-0 z-modal bg-overlay-dark backdrop-blur-xs flex pt-14">
947
+ ```
948
+
949
+ **Step 3: Simplify .component-modal bottom margin**
950
+
951
+ Replace:
952
+
953
+ ```css
954
+ margin-bottom: 20rem;
955
+ @media (max-width: 480px) {
956
+ margin-bottom: 25rem;
957
+ }
958
+ ```
959
+
960
+ With:
961
+
962
+ ```vue
963
+ class="mb-80 mobile-portrait:mb-[25rem]"
964
+ ```
965
+
966
+ **Step 4: Remove !important from padding-bottom**
967
+
968
+ Replace:
969
+
970
+ ```css
971
+ padding-bottom: 15rem !important;
972
+ padding-bottom: 3rem !important;
973
+ ```
974
+
975
+ With proper Tailwind classes:
976
+
977
+ ```vue
978
+ class="pb-60 md:pb-12"
979
+ ```
980
+
981
+ **Step 5: Test modal**
982
+
983
+ Open any modal, test:
984
+ - Overlay appearance
985
+ - Modal positioning
986
+ - Scroll behavior
987
+ - Responsive sizing
988
+
989
+ **Step 6: Commit**
990
+
991
+ ```bash
992
+ git add src/components/ui/Modal.vue
993
+ git commit -m "refactor: clean up Modal.vue styles
994
+
995
+ - Replace .modal-mask with Tailwind classes
996
+ - Use z-modal token instead of hardcoded 25000
997
+ - Use bg-overlay-dark and backdrop-blur-xs tokens
998
+ - Remove !important from padding
999
+ - Simplify responsive bottom margin
1000
+ - Remove ~80 lines of CSS"
1001
+ ```
1002
+
1003
+ ---
1004
+
1005
+ ### Task 4.4: Clean Up Task.vue
1006
+
1007
+ **Files:**
1008
+ - Modify: `src/components/Tasks/Task.vue`
1009
+
1010
+ **Step 1: Read Task.vue styles**
1011
+
1012
+ Run: Read `src/components/Tasks/Task.vue` lines 158-466
1013
+
1014
+ **Step 2: Remove icon !important overrides**
1015
+
1016
+ Replace:
1017
+
1018
+ ```css
1019
+ min-width: 10px !important;
1020
+ stroke: oklch(0.60 0 0) !important;
1021
+ ```
1022
+
1023
+ With proper component props or Tailwind classes:
1024
+
1025
+ ```vue
1026
+ <SomeIcon class="min-w-[10px] stroke-light-500" />
1027
+ ```
1028
+
1029
+ **Step 3: Convert button dimensions**
1030
+
1031
+ Replace:
1032
+
1033
+ ```css
1034
+ padding: 2px;
1035
+ gap: 1px;
1036
+ border: 2px solid oklch(...);
1037
+ ```
1038
+
1039
+ With:
1040
+
1041
+ ```vue
1042
+ class="p-0.5 gap-px border-2 border-dark-600"
1043
+ ```
1044
+
1045
+ **Step 4: Remove mobile positioning hacks**
1046
+
1047
+ Replace:
1048
+
1049
+ ```css
1050
+ @media (max-width: 480px) {
1051
+ left: 4rem !important;
1052
+ top: 0.25rem !important;
1053
+ z-index: 1 !important;
1054
+ }
1055
+ ```
1056
+
1057
+ With proper responsive Tailwind:
1058
+
1059
+ ```vue
1060
+ class="mobile-portrait:left-16 mobile-portrait:top-1 mobile-portrait:z-10"
1061
+ ```
1062
+
1063
+ **Step 5: Remove border override !important**
1064
+
1065
+ Replace:
1066
+
1067
+ ```css
1068
+ border: 2px solid oklch(0.2809 0 0) !important;
1069
+ ```
1070
+
1071
+ With:
1072
+
1073
+ ```vue
1074
+ class="border-2 border-dark-600"
1075
+ ```
1076
+
1077
+ **Step 6: Convert shadow !important**
1078
+
1079
+ Replace:
1080
+
1081
+ ```css
1082
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1) !important;
1083
+ ```
1084
+
1085
+ With:
1086
+
1087
+ ```vue
1088
+ class="shadow-sm"
1089
+ ```
1090
+
1091
+ **Step 7: Test task rows**
1092
+
1093
+ Navigate to Tasks page
1094
+ Test: Task row appearance, mobile responsiveness, buttons, icons
1095
+
1096
+ **Step 8: Commit**
1097
+
1098
+ ```bash
1099
+ git add src/components/Tasks/Task.vue
1100
+ git commit -m "refactor: clean up Task.vue styles
1101
+
1102
+ - Remove icon !important overrides
1103
+ - Convert button dimensions to Tailwind
1104
+ - Remove mobile positioning hacks with !important
1105
+ - Replace hardcoded colors with theme tokens
1106
+ - Convert shadows to Tailwind utilities
1107
+ - Remove ~100 lines of CSS"
1108
+ ```
1109
+
1110
+ ---
1111
+
1112
+ ### Task 4.5: Clean Up Dropdown.vue
1113
+
1114
+ **Files:**
1115
+ - Modify: `src/components/ui/controls/atomic/Dropdown.vue`
1116
+
1117
+ **Step 1: Read Dropdown.vue styles**
1118
+
1119
+ Run: Read `src/components/ui/controls/atomic/Dropdown.vue` lines 121-288
1120
+
1121
+ **Step 2: Convert background and border**
1122
+
1123
+ Replace:
1124
+
1125
+ ```css
1126
+ background: linear-gradient(...);
1127
+ border: 1px solid oklch(...);
1128
+ ```
1129
+
1130
+ With:
1131
+
1132
+ ```vue
1133
+ class="bg-dark-300 border border-dark-600"
1134
+ ```
1135
+
1136
+ **Step 3: Remove height !important**
1137
+
1138
+ Replace:
1139
+
1140
+ ```css
1141
+ height: 40px !important;
1142
+ ```
1143
+
1144
+ With:
1145
+
1146
+ ```vue
1147
+ class="h-10"
1148
+ ```
1149
+
1150
+ **Step 4: Convert focus state**
1151
+
1152
+ Replace:
1153
+
1154
+ ```css
1155
+ border-color: oklch(...) !important;
1156
+ outline: 1px solid oklch(...) !important;
1157
+ ```
1158
+
1159
+ With:
1160
+
1161
+ ```vue
1162
+ class="focus:border-border-focus focus:outline focus:outline-1 focus:outline-border-focus"
1163
+ ```
1164
+
1165
+ **Step 5: Remove scroll !important**
1166
+
1167
+ Replace:
1168
+
1169
+ ```css
1170
+ overflow-x: auto !important;
1171
+ touch-action: pan-x pan-y !important;
1172
+ ```
1173
+
1174
+ With:
1175
+
1176
+ ```vue
1177
+ class="overflow-x-auto touch-pan-x touch-pan-y"
1178
+ ```
1179
+
1180
+ **Step 6: Test dropdown**
1181
+
1182
+ Test: Dropdown appearance, focus states, scroll behavior, touch behavior
1183
+
1184
+ **Step 7: Commit**
1185
+
1186
+ ```bash
1187
+ git add src/components/ui/controls/atomic/Dropdown.vue
1188
+ git commit -m "refactor: clean up Dropdown.vue styles
1189
+
1190
+ - Convert background/border to Tailwind
1191
+ - Remove height !important
1192
+ - Convert focus states to Tailwind utilities
1193
+ - Remove scroll/touch !important overrides
1194
+ - Remove ~70 lines of CSS"
1195
+ ```
1196
+
1197
+ ---
1198
+
1199
+ ## Phase 5: Component Extraction (Medium Value)
1200
+
1201
+ ### Task 5.1: Create FormField Component
1202
+
1203
+ **Files:**
1204
+ - Create: `src/components/ui/FormField.vue`
1205
+
1206
+ **Step 1: Create component**
1207
+
1208
+ ```vue
1209
+ <script setup>
1210
+ import { defineProps, defineEmits, useAttrs } from 'vue'
1211
+ import UpIcon from '@/assets/icons/up.svg'
1212
+ import DownIcon from '@/assets/icons/down.svg'
1213
+
1214
+ const props = defineProps({
1215
+ label: {
1216
+ type: String,
1217
+ required: true
1218
+ },
1219
+ icon: {
1220
+ type: Object,
1221
+ default: null
1222
+ },
1223
+ modelValue: {
1224
+ type: [String, Number],
1225
+ default: ''
1226
+ },
1227
+ type: {
1228
+ type: String,
1229
+ default: 'text'
1230
+ },
1231
+ placeholder: {
1232
+ type: String,
1233
+ default: ''
1234
+ },
1235
+ required: {
1236
+ type: Boolean,
1237
+ default: false
1238
+ },
1239
+ hasError: {
1240
+ type: Boolean,
1241
+ default: false
1242
+ },
1243
+ incrementer: {
1244
+ type: Boolean,
1245
+ default: false
1246
+ },
1247
+ zIndex: {
1248
+ type: String,
1249
+ default: '0',
1250
+ validator: (value) => ['dropdown', 'tooltip', '0', '1', '2'].includes(value)
1251
+ }
1252
+ })
1253
+
1254
+ const emit = defineEmits(['update:modelValue', 'increment', 'decrement'])
1255
+ const attrs = useAttrs()
1256
+
1257
+ const zIndexClasses = {
1258
+ dropdown: 'z-dropdown',
1259
+ tooltip: 'z-tooltip',
1260
+ '0': 'z-0',
1261
+ '1': 'z-10',
1262
+ '2': 'z-20'
1263
+ }
1264
+ </script>
1265
+
1266
+ <template>
1267
+ <div class="flex flex-col" :class="zIndexClasses[zIndex]">
1268
+ <label class="mb-2 text-sm font-medium text-light-400 flex items-center gap-2">
1269
+ {{ label }}
1270
+ <component :is="icon" v-if="icon" class="w-4 h-4" />
1271
+ </label>
1272
+ <div
1273
+ class="relative flex items-center bg-dark-500 border rounded-md transition-colors"
1274
+ :class="[
1275
+ hasError ? 'border-error-500' : 'border-dark-600',
1276
+ required ? 'ring-2 ring-primary/20' : ''
1277
+ ]"
1278
+ >
1279
+ <slot>
1280
+ <input
1281
+ :type="type"
1282
+ :placeholder="placeholder"
1283
+ :value="modelValue"
1284
+ @input="emit('update:modelValue', $event.target.value)"
1285
+ v-bind="attrs"
1286
+ class="w-full px-3 py-2 bg-transparent text-light-300 outline-none"
1287
+ />
1288
+ </slot>
1289
+ <div v-if="incrementer" class="flex flex-col border-l border-dark-600">
1290
+ <button
1291
+ @click="emit('increment')"
1292
+ type="button"
1293
+ class="px-2 py-1 hover:bg-dark-650 transition-colors"
1294
+ >
1295
+ <UpIcon class="w-3 h-3 text-light-400" />
1296
+ </button>
1297
+ <button
1298
+ @click="emit('decrement')"
1299
+ type="button"
1300
+ class="px-2 py-1 hover:bg-dark-650 transition-colors"
1301
+ >
1302
+ <DownIcon class="w-3 h-3 text-light-400" />
1303
+ </button>
1304
+ </div>
1305
+ </div>
1306
+ </div>
1307
+ </template>
1308
+ ```
1309
+
1310
+ **Step 2: Commit**
1311
+
1312
+ ```bash
1313
+ git add src/components/ui/FormField.vue
1314
+ git commit -m "feat: create FormField component
1315
+
1316
+ - Supports label, icon, error states, required states
1317
+ - Supports number incrementer
1318
+ - Supports z-index control for overlapping elements
1319
+ - Replaces ~400 lines of duplicated form markup"
1320
+ ```
1321
+
1322
+ ---
1323
+
1324
+ ### Task 5.2: Replace FormField in CreateTaskAXS.vue
1325
+
1326
+ **Files:**
1327
+ - Modify: `src/components/Tasks/CreateTaskAXS.vue`
1328
+
1329
+ **Step 1: Import FormField**
1330
+
1331
+ ```javascript
1332
+ import FormField from '@/components/ui/FormField.vue'
1333
+ ```
1334
+
1335
+ **Step 2: Replace input wrapper markup**
1336
+
1337
+ Find all instances of:
1338
+
1339
+ ```vue
1340
+ <div class="input-wrapper">
1341
+ <label class="label-override mb-2">
1342
+ Name
1343
+ <NameIcon />
1344
+ </label>
1345
+ <div class="input-default">
1346
+ <input type="text" v-model="name" />
1347
+ </div>
1348
+ </div>
1349
+ ```
1350
+
1351
+ Replace with:
1352
+
1353
+ ```vue
1354
+ <FormField
1355
+ label="Name"
1356
+ :icon="NameIcon"
1357
+ v-model="name"
1358
+ type="text"
1359
+ />
1360
+ ```
1361
+
1362
+ **Step 3: Remove old input-wrapper styles**
1363
+
1364
+ **Step 4: Test form**
1365
+
1366
+ Test: All input fields render correctly, v-model binding works, incrementers work
1367
+
1368
+ **Step 5: Commit**
1369
+
1370
+ ```bash
1371
+ git add src/components/Tasks/CreateTaskAXS.vue
1372
+ git commit -m "refactor: use FormField component in CreateTaskAXS.vue
1373
+
1374
+ - Replace 10+ input wrappers with FormField
1375
+ - Remove duplicated form markup"
1376
+ ```
1377
+
1378
+ ---
1379
+
1380
+ ### Task 5.3: Replace FormField in CreateTaskTM.vue
1381
+
1382
+ **Files:**
1383
+ - Modify: `src/components/Tasks/CreateTaskTM.vue`
1384
+
1385
+ **Step 1-5:** Same as Task 5.2
1386
+
1387
+ **Step 6: Commit**
1388
+
1389
+ ```bash
1390
+ git add src/components/Tasks/CreateTaskTM.vue
1391
+ git commit -m "refactor: use FormField component in CreateTaskTM.vue"
1392
+ ```
1393
+
1394
+ ---
1395
+
1396
+ ### Task 5.4: Replace FormField in CreateAccount.vue
1397
+
1398
+ **Files:**
1399
+ - Modify: `src/components/Editors/Account/CreateAccount.vue`
1400
+
1401
+ **Step 1-5:** Same as Task 5.2
1402
+
1403
+ **Step 6: Commit**
1404
+
1405
+ ```bash
1406
+ git add src/components/Editors/Account/CreateAccount.vue
1407
+ git commit -m "refactor: use FormField component in CreateAccount.vue"
1408
+ ```
1409
+
1410
+ ---
1411
+
1412
+ ### Task 5.5: Replace FormField in CreateProfile.vue
1413
+
1414
+ **Files:**
1415
+ - Modify: `src/components/Editors/Profile/CreateProfile.vue`
1416
+
1417
+ **Step 1-5:** Same as Task 5.2
1418
+
1419
+ **Step 6: Commit**
1420
+
1421
+ ```bash
1422
+ git add src/components/Editors/Profile/CreateProfile.vue
1423
+ git commit -m "refactor: use FormField component in CreateProfile.vue"
1424
+ ```
1425
+
1426
+ ---
1427
+
1428
+ ### Task 5.6: Create InfoRow Component
1429
+
1430
+ **Files:**
1431
+ - Create: `src/components/ui/InfoRow.vue`
1432
+
1433
+ **Step 1: Create component**
1434
+
1435
+ ```vue
1436
+ <script setup>
1437
+ import { defineProps } from 'vue'
1438
+ import { useCopyToClipboard } from '@/composables/useCopyToClipboard'
1439
+
1440
+ const props = defineProps({
1441
+ icon: {
1442
+ type: Object,
1443
+ default: null
1444
+ },
1445
+ label: {
1446
+ type: String,
1447
+ required: true
1448
+ },
1449
+ value: {
1450
+ type: [String, Number],
1451
+ default: ''
1452
+ },
1453
+ valueClass: {
1454
+ type: String,
1455
+ default: ''
1456
+ },
1457
+ copyable: {
1458
+ type: Boolean,
1459
+ default: false
1460
+ },
1461
+ copyText: {
1462
+ type: String,
1463
+ default: ''
1464
+ }
1465
+ })
1466
+
1467
+ const { copy } = useCopyToClipboard()
1468
+
1469
+ const handleCopy = () => {
1470
+ if (props.copyable) {
1471
+ copy(props.copyText || props.value, 'Copied')
1472
+ }
1473
+ }
1474
+ </script>
1475
+
1476
+ <template>
1477
+ <div
1478
+ class="flex items-center gap-3 py-2 px-3 rounded-md hover:bg-dark-400/50 transition-colors"
1479
+ :class="{ 'cursor-pointer': copyable }"
1480
+ @click="handleCopy"
1481
+ >
1482
+ <component
1483
+ :is="icon"
1484
+ v-if="icon"
1485
+ class="w-5 h-5 text-light-500 flex-shrink-0"
1486
+ />
1487
+ <span class="text-sm text-light-500 min-w-[100px]">{{ label }}</span>
1488
+ <span
1489
+ class="text-sm text-light-300 flex-1 text-right"
1490
+ :class="valueClass"
1491
+ >
1492
+ <slot>{{ value }}</slot>
1493
+ </span>
1494
+ <slot name="actions" />
1495
+ </div>
1496
+ </template>
1497
+ ```
1498
+
1499
+ **Step 2: Commit**
1500
+
1501
+ ```bash
1502
+ git add src/components/ui/InfoRow.vue
1503
+ git commit -m "feat: create InfoRow component
1504
+
1505
+ - Supports icon, label, value display
1506
+ - Supports copyable rows
1507
+ - Supports custom value classes
1508
+ - Supports action slot for buttons
1509
+ - Replaces ~260 lines of duplicated markup"
1510
+ ```
1511
+
1512
+ ---
1513
+
1514
+ ### Task 5.7: Replace InfoRow in ViewTask.vue
1515
+
1516
+ **Files:**
1517
+ - Modify: `src/components/Tasks/ViewTask.vue`
1518
+
1519
+ **Step 1: Import InfoRow**
1520
+
1521
+ ```javascript
1522
+ import InfoRow from '@/components/ui/InfoRow.vue'
1523
+ ```
1524
+
1525
+ **Step 2: Replace info row markup**
1526
+
1527
+ Find instances like:
1528
+
1529
+ ```vue
1530
+ <div class="info-row">
1531
+ <IdIcon />
1532
+ <span>ID</span>
1533
+ <span>{{ task.id }}</span>
1534
+ </div>
1535
+ ```
1536
+
1537
+ Replace with:
1538
+
1539
+ ```vue
1540
+ <InfoRow
1541
+ :icon="IdIcon"
1542
+ label="ID"
1543
+ :value="task.id"
1544
+ copyable
1545
+ :copy-text="task.id"
1546
+ />
1547
+ ```
1548
+
1549
+ **Step 3: Test**
1550
+
1551
+ Open task details modal
1552
+ Test: All info rows render, copy functionality works
1553
+
1554
+ **Step 4: Commit**
1555
+
1556
+ ```bash
1557
+ git add src/components/Tasks/ViewTask.vue
1558
+ git commit -m "refactor: use InfoRow component in ViewTask.vue
1559
+
1560
+ - Replace 20+ info row instances
1561
+ - Remove duplicated markup"
1562
+ ```
1563
+
1564
+ ---
1565
+
1566
+ ### Task 5.8: Create SectionCard Component
1567
+
1568
+ **Files:**
1569
+ - Create: `src/components/ui/SectionCard.vue`
1570
+
1571
+ **Step 1: Create component**
1572
+
1573
+ ```vue
1574
+ <script setup>
1575
+ import { defineProps } from 'vue'
1576
+
1577
+ const props = defineProps({
1578
+ title: {
1579
+ type: String,
1580
+ default: ''
1581
+ }
1582
+ })
1583
+ </script>
1584
+
1585
+ <template>
1586
+ <div class="bg-dark-400 rounded-lg p-4 border border-dark-600">
1587
+ <h3
1588
+ v-if="title"
1589
+ class="text-lg font-semibold text-light-300 mb-4 pb-2 border-b border-dark-600"
1590
+ >
1591
+ {{ title }}
1592
+ </h3>
1593
+ <slot />
1594
+ </div>
1595
+ </template>
1596
+ ```
1597
+
1598
+ **Step 2: Commit**
1599
+
1600
+ ```bash
1601
+ git add src/components/ui/SectionCard.vue
1602
+ git commit -m "feat: create SectionCard component
1603
+
1604
+ - Card container with optional title
1605
+ - Consistent styling across modals
1606
+ - Uses Tailwind exclusively"
1607
+ ```
1608
+
1609
+ ---
1610
+
1611
+ ### Task 5.9: Use SectionCard in ViewTask.vue
1612
+
1613
+ **Files:**
1614
+ - Modify: `src/components/Tasks/ViewTask.vue`
1615
+
1616
+ **Step 1: Import SectionCard**
1617
+
1618
+ **Step 2: Replace section-card markup**
1619
+
1620
+ Replace:
1621
+
1622
+ ```vue
1623
+ <div class="section-card">
1624
+ <h3 class="section-title">Details</h3>
1625
+ <!-- content -->
1626
+ </div>
1627
+ ```
1628
+
1629
+ With:
1630
+
1631
+ ```vue
1632
+ <SectionCard title="Details">
1633
+ <!-- content -->
1634
+ </SectionCard>
1635
+ ```
1636
+
1637
+ **Step 3: Remove section-card styles**
1638
+
1639
+ **Step 4: Test**
1640
+
1641
+ **Step 5: Commit**
1642
+
1643
+ ```bash
1644
+ git add src/components/Tasks/ViewTask.vue
1645
+ git commit -m "refactor: use SectionCard component in ViewTask.vue"
1646
+ ```
1647
+
1648
+ ---
1649
+
1650
+ ### Task 5.10: Create ActionButtonGroup Component
1651
+
1652
+ **Files:**
1653
+ - Create: `src/components/ui/ActionButtonGroup.vue`
1654
+
1655
+ **Step 1: Create component**
1656
+
1657
+ ```vue
1658
+ <template>
1659
+ <ul class="flex items-center gap-1 mobile-portrait:gap-0.5">
1660
+ <slot />
1661
+ </ul>
1662
+ </template>
1663
+
1664
+ <style scoped>
1665
+ /* Minimal styles for button group - mostly handled by slot content */
1666
+ </style>
1667
+ ```
1668
+
1669
+ **Step 2: Commit**
1670
+
1671
+ ```bash
1672
+ git add src/components/ui/ActionButtonGroup.vue
1673
+ git commit -m "feat: create ActionButtonGroup component
1674
+
1675
+ - Wrapper for row action buttons
1676
+ - Consistent responsive spacing
1677
+ - Replaces 555+ lines of duplicated CSS"
1678
+ ```
1679
+
1680
+ ---
1681
+
1682
+ ### Task 5.11: Use ActionButtonGroup in Task.vue
1683
+
1684
+ **Files:**
1685
+ - Modify: `src/components/Tasks/Task.vue`
1686
+
1687
+ **Step 1: Import ActionButtonGroup**
1688
+
1689
+ **Step 2: Wrap buttons**
1690
+
1691
+ Replace:
1692
+
1693
+ ```vue
1694
+ <ul class="task-buttons">
1695
+ <li><button>...</button></li>
1696
+ <li><button>...</button></li>
1697
+ </ul>
1698
+ ```
1699
+
1700
+ With:
1701
+
1702
+ ```vue
1703
+ <ActionButtonGroup>
1704
+ <li><button>...</button></li>
1705
+ <li><button>...</button></li>
1706
+ </ActionButtonGroup>
1707
+ ```
1708
+
1709
+ **Step 3: Remove .task-buttons styles**
1710
+
1711
+ **Step 4: Test**
1712
+
1713
+ **Step 5: Commit**
1714
+
1715
+ ```bash
1716
+ git add src/components/Tasks/Task.vue
1717
+ git commit -m "refactor: use ActionButtonGroup in Task.vue
1718
+
1719
+ - Replace custom button group with component
1720
+ - Remove ~185 lines of CSS"
1721
+ ```
1722
+
1723
+ ---
1724
+
1725
+ ### Task 5.12: Use ActionButtonGroup in Account.vue
1726
+
1727
+ **Files:**
1728
+ - Modify: `src/components/Editors/Account/Account.vue`
1729
+
1730
+ **Step 1-5:** Same as Task 5.11
1731
+
1732
+ **Step 6: Commit**
1733
+
1734
+ ```bash
1735
+ git add src/components/Editors/Account/Account.vue
1736
+ git commit -m "refactor: use ActionButtonGroup in Account.vue"
1737
+ ```
1738
+
1739
+ ---
1740
+
1741
+ ### Task 5.13: Use ActionButtonGroup in Profile.vue
1742
+
1743
+ **Files:**
1744
+ - Modify: `src/components/Editors/Profile/Profile.vue`
1745
+
1746
+ **Step 1-5:** Same as Task 5.11
1747
+
1748
+ **Step 6: Commit**
1749
+
1750
+ ```bash
1751
+ git add src/components/Editors/Profile/Profile.vue
1752
+ git commit -m "refactor: use ActionButtonGroup in Profile.vue"
1753
+ ```
1754
+
1755
+ ---
1756
+
1757
+ ## Phase 6: Color Migration (Medium Priority)
1758
+
1759
+ ### Task 6.1: Replace Hardcoded Gray Colors
1760
+
1761
+ **Files:**
1762
+ - Modify: `src/components/Editors/Account/AccountView.vue`
1763
+ - Modify: `src/components/Editors/Profile/ProfileView.vue`
1764
+ - Modify: `src/components/Tasks/TaskView.vue`
1765
+
1766
+ **Step 1: Find and replace #969696**
1767
+
1768
+ Find: `color: #969696`
1769
+ Replace with class: `text-light-500`
1770
+
1771
+ **Step 2: Find and replace #9CA3AF**
1772
+
1773
+ Find: `color: #9CA3AF`
1774
+ Replace with class: `text-light-400`
1775
+
1776
+ **Step 3: Test**
1777
+
1778
+ Check all views, ensure text colors look identical
1779
+
1780
+ **Step 4: Commit**
1781
+
1782
+ ```bash
1783
+ git add src/components/Editors/Account/AccountView.vue src/components/Editors/Profile/ProfileView.vue src/components/Tasks/TaskView.vue
1784
+ git commit -m "refactor: replace hardcoded gray text colors with theme tokens
1785
+
1786
+ - Replace #969696 with text-light-500
1787
+ - Replace #9CA3AF with text-light-400"
1788
+ ```
1789
+
1790
+ ---
1791
+
1792
+ ### Task 6.2: Replace rgba Gray Backgrounds in Filter.vue
1793
+
1794
+ **Files:**
1795
+ - Modify: `src/components/Filter/Filter.vue`
1796
+
1797
+ **Step 1: Replace rgba(61, 62, 68, X)**
1798
+
1799
+ Find: `rgba(61, 62, 68, 0.3)`
1800
+ Replace with: `bg-dark-625/30`
1801
+
1802
+ Find: `rgba(61, 62, 68, 0.6)`
1803
+ Replace with: `bg-dark-625/60`
1804
+
1805
+ **Step 2: Replace rgba(68, 69, 75, X)**
1806
+
1807
+ Find: `rgba(68, 69, 75, 0.3)`
1808
+ Replace with: `bg-dark-675/30`
1809
+
1810
+ **Step 3: Replace rgba(46, 47, 52, X)**
1811
+
1812
+ Find: `rgba(46, 47, 52, 0.9)`
1813
+ Replace with: `bg-dark-475/90`
1814
+
1815
+ **Step 4: Replace rgba(35, 36, 41, X)**
1816
+
1817
+ Find: `rgba(35, 36, 41, 0.9)`
1818
+ Replace with: `bg-dark-450/90`
1819
+
1820
+ **Step 5: Test filter component**
1821
+
1822
+ Test: Filter appearance, background colors, opacity levels
1823
+
1824
+ **Step 6: Commit**
1825
+
1826
+ ```bash
1827
+ git add src/components/Filter/Filter.vue
1828
+ git commit -m "refactor: replace rgba gray backgrounds with dark scale tokens
1829
+
1830
+ - Use dark-625, dark-675, dark-475, dark-450 with opacity
1831
+ - Replace ~30 rgba instances"
1832
+ ```
1833
+
1834
+ ---
1835
+
1836
+ ### Task 6.3: Replace Error Color Variations
1837
+
1838
+ **Files:**
1839
+ - Modify: `src/components/Filter/Filter.vue`
1840
+ - Modify: `src/components/Editors/Profile/CreateProfile.vue`
1841
+ - Modify: `src/components/Editors/Account/CreateAccount.vue`
1842
+
1843
+ **Step 1: Replace #EE8282**
1844
+
1845
+ Find: `#EE8282` or `rgb(238, 130, 130)`
1846
+ Replace with class: `text-error-300` or `border-error-300`
1847
+
1848
+ **Step 2: Replace rgba(239, 68, 68, X)**
1849
+
1850
+ Find: `rgba(239, 68, 68, 0.8)`
1851
+ Replace with: `bg-error-500/80`
1852
+
1853
+ **Step 3: Test**
1854
+
1855
+ Check error states, border colors, text colors
1856
+
1857
+ **Step 4: Commit**
1858
+
1859
+ ```bash
1860
+ git add src/components/Filter/Filter.vue src/components/Editors/Profile/CreateProfile.vue src/components/Editors/Account/CreateAccount.vue
1861
+ git commit -m "refactor: standardize error colors
1862
+
1863
+ - Replace #EE8282 with error-300
1864
+ - Replace rgba(239,68,68,X) with error-500
1865
+ - Consolidate error color usage"
1866
+ ```
1867
+
1868
+ ---
1869
+
1870
+ ### Task 6.4: Replace Modal Overlay Color
1871
+
1872
+ **Files:**
1873
+ - Modify: `src/components/ui/Modal.vue` (if not done in Task 4.3)
1874
+
1875
+ **Step 1: Replace rgba(17, 17, 17, 0.85)**
1876
+
1877
+ Find: `background-color: rgba(17, 17, 17, 0.85)`
1878
+ Replace with class: `bg-overlay-dark`
1879
+
1880
+ **Step 2: Test**
1881
+
1882
+ Open modal, check overlay appearance
1883
+
1884
+ **Step 3: Commit**
1885
+
1886
+ ```bash
1887
+ git add src/components/ui/Modal.vue
1888
+ git commit -m "refactor: use overlay-dark token for modal background"
1889
+ ```
1890
+
1891
+ ---
1892
+
1893
+ ### Task 6.5: Replace Accent Color Variations in ReconnectIndicator
1894
+
1895
+ **Files:**
1896
+ - Modify: `src/components/ui/ReconnectIndicator.vue`
1897
+
1898
+ **Step 1: Replace rgba(136, 201, 153, X)**
1899
+
1900
+ Find: `rgba(136, 201, 153, 0.3)` (and similar)
1901
+ Replace with: `bg-accent-green/30`
1902
+
1903
+ **Step 2: Replace rgba(157, 211, 168, X)**
1904
+
1905
+ Replace with: `bg-accent-green/40` (approximate)
1906
+
1907
+ **Step 3: Replace rgba(123, 193, 135, X)**
1908
+
1909
+ Replace with: `bg-accent-green/50` (approximate)
1910
+
1911
+ **Step 4: Test**
1912
+
1913
+ Trigger reconnection, check indicator colors
1914
+
1915
+ **Step 5: Commit**
1916
+
1917
+ ```bash
1918
+ git add src/components/ui/ReconnectIndicator.vue
1919
+ git commit -m "refactor: use accent-green token for reconnect indicator
1920
+
1921
+ - Replace hardcoded rgba green variants
1922
+ - Use accent-green with opacity"
1923
+ ```
1924
+
1925
+ ---
1926
+
1927
+ ## Phase 7: Remaining CSS Cleanup
1928
+
1929
+ ### Task 7.1: Clean Up CountryChooser.vue
1930
+
1931
+ **Files:**
1932
+ - Modify: `src/components/ui/controls/CountryChooser.vue`
1933
+
1934
+ **Step 1: Replace circular button hack**
1935
+
1936
+ Find:
1937
+
1938
+ ```css
1939
+ border-radius: 100% !important;
1940
+ width: 3em !important;
1941
+ height: 3em !important;
1942
+ ```
1943
+
1944
+ Replace with:
1945
+
1946
+ ```vue
1947
+ class="rounded-full w-12 h-12"
1948
+ ```
1949
+
1950
+ **Step 2: Remove dropdown !important**
1951
+
1952
+ Find:
1953
+
1954
+ ```css
1955
+ max-height: 208px !important;
1956
+ overflow-y: auto !important;
1957
+ touch-action: pan-y !important;
1958
+ ```
1959
+
1960
+ Replace with:
1961
+
1962
+ ```vue
1963
+ class="max-h-52 overflow-y-auto touch-pan-y"
1964
+ ```
1965
+
1966
+ **Step 3: Convert header padding/margin**
1967
+
1968
+ Replace hardcoded values with Tailwind spacing utilities
1969
+
1970
+ **Step 4: Test**
1971
+
1972
+ Test country chooser dropdown, button appearance
1973
+
1974
+ **Step 5: Commit**
1975
+
1976
+ ```bash
1977
+ git add src/components/ui/controls/CountryChooser.vue
1978
+ git commit -m "refactor: clean up CountryChooser.vue
1979
+
1980
+ - Replace circular button hack with Tailwind
1981
+ - Remove !important overrides
1982
+ - Convert spacing to Tailwind utilities
1983
+ - Remove ~40 lines of CSS"
1984
+ ```
1985
+
1986
+ ---
1987
+
1988
+ ### Task 7.2: Clean Up Table.vue
1989
+
1990
+ **Files:**
1991
+ - Modify: `src/components/Table/Table.vue`
1992
+
1993
+ **Step 1: Remove scroll !important**
1994
+
1995
+ Find:
1996
+
1997
+ ```css
1998
+ overflow-x: auto !important;
1999
+ overflow-y: auto !important;
2000
+ touch-action: pan-x pan-y !important;
2001
+ ```
2002
+
2003
+ Replace with:
2004
+
2005
+ ```vue
2006
+ class="overflow-x-auto overflow-y-auto touch-pan-x touch-pan-y"
2007
+ ```
2008
+
2009
+ **Step 2: Simplify max-height calculation**
2010
+
2011
+ Keep `calc(100vh - 200px)` but remove !important if present
2012
+
2013
+ **Step 3: Remove landscape mode hack**
2014
+
2015
+ Remove:
2016
+
2017
+ ```css
2018
+ @media (orientation: landscape) {
2019
+ max-height: calc(100vh - 160px) !important;
2020
+ margin-bottom: 2rem !important;
2021
+ }
2022
+ ```
2023
+
2024
+ Since iPhone landscape is no longer supported.
2025
+
2026
+ **Step 4: Test**
2027
+
2028
+ Test table scrolling, responsiveness
2029
+
2030
+ **Step 5: Commit**
2031
+
2032
+ ```bash
2033
+ git add src/components/Table/Table.vue
2034
+ git commit -m "refactor: clean up Table.vue
2035
+
2036
+ - Remove scroll !important overrides
2037
+ - Remove landscape mode hacks
2038
+ - Simplify height calculations
2039
+ - Remove ~30 lines of CSS"
2040
+ ```
2041
+
2042
+ ---
2043
+
2044
+ ### Task 7.3: Clean Up Console.vue
2045
+
2046
+ **Files:**
2047
+ - Modify: `src/views/Console.vue`
2048
+
2049
+ **Step 1: Optimize responsive padding**
2050
+
2051
+ Replace:
2052
+
2053
+ ```css
2054
+ padding-bottom: 4rem;
2055
+ @media (max-width: 480px) {
2056
+ padding-bottom: 6rem;
2057
+ }
2058
+ ```
2059
+
2060
+ With:
2061
+
2062
+ ```vue
2063
+ class="pb-16 mobile-portrait:pb-24"
2064
+ ```
2065
+
2066
+ **Step 2: Remove touch-action !important**
2067
+
2068
+ **Step 3: Test**
2069
+
2070
+ Navigate to console, check padding, scroll behavior
2071
+
2072
+ **Step 4: Commit**
2073
+
2074
+ ```bash
2075
+ git add src/views/Console.vue
2076
+ git commit -m "refactor: clean up Console.vue responsive padding"
2077
+ ```
2078
+
2079
+ ---
2080
+
2081
+ ### Task 7.4: Clean Up Tasks.vue
2082
+
2083
+ **Files:**
2084
+ - Modify: `src/views/Tasks.vue`
2085
+
2086
+ **Step 1: Remove PWA padding hack**
2087
+
2088
+ Find:
2089
+
2090
+ ```css
2091
+ @media (display-mode: standalone) {
2092
+ padding-bottom: X !important;
2093
+ }
2094
+ ```
2095
+
2096
+ Replace with proper Tailwind utility if needed, or remove if redundant.
2097
+
2098
+ **Step 2: Remove magic height !important**
2099
+
2100
+ **Step 3: Test**
2101
+
2102
+ Navigate to tasks page, check layout
2103
+
2104
+ **Step 4: Commit**
2105
+
2106
+ ```bash
2107
+ git add src/views/Tasks.vue
2108
+ git commit -m "refactor: clean up Tasks.vue PWA hacks"
2109
+ ```
2110
+
2111
+ ---
2112
+
2113
+ ### Task 7.5: Clean Up Switch.vue
2114
+
2115
+ **Files:**
2116
+ - Modify: `src/components/ui/controls/atomic/Switch.vue`
2117
+
2118
+ **Step 1: Convert hardcoded px to Tailwind**
2119
+
2120
+ The Switch component has well-structured iOS-style CSS. Keep the custom styles but ensure Tailwind is used where possible for spacing, colors.
2121
+
2122
+ **Step 2: Test**
2123
+
2124
+ Test switch toggle behavior, appearance
2125
+
2126
+ **Step 3: Commit**
2127
+
2128
+ ```bash
2129
+ git add src/components/ui/controls/atomic/Switch.vue
2130
+ git commit -m "refactor: optimize Switch.vue with Tailwind where applicable"
2131
+ ```
2132
+
2133
+ ---
2134
+
2135
+ ### Task 7.6: Clean Up Splash.vue
2136
+
2137
+ **Files:**
2138
+ - Modify: `src/components/ui/Splash.vue`
2139
+
2140
+ **Step 1: Replace background-color**
2141
+
2142
+ Find: `background-color: rgba(28, 28, 49, 100%)`
2143
+ Replace with: `class="bg-dark-300"`
2144
+
2145
+ **Step 2: Test**
2146
+
2147
+ Check splash screen appearance
2148
+
2149
+ **Step 3: Commit**
2150
+
2151
+ ```bash
2152
+ git add src/components/ui/Splash.vue
2153
+ git commit -m "refactor: use theme color in Splash.vue"
2154
+ ```
2155
+
2156
+ ---
2157
+
2158
+ ## Phase 8: Final Verification
2159
+
2160
+ ### Task 8.1: Run Automated Verification Plan
2161
+
2162
+ **Files:**
2163
+ - Reference: `/Users/luca/Documents/GitHub/Necro/Dashboard/VERIFICATION_PLAN.md`
2164
+
2165
+ **Step 1: Start both dev servers**
2166
+
2167
+ Run: `npm run dev`
2168
+ Expected: Servers on 5173 and 8081
2169
+
2170
+ **Step 2: Manual quick check**
2171
+
2172
+ Test critical paths:
2173
+ - Login flow
2174
+ - Navigate to each route
2175
+ - Open/close modals
2176
+ - Test dropdowns
2177
+ - Test tables
2178
+ - Test forms
2179
+
2180
+ **Step 3: Responsive testing**
2181
+
2182
+ Test at breakpoints:
2183
+ - Mobile portrait (375px)
2184
+ - iPad Pro (1024px)
2185
+ - Desktop (1920px)
2186
+
2187
+ **Step 4: PWA verification**
2188
+
2189
+ - Check manifest
2190
+ - Test service worker
2191
+ - Test offline behavior
2192
+ - Test install prompt
2193
+
2194
+ **Step 5: Document any issues**
2195
+
2196
+ Create issues file if regressions found.
2197
+
2198
+ **Step 6: Commit verification results**
2199
+
2200
+ ```bash
2201
+ git add VERIFICATION_PLAN.md
2202
+ git commit -m "docs: verification results for Tailwind consolidation"
2203
+ ```
2204
+
2205
+ ---
2206
+
2207
+ ### Task 8.2: Count Remaining CSS Lines
2208
+
2209
+ **Files:**
2210
+ - All Vue files
2211
+
2212
+ **Step 1: Count <style> blocks**
2213
+
2214
+ Run: `grep -r "<style" src/components src/views | wc -l`
2215
+
2216
+ **Step 2: Count !important usage**
2217
+
2218
+ Run: `grep -r "!important" src/components src/views | wc -l`
2219
+
2220
+ **Step 3: Compare with baseline**
2221
+
2222
+ Baseline:
2223
+ - 53 files with `<style>` blocks
2224
+ - 378 `!important` declarations
2225
+
2226
+ Target:
2227
+ - < 20 files with `<style>` blocks (animations only)
2228
+ - < 50 `!important` declarations
2229
+
2230
+ **Step 4: Document results**
2231
+
2232
+ Create summary in docs/plans/2026-02-08-tailwind-consolidation-results.md
2233
+
2234
+ ---
2235
+
2236
+ ### Task 8.3: Create Final Summary Report
2237
+
2238
+ **Files:**
2239
+ - Create: `docs/plans/2026-02-08-tailwind-consolidation-results.md`
2240
+
2241
+ **Step 1: Document changes**
2242
+
2243
+ ```markdown
2244
+ # Tailwind Consolidation Results
2245
+
2246
+ ## Metrics
2247
+
2248
+ **Before:**
2249
+ - Files with <style> blocks: 53
2250
+ - !important declarations: 378
2251
+ - Lines of CSS: ~2000
2252
+ - Duplicate components: 7 patterns identified
2253
+
2254
+ **After:**
2255
+ - Files with <style> blocks: X
2256
+ - !important declarations: X
2257
+ - Lines of CSS: ~X
2258
+ - Duplicate components: 0 (all extracted)
2259
+
2260
+ ## Components Created
2261
+
2262
+ 1. StatusBadge - 4 files refactored
2263
+ 2. FormField - 5 files refactored
2264
+ 3. InfoRow - 2 files refactored
2265
+ 4. SectionCard - 2 files refactored
2266
+ 5. ActionButtonGroup - 3 files refactored
2267
+
2268
+ ## Composables Created
2269
+
2270
+ 1. useRowSelection - 3 files refactored
2271
+ 2. useCopyToClipboard - 3 files refactored
2272
+
2273
+ ## Theme Tokens Added
2274
+
2275
+ - Dark scale extensions: 350, 450, 475, 625, 675
2276
+ - Error colors: 300, 400, 500
2277
+ - Overlay colors: dark, darker
2278
+ - Semantic tokens: text-*, bg-*, border-focus, primary
2279
+ - Shadow system: 7 new shadows
2280
+ - Font sizes: xxs, xxxs
2281
+
2282
+ ## Files Modified
2283
+
2284
+ [List all modified files]
2285
+
2286
+ ## Breaking Changes
2287
+
2288
+ - iPhone landscape support removed (forces rotation)
2289
+
2290
+ ## Verification Status
2291
+
2292
+ - ✅ All routes accessible
2293
+ - ✅ Responsive behavior maintained
2294
+ - ✅ PWA functionality working
2295
+ - ✅ Dark theme intact
2296
+ - ✅ No visual regressions
2297
+ ```
2298
+
2299
+ **Step 2: Commit**
2300
+
2301
+ ```bash
2302
+ git add docs/plans/2026-02-08-tailwind-consolidation-results.md
2303
+ git commit -m "docs: Tailwind consolidation completion report"
2304
+ ```
2305
+
2306
+ ---
2307
+
2308
+ ## Phase 9: Cleanup and Documentation
2309
+
2310
+ ### Task 9.1: Update README (if exists)
2311
+
2312
+ **Files:**
2313
+ - Modify: `README.md` (if exists)
2314
+
2315
+ **Step 1: Document new components**
2316
+
2317
+ Add section:
2318
+
2319
+ ```markdown
2320
+ ## UI Components
2321
+
2322
+ - `StatusBadge` - Enabled/disabled badge indicator
2323
+ - `FormField` - Input field with label and icon
2324
+ - `InfoRow` - Key-value display row
2325
+ - `SectionCard` - Card container for modal sections
2326
+ - `ActionButtonGroup` - Row action button group
2327
+
2328
+ ## Composables
2329
+
2330
+ - `useRowSelection` - Double-click/tap row selection
2331
+ - `useCopyToClipboard` - Copy to clipboard with notification
2332
+ ```
2333
+
2334
+ **Step 2: Update supported devices**
2335
+
2336
+ ```markdown
2337
+ ## Supported Devices
2338
+
2339
+ - Desktop (1024px+)
2340
+ - iPad Pro
2341
+ - iPhone (Portrait mode only)
2342
+
2343
+ iPhone landscape mode forces rotation to portrait.
2344
+ ```
2345
+
2346
+ **Step 3: Commit**
2347
+
2348
+ ```bash
2349
+ git add README.md
2350
+ git commit -m "docs: update README with new components and device support"
2351
+ ```
2352
+
2353
+ ---
2354
+
2355
+ ### Task 9.2: Final Commit and Branch Summary
2356
+
2357
+ **Step 1: Review all changes**
2358
+
2359
+ Run: `git log --oneline | head -50`
2360
+
2361
+ **Step 2: Create final summary commit**
2362
+
2363
+ ```bash
2364
+ git commit --allow-empty -m "feat: complete Tailwind CSS consolidation
2365
+
2366
+ Summary of changes:
2367
+ - Removed 1,600+ lines of duplicate CSS
2368
+ - Extracted 5 reusable components
2369
+ - Created 2 composables for common patterns
2370
+ - Extended Tailwind theme with 20+ tokens
2371
+ - Removed 300+ !important declarations
2372
+ - Removed iPhone landscape support
2373
+ - Achieved near-zero CSS in Vue files
2374
+
2375
+ Components created:
2376
+ - StatusBadge (4 files refactored)
2377
+ - FormField (5 files refactored)
2378
+ - InfoRow (2 files refactored)
2379
+ - SectionCard (2 files refactored)
2380
+ - ActionButtonGroup (3 files refactored)
2381
+
2382
+ Composables created:
2383
+ - useRowSelection (3 files)
2384
+ - useCopyToClipboard (3 files)
2385
+
2386
+ All functionality verified, no regressions."
2387
+ ```
2388
+
2389
+ ---
2390
+
2391
+ ## Execution Notes
2392
+
2393
+ **Estimated time:** 8-12 hours (depending on file complexity)
2394
+
2395
+ **Recommended approach:**
2396
+ 1. Execute phases sequentially
2397
+ 2. Test after each phase before moving to next
2398
+ 3. Commit frequently (after each task)
2399
+ 4. Use verification plan after Phase 4, 5, 7, and 8
2400
+
2401
+ **Rollback strategy:**
2402
+ If any phase causes issues, rollback to previous phase commit:
2403
+ ```bash
2404
+ git log --oneline
2405
+ git reset --hard <commit-hash>
2406
+ ```
2407
+
2408
+ **Testing checklist per phase:**
2409
+ - [ ] Phase 1: Dev server starts, no config errors
2410
+ - [ ] Phase 2: App loads without landscape lock
2411
+ - [ ] Phase 3: Components render correctly
2412
+ - [ ] Phase 4: No visual regressions in cleaned files
2413
+ - [ ] Phase 5: Forms and info displays work
2414
+ - [ ] Phase 6: Colors look identical to before
2415
+ - [ ] Phase 7: Remaining components work
2416
+ - [ ] Phase 8: Full app verification passes