Skip to content

feat: animation polish — view-transitions, sidebar collapse animation, reduced-motion guard, copy-icon bounce - #17

Merged
Shewart merged 3 commits into
mainfrom
feat/animation-polish
Jul 24, 2026
Merged

feat: animation polish — view-transitions, sidebar collapse animation, reduced-motion guard, copy-icon bounce#17
Shewart merged 3 commits into
mainfrom
feat/animation-polish

Conversation

@Shewart

@Shewart Shewart commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds the animation-polish layer the roadmap called for in Phase 2. Pure CSS + progressive enhancement — no Motion One dependency, no JS interop for animation, no external CDN. Every animation is guarded by a global prefers-reduced-motion rule so accessibility isn't optional.

What's new

Global (src/ShellDocs.Components/wwwroot/shelldocs-theme.css)

View-transitions API — cross-fade on route change.

@view-transition { navigation: auto; }
::view-transition-old(root),
::view-transition-new(root) { animation-duration: 180ms; animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); }

Browser-native cross-fade whenever Blazor enhanced navigation swaps the DOM. Chromium supports today; other engines silently no-op the pseudo rules. Zero JS.

Global prefers-reduced-motion guard.

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
    ::view-transition-old(root),
    ::view-transition-new(root) { animation: none !important; }
}

Kept at 0.01ms (not 0) so JS transitionend handlers still fire — dropping to true zero silently breaks any code that awaits them. Disables scroll-behavior: smooth and view-transitions too.

Sidebar section collapse (Chrome/DocsSidebarNode.razor + Chrome/DocsSidebar.razor.css)

Toggleable sections now animate their content in/out via the grid-template-rows: 0fr → 1fr trick — natural-height animation without a fixed max-height, no JS.

Refactor: toggleable sections always mount a .sidebar-section-shell wrapper regardless of open state; before this branch, the whole <div class="sidebar-section-items"> was conditionally rendered via @if (_isOpen), which made CSS transitions impossible because the element didn't exist when closed.

::deep .sidebar-section-shell {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 220ms cubic-bezier(0.16, 1, 0.3, 1);
}
::deep .sidebar-section-shell[data-open="true"] { grid-template-rows: 1fr; }
::deep .sidebar-section-shell > .sidebar-section-items {
    overflow: hidden;
    min-height: 0;
}

Non-toggleable sections (root level, always open) render directly with no wrapper — no overhead where the animation isn't needed. Chevron rotation already existed (200ms transform transition, matched to the collapse duration).

Copy-button success morph (Content/PreviewFrame.razor.css, Content/ComponentPreview.razor.css)

Both copy buttons already toggled between two SVG icons (copy → checkmark) on .copied. The transition was a snap. Now:

.preview-copy svg { transition: transform 150ms cubic-bezier(0.34, 1.56, 0.64, 1); }
.preview-copy.copied svg { transform: scale(1.15); }

Elastic-out easing gives a subtle bounce on success — 150ms in, coasts back over the 1.4s hold, snaps to base when the state flips off.

What was already animated (not touched)

  • Search dialog fade + scale-in (140ms + 160ms cubic-bezier)
  • Mobile drawer translate (260ms cubic-bezier)
  • Sidebar chevron rotation (200ms cubic-bezier — matched to new collapse timing)
  • TOC scroll-spy bar transform + height (220ms cubic-bezier)

All of the above now also inherit prefers-reduced-motion collapse via the global guard — previously they'd have fired even with the OS preference set.

Test plan

  • dotnet build shelldocs.slnx — clean, 0 warnings, 0 errors
  • dotnet test shelldocs.slnx129 / 129 passing (no new tests; CSS-only + one Razor structural refactor, covered by manual smoke)
  • Preview served:
    • _content/ShellDocs.Components/shelldocs-theme.css contains @view-transition, prefers-reduced-motion, and view-transition-old blocks
    • Every toggleable sidebar section renders a .sidebar-section-shell wrapper — visually confirmed the grid-rows transition on click
    • All 7 primitive pages (callout, card, steps, filetree, code-group, type-table, component-preview) render clean — no regressions from the sidebar-node refactor
  • Manual browser check:
    • Sidebar section chevron click → items slide open/closed, not snap
    • Route navigation → subtle cross-fade in Chromium (silent no-op in Firefox — expected)
    • Copy any preview code → copy-icon bounces on switch to checkmark
    • OS "reduce motion" toggled on → all of the above collapse to instant, no jank

Files touched

  • src/ShellDocs.Components/wwwroot/shelldocs-theme.css@view-transition, prefers-reduced-motion guard
  • src/ShellDocs.Components/Chrome/DocsSidebarNode.razor — always-mount shell wrapper for toggleable sections
  • src/ShellDocs.Components/Chrome/DocsSidebar.razor.css.sidebar-section-shell grid-rows transition
  • src/ShellDocs.Components/Content/PreviewFrame.razor.css — copy-icon bounce
  • src/ShellDocs.Components/Content/ComponentPreview.razor.css — copy-icon bounce (same pattern)

@Shewart
Shewart merged commit 1a3709c into main Jul 24, 2026
1 check passed
@Shewart
Shewart deleted the feat/animation-polish branch July 25, 2026 00:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant