Services UI Conventions
Authenticated mini-apps under app/(services)/services/. Complements the services-confirm-toasts skill (destructive actions + toasts).
#Copy and typography
- Lowercase labels, buttons, headings, and dialog copy
- Monospace buttons:
font-mono text-xs - Form labels:
text-xs text-rurikon-400 lowercase - Inputs: bordered,
rounded-sm,text-sm text-rurikon-700,focus:border-rurikon-400
const inputCls =
'w-full border border-rurikon-border rounded-sm px-3 py-1.5 text-sm text-rurikon-700 placeholder:text-rurikon-200 focus:outline-none focus:border-rurikon-400 bg-white'
const labelCls = 'block text-xs text-rurikon-400 lowercase mb-1'
Reference: app/(services)/services/stock/_components/add-transaction-dialog.tsx
#Button states
Services use rounded buttons (unlike admin's square corners):
className={cn(
'font-mono text-xs rounded px-2.5 py-1.5 border transition-colors',
isActive
? 'bg-rurikon-800 text-white border-rurikon-600'
: 'border-rurikon-border text-rurikon-400 hover:border-rurikon-400 hover:text-rurikon-600',
)}
#Dialogs
| Use case | Component |
|---|---|
| Destructive confirm (delete) | ConfirmDialog from @/components/ui/confirm-dialog |
| Forms (add/edit) | Dialog from @/components/ui/dialog directly |
Dialog content: max-w-sm for confirms, appropriate width for forms.
#Client fetch
// Simple helper — throws on non-OK, includes credentials
import { apiFetch } from '@/lib/api-fetch'
// Or raw fetch for mutation control
const res = await fetch('/api/...', { method: 'POST', credentials: 'include', body: JSON.stringify(data) })
const json = await res.json()
if (!res.ok) { toast.error(json.error ?? 'failed'); return }
toast.success('saved')
Always credentials: 'include' for cookie auth.
#Workspace shells
Multi-view services (stock, split, jobs) use a shared shell pattern:
ServiceWorkspaceShellor feature-specific shell (JobsShell) —app/(services)/services/_components/workspace/- Wrap with
WorkspaceUIProviderfor sidebar collapse + ⌘K command palette (useCommandPaletteShortcut) - Workspace nav types in
types/services/workspace/shell.ts— not siteNavItemfromtypes/nav.ts
#Sign-in redirect
if (!user) redirect('/services/sign-in?from=/services/jobs')
After sign-in, redirect back to the from path.
#Toaster placement
Sonner <Toaster> is in app/(services)/layout.tsx (position="bottom-center") — not on public home pages.
#Autosave
Notes use autosave with inline status — do not toast on autosave. Toast only on explicit create/delete/rename actions.
#Install
Copy .cursor/skills/services-ui/SKILL.md into your project, or clone from github.com/1chooo/skills.