From fd928537e32099e34f19e23a61e7328e70b3b090 Mon Sep 17 00:00:00 2001 From: Aditya Tripathi Date: Mon, 7 Sep 2026 03:28:03 +0000 Subject: [PATCH] feat(ui): unify motion/transition system across interactive components Add shared easing curves and press/focus transitions for buttons, inputs, and form controls in app.css. Refine dropdown, modal, tooltip, and slide-over enter/leave transitions to use consistent easing and durations, and remove the focus-visible box-shadow ring on inputs/selects in favor of border-color transitions. --- resources/css/app.css | 104 +++++++++++++++++- resources/css/utilities.css | 8 +- .../configuration-sidebar.blade.php | 2 +- resources/views/components/dropdown.blade.php | 10 +- .../views/components/forms/button.blade.php | 4 + .../views/components/forms/checkbox.blade.php | 2 +- .../views/components/icon-tooltip.blade.php | 4 + .../components/modal-confirmation.blade.php | 19 ++-- .../views/components/modal-input.blade.php | 18 +-- .../views/components/slide-over.blade.php | 8 +- .../views/components/table/dropdown.blade.php | 8 +- resources/views/components/toast.blade.php | 2 +- .../views/components/top-user-menu.blade.php | 11 +- .../project/shared/get-logs.blade.php | 2 +- .../livewire/source/github/create.blade.php | 2 +- .../livewire/source/gitlab/change.blade.php | 2 +- .../livewire/source/gitlab/create.blade.php | 2 +- 17 files changed, 169 insertions(+), 39 deletions(-) diff --git a/resources/css/app.css b/resources/css/app.css index f2e7d99517..b3cb908fb3 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -77,6 +77,47 @@ command palette. Lighter and consistent, replacing the old scattered 0.45 / 0.35 / shadow-lg / shadow-sm mix. Modals keep --shadow-modal. */ --shadow-dropdown: 0 4px 12px rgb(0 0 0 / 0.12), 0 2px 4px rgb(0 0 0 / 0.08); + + /* Shared motion curves (stronger than the built-in CSS easings). Use these + for consistency: --ease-out for UI enter/press, --ease-drawer for + drawers/sheets, --ease-in-out for on-screen movement. */ + --ease-out: cubic-bezier(0.23, 1, 0.32, 1); + --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1); + --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1); +} + +/* Shared press feedback: every button-like control dips slightly on press and + eases back, so pressable elements feel responsive and consistent app-wide. */ +.button, +.icon-button, +.app-tab, +.split-action-main, +.split-action-caret { + transition-property: color, background-color, border-color, box-shadow, transform; + transition-timing-function: var(--ease-out); + transition-duration: 120ms; +} + +.button:not(:disabled):active, +.icon-button:not(:disabled):active, +.app-tab:active, +.split-action-main:not(:disabled):active, +.split-action-caret:not(:disabled):active { + transform: scale(0.97); +} + +/* Focus border/ring on any form control should ease, not snap. The accent + focus indicator is a border-color and/or box-shadow (ring) change, which the + utilities' `transition-colors` did not fully animate. Target the elements + themselves (covers bespoke search fields too) plus the div-based controls. */ +input, +textarea, +select, +.listbox-trigger, +.chip-input { + transition-property: color, background-color, border-color, box-shadow; + transition-timing-function: var(--ease-out); + transition-duration: 120ms; } /* @@ -1641,7 +1682,7 @@ html[data-theme="custom"] textarea:disabled { .application-settings-form .input:focus-visible, .application-settings-form .select:focus-visible { border-color: var(--color-accent); - box-shadow: 0 0 0 1px var(--color-accent) !important; + box-shadow: none !important; } .application-settings-workspace textarea.input, @@ -1951,6 +1992,61 @@ html[data-theme="custom"] textarea:disabled { flex-shrink: 0; } +.split-action { + display: inline-flex; +} + +.split-action-main, +.split-action-caret { + @apply button-highlighted; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.375rem; + height: 2rem; + font-size: 13px; + font-weight: 500; + white-space: nowrap; + cursor: pointer; +} + +.split-action-main { + flex: 1 1 auto; + min-width: 0; + padding: 0 0.625rem; + border-radius: 6px 0 0 6px; +} + +.split-action-caret { + flex-shrink: 0; + width: 1.75rem; + border-left: 1px solid rgba(255, 255, 255, 0.25); + border-radius: 0 6px 6px 0; +} + +.split-action > .split-action-main:only-of-type { + border-radius: 6px; +} + +.split-action-main:disabled, +.split-action-caret:disabled { + cursor: not-allowed; + opacity: 0.45; +} + +.split-action-main:focus-visible, +.split-action-caret:focus-visible { + outline: none; + position: relative; + z-index: 1; + box-shadow: 0 0 0 3px color-mix(in oklab, var(--color-accent) 40%, transparent); +} + +.application-heading-actions .split-action-main, +.application-heading-actions .split-action-caret { + height: 1.75rem; +} + /* Custom listbox (replaces native