feat(ux): listeden silme geri alınabilir; better-ui skill'i eklendi
- Çekmecede "Listeyi temizle" ve satır çıkarma (düğme ve kaydırma) anında siliyordu, geri dönüş yoktu. Artık 8 sn "Geri al" bildirimi; çıkanlar eski sıralarına döner, arada eklenenler korunur - Çekmece kaydırması sayfaya taşmıyor (overscroll-contain) - .claude/skills/better-ui: Jakub Krehel'in UI cilası skill'i (ui-skills.com); başına DESIGN.md önceliği ve çakışan iki değer notu eklendi Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
106
.claude/skills/better-ui/SKILL.md
Normal file
106
.claude/skills/better-ui/SKILL.md
Normal file
@@ -0,0 +1,106 @@
|
||||
---
|
||||
name: better-ui
|
||||
description: Design engineering principles for making interfaces feel polished. Use when building UI components, reviewing frontend code, implementing animations, hover states, shadows, borders, micro-interactions, enter/exit animations, or any visual detail work. Triggers on UI polish, design details, "make it feel better", "feels off", stagger animations, border radius, optical alignment, image outlines, box shadows.
|
||||
---
|
||||
|
||||
> **KolayTercih notu (25 Eyl 2026, Bilal'in isteğiyle eklendi).** Kaynak: Jakub Krehel,
|
||||
> https://github.com/jakubkrehel/skills (ui-skills.com üzerinden okundu, elle kopyalandı).
|
||||
> Bu projede `docs/tasarim/DESIGN.md` önceliklidir. Çakışan iki nokta:
|
||||
> basınca küçülme bizde `scale-[0.97]` (geniş satır `0.99`, çarpı `0.96`), buradaki `0.96`
|
||||
> değil; kart ve satırlarda yapıyı `border-slate-200` verir, gölge yalnız §4.4'teki kadar.
|
||||
> Görsel ayar yaparken önce DESIGN.md, sonra bu dosya.
|
||||
|
||||
# UI polish
|
||||
|
||||
Polish comes from a pile of small details that compound. This skill is the reference for which are worth having and what values they take.
|
||||
|
||||
When reviewing, slow the interface down. What feels off at 10% speed is what is subtly wrong at full speed.
|
||||
|
||||
Keep the project's component library, tokens and density, and match its motion language except where a rule below prescribes an exact interaction.
|
||||
|
||||
Every duration, curve, scale and blur below is a specific value, not a range to approximate. cubic-bezier(0.2, 0, 0, 1) is not cubic-bezier(0.4, 0, 0.2, 1), and 0.96 is not 0.95. Use what is written.
|
||||
|
||||
## Concentric border radius
|
||||
|
||||
Outer radius = inner radius + padding. Mismatched radii on nested elements is the most common thing that makes an interface feel off.
|
||||
|
||||
## Optical over geometric alignment
|
||||
|
||||
When geometric centering looks off, align optically. Buttons with icons, play triangles and asymmetric icons all need a manual nudge.
|
||||
|
||||
## Shadows for elevation, borders for structure
|
||||
|
||||
Where a border exists only to create depth, prefer layered transparent box-shadow values. Keep borders that communicate structure or state: dividers, separators and selected or focus states.
|
||||
|
||||
## Interruptible animations
|
||||
|
||||
Use CSS transitions for interactive state changes, because they can be interrupted mid-animation. Reserve keyframes for staged sequences that run once.
|
||||
|
||||
## Split and stagger enter animations
|
||||
|
||||
For an infrequent staged entrance where sequence communicates hierarchy, break the content into semantic chunks and stagger them by ~100ms. Animating one container gets you less for the same cost. Leave high-frequency interactions unstaggered.
|
||||
|
||||
## Subtle exit animations
|
||||
|
||||
Use a small fixed translateY rather than full height. Exits should be softer than enters. Use ease-out for both directions.
|
||||
|
||||
## Contextual icon animations
|
||||
|
||||
Animate icons with opacity, scale and blur rather than toggling visibility. Use exactly these values: scale 0.25 to 1, opacity 0 to 1, blur 4px to 0px.
|
||||
|
||||
With a motion library (motion or framer-motion in package.json), match that package's import path. Use transition: { type: "spring", duration: 0.3, bounce: 0 }. Bounce is always 0.
|
||||
|
||||
Without one, keep both icons in the DOM with one absolutely positioned, and cross-fade with cubic-bezier(0.2, 0, 0, 1).
|
||||
|
||||
## Image outlines
|
||||
|
||||
Give images a 1px outline at low opacity for consistent depth. Pure black in light mode (oklch(0 0 0 / 0.1)), pure white in dark (oklch(1 0 0 / 0.1)). Never a near-black like slate or zinc and never a tinted neutral.
|
||||
|
||||
## Scale on press
|
||||
|
||||
A scale on click gives a button tactile feedback (upstream value 0.96; this project uses 0.97, see note above). Add a static prop to switch it off where motion would distract.
|
||||
|
||||
## Skip animation on page load
|
||||
|
||||
Use initial={false} on AnimatePresence to keep enter animations off the first render. Check that it leaves intentional page entrances intact.
|
||||
|
||||
## Suppress transitions on theme switch
|
||||
|
||||
A theme flip changes color, background, border and shadow on nearly every element at once. Inject *,*::before,*::after{transition:none !important}, force a reflow, then remove it on the next frame.
|
||||
|
||||
## Transition only what changes
|
||||
|
||||
Always name the exact properties: transition-property: scale, opacity. Tailwind's transition-transform covers transform, translate, scale, rotate.
|
||||
|
||||
## Use will-change sparingly
|
||||
|
||||
Only for transform, opacity and filter. Never will-change: all. Add it when you see first-frame stutter, not before.
|
||||
|
||||
## Match icon stroke to text weight
|
||||
|
||||
1.5px stroke beside regular (400) text, 2px beside semibold (600). One stroke weight per icon set and one icon library per surface.
|
||||
|
||||
## One SVG, recolored per state
|
||||
|
||||
Icons use currentColor and take hover, selected and disabled states from CSS color and opacity. Outline is the default variant; fill marks the active state.
|
||||
|
||||
## Motion restraint
|
||||
|
||||
Give high-frequency interactions instant feedback, or a transition of 150ms or less on opacity and color. Every animated state change also needs a static cue: color, an icon, or a label. Motion is never the only feedback channel.
|
||||
|
||||
## Before you finish
|
||||
|
||||
| Mistake | Fix |
|
||||
|---|---|
|
||||
| Icons look off-center | Nudge optically with padding, or fix the SVG |
|
||||
| Jarring staged entrance or exit | Stagger infrequent entrances; keep exits subtle |
|
||||
| Theme toggle crossfades the whole page | Disable transitions for the swap, force a reflow, restore on the next frame |
|
||||
| transition: all on elements | Specify exact properties |
|
||||
| First-frame animation stutter | Add will-change: transform (sparingly) |
|
||||
| Hairline icon beside bold text | Match the stroke width to the text weight |
|
||||
|
||||
## Reporting
|
||||
|
||||
Severity. HIGH breaks an interaction, makes motion unusable, or leaves a state change visible only while the animation runs. MEDIUM is a visible inconsistency in surfaces, icons, or motion. LOW is isolated polish.
|
||||
|
||||
Format: group findings under the principle each violates, ordered by severity, one row per root cause: Severity | Location | Before | After | Why. End with Block when any HIGH remains, Approve otherwise. Report every check you could not run as Not verified.
|
||||
Reference in New Issue
Block a user