- Added YAML frontmatter to all 8 polish-* skills and sweep skill so Claude can auto-invoke them - New bitcoin-conventions skill with PROUX UX methodology, sats display, address validation, Tor preferences, Lightning patterns - Path-specific rules for containers (security hardening) and frontend (Vue/glassmorphism conventions) - Gitea Actions: nightly security review and weekly dependency audit Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
126 lines
3.5 KiB
Markdown
126 lines
3.5 KiB
Markdown
---
|
|
name: polish-forms
|
|
description: Improve form validation across Archipelago UI with real-time feedback, input sanitization, disabled states during submission, and consistent error messaging. Use when user says "polish forms", "form validation", "input validation", or "fix forms".
|
|
---
|
|
|
|
# Skill: Polish Form Validation
|
|
|
|
Improve all form inputs to have real-time validation feedback, proper trimming, disabled states during submission, and consistent error messaging.
|
|
|
|
## Forms to Polish
|
|
|
|
### 1. Login.vue — Password Setup
|
|
- Real-time validation as user types (debounced 300ms):
|
|
- Length >= 8 chars (show checkmark/X)
|
|
- Passwords match (show match indicator)
|
|
- Trim input on submit
|
|
- Disable submit button while `isSubmitting`
|
|
- Clear error on new input
|
|
|
|
### 2. Login.vue — TOTP Verification
|
|
- `inputmode="numeric"` + `pattern="[0-9]*"`
|
|
- Auto-submit when 6 digits entered
|
|
- Show session timeout countdown if applicable
|
|
- Trim and strip non-numeric characters on paste
|
|
|
|
### 3. Settings.vue — Password Change
|
|
- Real-time strength validation:
|
|
- 12+ characters
|
|
- Has uppercase, lowercase, digit, special char
|
|
- New password matches confirmation
|
|
- Show strength meter (weak/medium/strong)
|
|
- Disable button during submission
|
|
- Show spinner in button during async operation
|
|
|
|
### 4. Any other form inputs found across views
|
|
|
|
## Validation Pattern
|
|
|
|
```typescript
|
|
const password = ref('')
|
|
const confirmPassword = ref('')
|
|
const isSubmitting = ref(false)
|
|
|
|
const passwordErrors = computed(() => {
|
|
const errors: string[] = []
|
|
if (password.value.length > 0 && password.value.length < 8)
|
|
errors.push('Must be at least 8 characters')
|
|
return errors
|
|
})
|
|
|
|
const passwordsMatch = computed(() =>
|
|
confirmPassword.value.length > 0 && password.value === confirmPassword.value
|
|
)
|
|
|
|
async function submit() {
|
|
if (isSubmitting.value) return
|
|
isSubmitting.value = true
|
|
try {
|
|
await rpcClient.call(...)
|
|
} catch (err) {
|
|
errorMessage.value = formatError(err)
|
|
} finally {
|
|
isSubmitting.value = false
|
|
}
|
|
}
|
|
```
|
|
|
|
## Template Pattern
|
|
|
|
```vue
|
|
<input v-model="password" type="password" class="glass-input" />
|
|
<ul v-if="passwordErrors.length" class="text-red-400 text-xs mt-1 space-y-0.5">
|
|
<li v-for="err in passwordErrors" :key="err">{{ err }}</li>
|
|
</ul>
|
|
|
|
<button
|
|
class="glass-button"
|
|
:disabled="isSubmitting || passwordErrors.length > 0"
|
|
@click="submit"
|
|
>
|
|
<span v-if="isSubmitting">Saving...</span>
|
|
<span v-else>Save</span>
|
|
</button>
|
|
```
|
|
|
|
## Input Trimming
|
|
|
|
All text inputs should be trimmed before submission:
|
|
```typescript
|
|
const trimmed = password.value.trim()
|
|
```
|
|
|
|
## Error Message Consistency
|
|
|
|
Create or use a `formatError` utility:
|
|
```typescript
|
|
function formatError(err: unknown): string {
|
|
if (err instanceof Error) {
|
|
if (err.message.includes('fetch') || err.message.includes('network'))
|
|
return 'Unable to reach server. Check your connection.'
|
|
if (err.message.includes('401') || err.message.includes('unauthorized'))
|
|
return 'Session expired. Please log in again.'
|
|
return err.message
|
|
}
|
|
return 'Something went wrong. Please try again.'
|
|
}
|
|
```
|
|
|
|
## Verification
|
|
|
|
For each form:
|
|
- [ ] Real-time validation shows feedback as user types
|
|
- [ ] Submit button disabled during operation
|
|
- [ ] Submit button disabled when validation fails
|
|
- [ ] Inputs trimmed before submission
|
|
- [ ] Error messages are user-friendly (no raw error strings)
|
|
- [ ] Success feedback shown after completion
|
|
|
|
## Deploy After Fixes
|
|
|
|
```bash
|
|
./scripts/deploy-to-target.sh --live
|
|
```
|
|
|
|
Test each form with: valid input, invalid input, empty input, whitespace-only input, rapid double-click on submit.
|