Skip to content

Slide Activator

<quiet-slide-activator> stable since 1.0

Slide activators give users a draggable thumb that must be moved to the end of its track to trigger an action.

Slide activators are unidirectional. Once activated by the user, they can only be reset programmatically. The deliberate friction in activation, followed by a locked state, helps prevent accidental triggering and ensures intentional actions are committed.

<quiet-slide-activator 
  label="Slide to activate" 
  attention="shimmer" 
  id="slide-activator__overview" 
  style="max-width: 340px;"
></quiet-slide-activator>

<script>
  const slideActivator = document.getElementById('slide-activator__overview');
  const originalLabel = slideActivator.getAttribute('label');

  // When the component is activated
  slideActivator.addEventListener('quiet-activated', () => {
    // Update the label
    slideActivator.label = 'Activated';

    // Deactivate it for the demo after two seconds
    setTimeout(() => {
      slideActivator.activated = false;
      slideActivator.label = originalLabel;
    }, 2000);
  });
</script>

For demonstration purposes, most of the examples on this page reset themselves shortly after activation.

Examples Jump to heading

Handling activation Jump to heading

When the control is activated, a quiet-activate event will be emitted. You can call event.preventDefault() to prevent the activation if needed. Upon activation, a subsequent quiet-activated event will be emitted.

If you deactivate the control programmatically, a corresponding quiet-deactivate and quiet-deactivated event will be emitted.

You can use these events to update labels and execute code to run on activation and deactivation.

Deactivate
<div id="slide-activator__activation">
  <quiet-slide-activator label="Slide to activate"></quiet-slide-activator>
  <quiet-button disabled>Deactivate</quiet-button>
</div>

<script>
const container = document.getElementById('slide-activator__activation');
const slideActivator = container.querySelector('quiet-slide-activator');
const button = container.querySelector('quiet-button');
const originalLabel = slideActivator.getAttribute('label');

// Deactivate it
button.addEventListener('click', () => {
  slideActivator.activated = false;
});

// Update the label and button state when activated
slideActivator.addEventListener('quiet-activated', () => {
  button.disabled = false;
  slideActivator.label = 'Activated';
});

// Update the label and button state when deactivated
slideActivator.addEventListener('quiet-deactivated', () => {
  button.disabled = true;
  slideActivator.label = originalLabel;
});
</script>

<style>
  #slide-activator__activation {
    quiet-slide-activator {
      max-width: 340px;
      margin-bottom: 1rem; 
    }
  }
</style>

Tracking slide progress Jump to heading

The readonly --thumb-position custom property will be set to a value between 0 and 1 on the host element, representing how far the user has slid the thumb toward activation. You can use this to transition styles at different thresholds.

Additionally, a quiet-progress event will be emitted while the user slides the thumb. This event contains an event.detail.percent payload with a corresponding number between 0 and 1.

Progress:
<div id="slide-activator__progress">
  <quiet-slide-activator label="Slide to place order"></quiet-slide-activator>
  Progress: <quiet-number number="0" type="percent"></quiet-number>
</div>

<script>
  const container = document.getElementById('slide-activator__progress');
  const slideActivator = container.querySelector('quiet-slide-activator');
  const originalLabel = slideActivator.getAttribute('label');
  const progress = container.querySelector('quiet-number');

  // Update progress as the user drags
  slideActivator.addEventListener('quiet-progress', event => {
    progress.number = event.detail.percent;
  });

  // Update the label and reset the demo when component is activated
  slideActivator.addEventListener('quiet-activated', () => {
    // Update the label
    slideActivator.label = 'Order received!';

    // Deactivate it for the demo after two seconds
    setTimeout(() => {
      slideActivator.activated = false;
      slideActivator.label = originalLabel;
    }, 2000);
  });
</script>

<style>
  #slide-activator__progress {
    quiet-slide-activator {
      max-width: 340px;
      margin-bottom: 1rem;

      /* Change the background color as the user slides the thumb */
      background-color: 
        color-mix(
          in oklab, 
          var(--quiet-neutral-fill-soft) calc((1 - var(--thumb-position)) * 100%), 
          var(--quiet-primary-fill-mid) calc(var(--thumb-position) * 100%)
        );

      /* Change the text color when activated */
      &:state(activated) {
        color: var(--quiet-primary-text-on-mid);
      }
    }
  }
</style>

Customizing icons Jump to heading

