Skip to content

Veil

<quiet-veil> stable since 1.0

Veils are used to cover elements visually and disable interaction during important states such as loading.

Submit
Activated
<div id="veil__overview">
  <quiet-veil active>
    <quiet-card>
      <form>
        <quiet-text-field label="Name" name="name" placeholder="Meowy McGee"></quiet-text-field>
        <quiet-text-area label="Feedback" name="feedback" placeholder="Tell us about your experience!"></quiet-text-area>
        <quiet-button type="submit" variant="primary">Submit</quiet-button>
      </form>
    </quiet-card>
  </quiet-veil>

  <quiet-button toggle="on">Activated</quiet-button>
</div>

<style>
  #veil__overview {
    quiet-veil {
      max-width: 360px;
      margin-block-end: 2rem;
    }

    form {
      display: flex;
      flex-direction: column;
      gap: 1.5rem;
    }
  }
</style>

<script>
  const container = document.getElementById('veil__overview');
  const veil = container.querySelector('quiet-veil');
  const form = container.querySelector('form');
  const activateButton = container.querySelector('quiet-button[toggle]');

  form.addEventListener('submit', event => event.preventDefault());

  activateButton.addEventListener('click', () => {
    veil.active = activateButton.toggle === 'on';
  });
</script>

Examples Jump to heading

Controlling the veil Jump to heading

Veils are designed to wrap block-level content or cover the entire screen. They are invisible and remain dormant until you activate them. When a veil is activated, it will show its front slot and everything inside of it will become inert until deactivated.

To activate a veil, set the active property to true. To deactivate a veil, set the active property to false.

<quiet-veil>
  <!-- Content to cover -->
</quiet-veil>

<script>
  // Obtain a reference
  const veil = document.querySelector('quiet-veil');

  // ...

  async function doSomething() {
    // Show the veil
    veil.active = true;

    // Do something, like post to the server
    await fetch('...');

    // Hide the veil
    veil.active = false;
  }
</script>

Fullscreen Jump to heading

To cover the entire viewport, add the fullscreen attribute. Under the hood, a modal dialog is used to ensure the rest of the document is inert until the veil is deactivated.

Try it for two seconds
<div id="veil__fullscreen">
  <quiet-veil fullscreen></quiet-veil>
  <quiet-button variant="primary">Try it for two seconds</quiet-button>
</div>

<script>
  const container = document.getElementById('veil__fullscreen');
  const veil = container.querySelector('quiet-veil');
  const button = container.querySelector('quiet-button');
  
  button.addEventListener('click', () => {
    // Show the veil
    veil.active = true;

    // Simulate an async operation, then hide it
    setTimeout(() => veil.active = false, 2000);
  });
</script>

Customizing the content Jump to heading

You can customize the content that appears in front of the veil using the front slot. This example shows a progress ring to reflect its progress while simulating an async save operation.

For details, please visit our website. Rate
Updating…
<div id="veil__progress">
  <quiet-veil>
    <!-- Content to cover -->
    <quiet-card>
      <form>
        <quiet-rating name="name" label="How would you rate our catnip?">
          <span slot="description">
            For details, please <a href="https://example.com/" target="_blank">visit our website</a>.
          </span>
        </quiet-rating>
        <quiet-button type="submit" variant="primary">Rate</quiet-button>
      </form>
    </quiet-card>

    <!-- Content in the front -->
    <quiet-progress slot="front" appearance="ring" label="Progress">
      <span class="message">Updating…</span>
      <quiet-icon name="check"></quiet-icon>
    </quiet-progress>
  </quiet-veil>
</div>

<script>
  const container = document.getElementById('veil__progress');
  const veil = container.querySelector('quiet-veil');
  const progress = container.querySelector('quiet-progress');
  const saveButton = container.querySelector('quiet-button');
  const form = container.querySelector('form');

  form.addEventListener('submit', event => {
    event.preventDefault();

    // Set the initial state
    progress.value = 0;
    veil.classList.remove('saved');
    veil.active = true;

    // Simulate a long running async task
    const interval = setInterval(() => {
      progress.value += 5;
      
      // Show saved state when it reaches 100%
      if (progress.value >= 100) {
        clearInterval(interval);

        veil.classList.add('saved');

        // Automatically dismiss after a moment
        setTimeout(() => veil.active = false, 1000);
      }
    }, 50);
  });
</script>

<style>
  #veil__progress {
    quiet-veil {
      max-width: 360px;

      &.saved {    
        quiet-progress {    
          --indicator-color: var(--quiet-constructive-fill-mid);
        }

        quiet-icon[name="check"] {
          color: var(--quiet-constructive-fill-mid);
        }

        .message {
          display: none;
        }
      }

      &:not(.saved) {
        quiet-icon[name="check"] {
          display: none;
        }
      }
    }

    form {
      display: flex;
      flex-direction: column;
      gap: 1.5rem;
    }

    quiet-progress {
      --track-size: .5rem;
      --track-color: #0002;
      max-width: 300px;

      quiet-icon {
        font-size: 5rem;
        stroke-width: .15rem;
        color: var(--quiet-primary-fill-mid);
      }
    }

    .message {
      font-size: 1rem;
      color: var(--quiet-text-muted);
    }
  }
</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-veil> from the CDN, use the following code.

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

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

import '@quietui/quiet/dist/components/veil/veil.js';

Slots Jump to heading

Veil supports the following slots. Learn more about using slots

Name Description
(default) The content to be covered when the veil state is active.
front Content to show in front of the veil, such as a custom loading indicator or message.

Properties Jump to heading

Veil 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 for screen readers when veil is active. string ''
active Description of the property. boolean false
fullscreen Set to true to show the veil over the entire viewport instead of the content inside of it. boolean false

Events Jump to heading

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

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

CSS custom properties Jump to heading

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

Name Description Default
--blur The amount of blur to apply to the veil when active. 3px
--show-duration The duration of the show/hide animation. 300

Custom States Jump to heading

Veil 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
active Applied when the veil is active. :state(active)

Dependencies Jump to heading

Veil 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