Micro-Motion Philosophy & Sub-100ms Hover
Motion serves as spatial anchors, not entertainment; zero-delay 0ms hover principles and state morph class isolation.
Micro-Motion Philosophy & Sub-100ms Hover
In desktop productivity applications, micro-motion exists solely to sustain spatial continuity in the user's mental model. Sluggish transitions destroy professional velocity.
Motion as Spatial Anchors, Not Entertainment
Consumer apps indulge in 600ms card flips. In Tuff, users execute hundreds of rapid operations daily:
- Motion's sole legitimate role is an optical spatial anchor: communicating where elements originate from and collapse into.
- The vast majority of micro-interactions complete within 90ms–180ms.
- Motion must never block incoming keyboard inputs or pointer clicks.
Hover States Require 0ms Instant Response
Moving a pointer across a screen is a high-intent exploratory action. Iron Rule: When the cursor enters an interactive hit area, background fills and text inks must update in 0ms!
Attempting to ease colors on hover makes the pointer feel bogged down in molasses, ruining responsive tactile feedback.
Why Easing Hover Colors Feels Laggy
Human motor reflexes expect visual feedback under the 100ms threshold. If an engineer declares:
// Severe anti-pattern!
.btn { transition: background-color 200ms ease; }
As the cursor traverses a button cluster, backgrounds fade in lethargically. The cursor exits before the transition resolves, inducing the physiological sensation of input lag.
State Morph Transition Class Isolation
When is color easing permissible? Only during semantic state shifts (e.g. converting a chip from muted to dangerous).
To prevent state transitions from polluting hover states, TuffEx's rule is: Color transitions must attach exclusively to temporary morph classes, never to the element root. Here is how TxModeChip writes it (variable fallbacks omitted):
.tx-mode-chip {
// Hover remains immediate: 0ms delay
&:hover:not(:disabled) {
background-color: var(--tx-mode-chip-fill-hover);
color: var(--tx-mode-chip-ink-hover, var(--tx-mode-chip-ink));
}
// Activated only during explicit semantic morphs
&.is-morphing {
transition:
background-color 240ms var(--tx-ease-out-strong),
color 240ms var(--tx-ease-out-strong);
}
}
Through class isolation, hovers retain instant snap, while semantic state changes morph smoothly.
Every TuffEx component now keeps this rule: a hover always repaints at once. A color transition either lives on .is-morphing alone, which a state change such as selecting, opening or focusing adds and the end of its longest color leg removes, or sits on an element whose color no hover changes. A highlight that follows the pointer counts as a hover too, for example TxSearchPanel's options and TxCascader's expanded path, and repaints at once as well.