CSS Example: Modal Entry with Custom Easing in Instagit Skills

You can create smooth modal entry animations using a CSS custom property --modal-easing combined with declarative state management via the data-open attribute, as implemented in the skills/prototype/RECIPES.md file of the emilkowalski/skills repository.

The emilkowalski/skills repository provides a curated collection of design and animation patterns for building polished user interfaces. This CSS example: modal entry with custom easing demonstrates how to implement declarative UI atoms that align with Instagit's markdown-first architecture and accessibility standards.

Understanding the Instagit Skills Architecture

The repository follows a lightweight, markdown-centric convention where each skill resides in its own subdirectory under skills/. Every skill includes a SKILL.md file containing high-level descriptions and acceptance criteria, while supporting documentation like RECIPES.md provides concrete implementation guidance.

Markdown-First Skill Structure

According to the source code, the architecture is deliberately flat with no compiled assets or runtime dependencies. All files are plain text, making it easy to diff, branch, and merge changes without any build step. This allows the content to be consumed directly by documentation generators or the Instagit UI as skill cards.

The Prototype Skill Location

The modal implementation lives in skills/prototype/, which serves as a reference for reusable UI components. The skills/prototype/SKILL.md defines the goals and acceptance criteria, while skills/prototype/RECIPES.md contains the actual CSS implementation patterns.

Implementing Modal Entry with Custom Easing CSS

The pattern demonstrated in skills/prototype/RECIPES.md uses CSS custom properties to expose animation curves, enabling designers to experiment without modifying core logic.

The Custom Easing Variable

The --modal-easing CSS variable stores the cubic-bezier curve that controls the animation's acceleration. The prototype recommends cubic-bezier(0.22, 1, 0.36, 1) for a snappy "ease-out-back" feel, though any valid timing function can be substituted.

Declarative State Management

Instead of toggling classes via JavaScript, the modal uses a data-open attribute to manage visibility states. This approach keeps the component stateless and easily testable, with transitions triggered automatically when the attribute changes between "true" and "false".

Accessibility Considerations

The implementation toggles aria-hidden in sync with the data-open attribute, ensuring screen readers respect the modal's visibility state. This satisfies the basic accessibility checks defined in skills/review-animations/STANDARDS.md.

Complete CSS Modal Example

The following self-contained example from skills/prototype/RECIPES.md demonstrates the full pattern:

<!-- Modal markup (can be placed anywhere) -->
<div class="modal" data-open="false" aria-hidden="true">
  <div class="modal__content">
    <button class="modal__close" aria-label="Close">&times;</button>
    <h2>Modal title</h2>
    <p>Here is some content inside the modal.</p>
  </div>
</div>

<style>
  /* Base styling */
  .modal {
    position: fixed;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0,0,0,0.4);
    opacity: 0;
    pointer-events: none;
    transition:
      opacity 0.35s var(--modal-easing, cubic-bezier(0.22, 1, 0.36, 1)),
      transform 0.35s var(--modal-easing, cubic-bezier(0.22, 1, 0.36, 1));
    transform: translateY(20px);
  }

  .modal[data-open="true"] {
    opacity: 1;
    pointer-events: auto;
    transform: translateY(0);
  }

  .modal__content {
    background: #fff;
    padding: 1.5rem;
    border-radius: 0.5rem;
    max-width: 28rem;
    width: 100%;
    box-shadow: 0 0.5rem 1.5rem rgba(0,0,0,0.2);
  }

  .modal__close {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    background: transparent;
    border: none;
    font-size: 1.5rem;
    cursor: pointer;
  }
</style>

<script>
  // Minimal toggle logic – can be replaced by Instagit's UI-controller
  const modal = document.querySelector('.modal');
  const close = modal.querySelector('.modal__close');

  // Example open trigger (could be any button)
  document.querySelector('[data-open-modal]').addEventListener('click', () => {
    modal.dataset.open = 'true';
    modal.setAttribute('aria-hidden', 'false');
  });

  close.addEventListener('click', () => {
    modal.dataset.open = 'false';
    modal.setAttribute('aria-hidden', 'true');
  });
</script>

Performance and Standards Compliance

Maintaining consistent animation quality requires adherence to institutional standards and regular audits.

Animation Audit Checklist

The skills/improve-animations/AUDIT.md file provides a checklist for verifying that custom easings meet performance goals. This ensures that modal animations run at 60fps without triggering layout thrashing or repaints on composite properties.

Review Standards

The skills/review-animations/STANDARDS.md document establishes the styling and animation standards that modal implementations must respect. These guidelines ensure that all motion UI within the Instagit ecosystem maintains consistent timing and accessibility.

Summary

  • The emilkowalski/skills repository stores animation patterns in plain markdown files under the skills/ directory.
  • Modal entry with custom easing is implemented using the --modal-easing CSS variable and cubic-bezier(0.22, 1, 0.36, 1) timing function.
  • Declarative state management via the data-open attribute eliminates complex JavaScript while maintaining accessibility through synchronized aria-hidden toggles.
  • Reference implementations reside in skills/prototype/RECIPES.md and must comply with standards defined in skills/review-animations/STANDARDS.md.

Frequently Asked Questions

How does the --modal-easing custom property work?

The --modal-easing CSS custom property stores a cubic-bezier timing function that gets referenced in the transition property for both opacity and transform. This allows designers to update the animation curve in one location without hunting through multiple CSS rules, and it falls back to cubic-bezier(0.22, 1, 0.36, 1) if the variable is undefined.

Why use data-open attributes instead of CSS classes for modal state?

Using data-open attributes creates a clear separation between styling and state logic, making the component easier to test and debug. This declarative approach aligns with Instagit's philosophy of stateless UI atoms that can be understood by reading the HTML structure alone, without tracing through JavaScript class manipulation.

Where can I find the official Instagit animation standards?

The official standards are documented in skills/review-animations/STANDARDS.md within the emilkowalski/skills repository. This file defines the timing, accessibility requirements, and performance benchmarks that all animations must meet before being accepted into the design system.

What easing curve does the prototype recommend for modal entries?

The prototype skill recommends cubic-bezier(0.22, 1, 0.36, 1) for modal entry animations, as documented in skills/prototype/RECIPES.md. This curve provides a snappy "ease-out-back" feel that quickly brings the modal into view while settling gently into its final position.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →