Kinetics System

Implementing Kinetics

CSS

A lot of motion can be done using CSS alone. Most motion involves the changing of CSS property values, and there’s an API in CSS to facilitate motion, so it’s advisable to think with a “CSS-first” approach to web animations.

  • Pseudo-classes, like `:hover, :focus, :active` enable the possibility of motion in an element in interactive states.
  • You’ll just need JavaScript to add and remove the classes that trigger the motion.
  • Declarative, state-based CSS code is generally easier to read than equivalent imperative approaches in JavaScript.
  • Two CSS approaches: transitions, animations (keyframes):
    • Transitions: best for symmetrical state changes, where the entrance and exit transition mirror each other. Probably the approach you’ll use most. Suitable for UI component state-to-state animation (e.g. sliding, fading). Motion is defined with the transition property.
A cursor hovers over an icon of a small letter ‘i,' triggering a tooltip description bubble to pop up. This pop up disappears when the user hovers off.
  • Animations: best for asymmetrical state changes, where the entrance and exit transitions don’t mirror each other. Usually for more expressive, choreographed, autonomous, multi-property motion (e.g. _click ripple_, spinner). Motion is defined by the @keyframes directive and timed with the animation property.
After a user clicks an an icon button, a dropdown menu appears. They click a second time and the menu fades away.
  • CSS motion can also be more performant than JavaScript motion:
    • JavaScript libraries increase load time.
    • JavaScript always makes use of the main execution thread, which can drag down other more important tasks. CSS doesn’t necessarily have to use this thread.
  • Focus states:
    • Be on the lookout for :focus-visible pseudo-class. Not yet widely supported, but slated to be the preferred :focus state. It’s supposed to only be triggered by keyboard, not mouse. Could help us get the best of both worlds: clean animation without focus ring; clear focus state for keyboard users.
  • Performance:
    • As much as possible, stick to opacity and transform changes only. These are processed in the compositor thread instead of the main thread, helping maintain performance and smoother motion.
    • When providing supplemental animation use SVGs or movie files in order to pause, play or entirely remove offscreen animation to improve performance of the page
    • Minimize motion involving changes to width, height, color, borders, left, right. These are processed in the main thread and reduce performance.
    • When animating size and position of an element, use transform() rather than editing the property value itself.
    • Pseudo-classes allow us to trigger transitions by hooking into some user interaction events, like :hover, :focus, and :active.
    • In case of performance issues, the will-change CSS property can be used. It is a way to tell the browser which properties are likely to be changed. If using the will-change property, use it as a “last resort.” Misuse can actually incur a performance hit. It is also recommended to remove the property after the animation has happened. [More Info]

JavaScript

  • JavaScript is necessary for when you need to programmatically control motion playback or listen for motion events.
  • Define your motion in CSS class, or attribute, selectors, and use JavaScript to add and remove those classes or attributes. With Custom Web Components, the attributeChangedCallback can be used with handlers for AnimationEnd or TransitionEnd events to start, stop and sequence events.
  • Variables can be communicated back and forth with CSS via CSS custom properties (Styling Hooks).
  • Avoid using JavaScript for directly animating element properties.
  • Consider using promised-based delays to sequence animations.
const delay = duration =>
  new Promise(resolve => {
    setTimeout(() => {
    resolve();
  }, duration);
});

const step1 = async (duration) => {
  element.classList.add("step-1");
  await delay(duration);
};

const step2 = async (duration) => {
  element.classList.add("step-2");
  await delay(duration);
};

const transition = async () => {
  await step1(300);
  await step2(250);
};

transition();
  • emphasized effects like bouncing.
Bouncing movement as seen in an Error Toast as it animates into screen from the top of the page

Other implementation methods

There are intuitive APIs and libraries that harness power of JS with less effort. Browser compatibility is usually built-in, but library adoption biases SLDS. It is recommended to integrate the code you with which you animate with the rest of your component code. Here are some technologies for implementing motion into your web experience. Although they may be limited and/or more rigid in their ability to integrate in a component, they may offer quicker means to a visual result if animation is at the focus of your experience.

Web Animations API (WAAPI)

  • Enables timeline sequencing
  • Native, no external library load
  • Allows for SLDS to remain library-agnostic
  • Browser support gaps necessitate polyfills
  • GreenSock (GSAP)

  • Intuitive timeline sequencing
  • Plugins library for more complex animation
  • Comprehensive and a large download, although runtime performant.
  • Existing usage in Salesforce platform, although not systemized in SLDS.
  • Lottie

  • Potential for one-off, contained, aesthetically-functional animations that would otherwise be inefficient to animate in code or WAAPI.
  • Paired with Bodymovin plugin, allows certain kinds of animations created with tools like Adobe After Effects to be converted to playable motion assets in web, iOS, and Android apps.
  • Think of these as motion video assets, not UI transitions. Best for intricate motion pieces used sparingly in specific views. For example, emphasized animation in onboarding
  • Programmatic playback control using JavaScript.
  • Understand the limits of Lottie before taking this approach. Not all animations will work with Lottie.
  • Kinetics Styling Hook Values

    Note: Use these values as a reference to build your animations. These values will be available as styling hooks in the future.

    Duration

    --kx-duration-xshort75ms
    --kx-duration-short150ms
    --kx-duration-normal250ms
    --kx-duration-long400ms
    --kx-duration-xlong600ms

    Acceleration

    --kx-ease-nonecubic-bezier(0, 0, 1, 1)
    --kx-ease-incubic-bezier(0.3, 0, 1, 0.3)
    --kx-ease-outcubic-bezier(0, 0.3, 0.15, 1)
    --kx-ease-in-outcubic-bezier(0.3, 0, 0.15, 1)
    --kx-ease-undercubic-bezier(0.7, 0, 0.7, -0.75)
    --kx-ease-overcubic-bezier(0.3, 1.75, 0.3, 1)
    --kx-ease-under-overcubic-bezier(0.7, -0.4, 0.4, 1.4)

    Pattern Styling

    --kx-ease-ripplecubic-bezier(.35,.01,.62,.99)