Use the thumb slot to provide your own icon(s) for the thumb. If you want to change the icon depending on the activation state, use the :state(activated) selector to show/hide the respective icons with CSS.

<quiet-slide-activator 
  label="Slide to unlock" 
  id="slide-activator__icons"
>
  <quiet-icon slot="thumb" name="lock"></quiet-icon>
  <quiet-icon slot="thumb" name="lock-open-2"></quiet-icon>
</quiet-slide-activator>

<script>
  const slideActivator = document.getElementById('slide-activator__icons');
  const originalLabel = slideActivator.getAttribute('label');

  // When the component is activated
  slideActivator.addEventListener('quiet-activated', () => {
    // Update the label
    slideActivator.label = 'Unlocked';

    // Deactivate it for the demo after two seconds
    setTimeout(() => {
      slideActivator.activated = false;
      slideActivator.label = originalLabel;
    }, 2000);
  });
</script>

<style>
  quiet-slide-activator#slide-activator__icons {
    max-width: 340px;

    /* Show locked until activated, then show unlocked */
    &:state(activated) quiet-icon[name="lock"],
    &:not(:state(activated)) quiet-icon[name="lock-open-2"] {
      display: none;
    }
  }
</style>

Drawing attention Jump to heading

Set the attention attribute to shimmer to provide a subtle visual hint via animation. The animation pauses when the slide activator is activated.

<quiet-slide-activator 
  label="Slide to release cats" 
  attention="shimmer" 
  id="slide-activator__attention" 
>
  <quiet-icon slot="thumb" name="cat"></quiet-icon>
</quiet-slide-activator>

<script>
  const slideActivator = document.getElementById('slide-activator__attention');
  const originalLabel = slideActivator.getAttribute('label');

  // When the component is activated
  slideActivator.addEventListener('quiet-activated', () => {
    // Update the label
    slideActivator.label = 'Releasing cats…';

    // Deactivate it for the demo after two seconds
    setTimeout(() => {
      slideActivator.activated = false;
      slideActivator.label = originalLabel;
    }, 2000);
  });
</script>

<style>
  quiet-slide-activator#slide-activator__attention {
    max-width: 340px;

    /* Head tilt*/
    quiet-icon {
      transition: 300ms rotate ease-out;
    }

    &:state(activated) quiet-icon {
      rotate: 20deg;
    }
  }
</style>

Disabling Jump to heading

Use the disabled attribute to disable the slide activator. The control cannot be activated or focused while disabled.

<quiet-slide-activator 
  label="Slide to activate" 
  disabled 
  style="max-width: 340px;"
></quiet-slide-activator>

Styling slide activators Jump to heading

Slide activators come with a simple, minimal appearance. Feel free to customize them with your own styles, icons, and animations.

<quiet-slide-activator 
  label="Empty the litter box" 
  attention="shimmer" 
  id="slide-activator__styling"
>
  <quiet-icon slot="thumb" name="arrow-right"></quiet-icon>
  <quiet-spinner slot="thumb"></quiet-spinner>
</quiet-slide-activator>

<script>
  const slideActivator = document.getElementById('slide-activator__styling');
  const originalLabel = slideActivator.getAttribute('label');

  // When the component is activated
  slideActivator.addEventListener('quiet-activated', () => {
    // Update the label
    slideActivator.label = 'Emptying…';

    // Deactivate it for the demo after two seconds
    setTimeout(() => {
      slideActivator.activated = false;
      slideActivator.label = originalLabel;
    }, 2000);
  });
</script>

