@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.
- package/.playwright-mcp/verification-accounts-desktop.png +0 -0
- package/.playwright-mcp/verification-tasks-desktop.png +0 -0
- package/.playwright-mcp/verification-tasks-mobile.png +0 -0
- package/README.md +21 -0
- package/docs/plans/2026-02-08-tailwind-consolidation-results.md +476 -0
- package/docs/plans/2026-02-08-tailwind-consolidation.md +2416 -0
- package/package.json +1 -1
- package/src/App.vue +2 -163
- package/src/assets/css/components/buttons.scss +43 -95
- package/src/assets/css/components/forms.scss +10 -28
- package/src/assets/css/components/search-groups.scss +80 -0
- package/src/assets/css/components/tables.scss +0 -8
- package/src/assets/css/main.scss +2 -43
- package/src/components/Editors/Account/Account.vue +14 -220
- package/src/components/Editors/Account/AccountCreator.vue +0 -4
- package/src/components/Editors/Account/AccountView.vue +0 -1
- package/src/components/Editors/Account/CreateAccount.vue +36 -107
- package/src/components/Editors/Profile/CreateProfile.vue +46 -135
- package/src/components/Editors/Profile/Profile.vue +10 -213
- package/src/components/Editors/Profile/ProfileView.vue +0 -1
- package/src/components/Filter/Filter.vue +14 -17
- package/src/components/Filter/FilterPreview.vue +0 -6
- package/src/components/Table/Row.vue +1 -1
- package/src/components/Table/Table.vue +2 -16
- package/src/components/Tasks/CreateTaskAXS.vue +45 -104
- package/src/components/Tasks/CreateTaskTM.vue +58 -96
- package/src/components/Tasks/Task.vue +22 -209
- package/src/components/Tasks/TaskView.vue +5 -4
- package/src/components/Tasks/ViewTask.vue +201 -214
- package/src/components/icons/Copy.vue +6 -0
- package/src/components/icons/index.js +3 -1
- package/src/components/ui/ActionButtonGroup.vue +70 -0
- package/src/components/ui/FormField.vue +74 -0
- package/src/components/ui/InfoRow.vue +100 -0
- package/src/components/ui/Modal.vue +6 -47
- package/src/components/ui/Navbar.vue +15 -43
- package/src/components/ui/ReconnectIndicator.vue +4 -4
- package/src/components/ui/SectionCard.vue +24 -0
- package/src/components/ui/Splash.vue +1 -6
- package/src/components/ui/StatusBadge.vue +37 -0
- package/src/components/ui/controls/CountryChooser.vue +14 -58
- package/src/components/ui/controls/atomic/Dropdown.vue +16 -24
- package/src/components/ui/controls/atomic/MultiDropdown.vue +7 -1
- package/src/components/ui/controls/atomic/Switch.vue +13 -29
- package/src/composables/useCopyToClipboard.js +25 -0
- package/src/composables/useRowSelection.js +48 -0
- package/src/views/Accounts.vue +0 -81
- package/src/views/Console.vue +4 -21
- package/src/views/Editor.vue +48 -138
- package/src/views/FilterBuilder.vue +0 -23
- package/src/views/Login.vue +14 -63
- package/src/views/Profiles.vue +0 -82
- package/src/views/Tasks.vue +3 -24
- 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
|