<style>
  quiet-slide-activator#slide-activator__styling {
    --border-radius: 0.5rem;
    --thumb-width: 4rem;
    --thumb-inset: 0.25rem;
    --shimmer-color: #fff2;
    --current-color: 
      color-mix(
        in oklab, 
        firebrick calc(var(--thumb-position) * 100%), 
        #0284c7 calc((1 - var(--thumb-position)) * 100%)
      );
    height: 4rem;
    max-width: 340px;
    background-color: var(--current-color);
    font-weight: var(--quiet-font-weight-semibold);
    color: white;
    
    &:focus-within {
      outline-color: var(--current-color) !important;
    }

    /* Animate when activated */
    &:state(activated) {
      animation: pulse 0.6s ease-out forwards;
    }

    /* Slightly bigger icons */
    quiet-icon {
      font-size: 1.5rem;
    }

    quiet-spinner {
      --indicator-color: firebrick;
      --track-color: color-mix(in oklab, firebrick, transparent 80%);
    }

    /* Show arrow icon until activated, then show trash */
    &:state(activated) quiet-icon[name="arrow-right"],
    &:not(:state(activated)) quiet-spinner {
      display: none;
    }

    /* Bounce animation for fun */
    quiet-icon[name="arrow-right"] {
      animation: bounce-right 1s infinite;

      /* Flip for RTL */
      &:dir(rtl) {
        scale: -1;
      }
    }  
  }

  @keyframes bounce-right {
    0%, 100% {
      transform: translateX(0);
    }
    50% {
      transform: translateX(6px);
    }
  }

  @keyframes pulse {
    0% {
      transform: scale(1);
      filter: brightness(1);
    }
    20% {
      transform: scale(1.05);
      filter: brightness(1.2);
    }
    40% {
      transform: scale(0.95);
      filter: brightness(0.9);
    }
    60% {
      transform: scale(1.02);
      filter: brightness(1.1);
    }
    80% {
      transform: scale(0.98);
      filter: brightness(0.95);
    }
    100% {
      transform: scale(1);
      filter: brightness(1);
    }
  }
</style>

API Jump to heading

Importing Jump to heading

The autoloader is the recommended way to import components but, if you prefer to do it manually, the following code snippets will be helpful.

CDN npm

To manually import <quiet-slide-activator> from the CDN, use the following code.

import 'https://cdn.jsdelivr.net/npm/@quietui/quiet@1.0.0/dist/components/slide-activator/slide-activator.js';

To manually import <quiet-slide-activator> from npm, use the following code.

import '@quietui/quiet/dist/components/slide-activator/slide-activator.js';

Slots Jump to heading

Slide Activator supports the following slots. Learn more about using slots

Name Description
label The slide activator's label. For plain-text labels, you can use the label attribute instead.
thumb The thumb element that users drag. Defaults to a double chevron icon if not provided.

Properties Jump to heading

Slide Activator has the following properties that can be set with corresponding attributes. In many cases, the attribute's name is the same as the property's name. If an attribute is different, it will be displayed after the property. Learn more about attributes and properties

Property / Attribute Description Reflects Type Default
label The label to show in the slide activator's track. If you need to provide HTML in the label, use the label slot instead. string ''
activated Reflects when the control is activated. Remove this attribute to deactivate it. boolean false
disabled Disables the control. boolean false
attention Draws attention to the track by adding a subtle animation. 'shimmer'

Events Jump to heading

Slide Activator dispatches the following custom events. You can listen to them the same way was native events. Learn more about custom events

Name Description
quiet-activate Emitted when the control will activate. Calling event.preventDefault() will prevent the activation from occurring.
quiet-activated Emitted immediately after the control is activated.
quiet-deactivate Emitted when the control will deactivate. Calling event.preventDefault() will prevent the deactivation from occurring.
quiet-deactivated Emitted immediately after the control is deactivated.

CSS custom properties Jump to heading

Slide Activator supports the following CSS custom properties. You can style them like any other CSS property. Learn more about CSS custom properties

Name Description Default
--border-radius The control's border radius. We use a CSS custom property so we can properly calculate the inset border radius for the thumb. 9999px
--thumb-width The thumb's width. 4em
--thumb-inset The thumb's inset from the host element. 0.125em
--shimmer-color The color to use as a base for the shimmer animation.
--thumb-position A read-only property that moves from 0 to 1 as the user slides the thumb to activate the control. Useful as a hook to transition background styles based on the thumb's position. (read-only)

CSS parts Jump to heading

Slide Activator exposes internal elements that can be styled with CSS using the selectors shown below. Learn more about CSS parts

Name Description CSS selector
thumb The slide activator's thumb. ::part(thumb)
label The slide activator's label. ::part(label)

Custom States Jump to heading

Slide Activator has the following custom states. You can target them with CSS using the selectors shown below. Learn more about custom states

Name Description CSS selector
activated Applied briefly when the slide activator has been activated. :state(activated)
dragging Applied when the slide activator is dragging. :state(dragging)
pressing Applied when the user is pressing a key to activate the slide activator. :state(pressing)
disabled Applied when the slide activator is disabled. :state(disabled)

Dependencies Jump to heading

Slide Activator automatically imports the following elements. Sub-dependencies are also included in this list.

Search this website Toggle dark mode Get the code on GitHub Follow @quietui.org on Bluesky Follow @quiet_ui on X
    No results found