Drawer

Drawer Figma Code Connected

The Drawer component is an off-screen content container that slides in from the right when needed. Similar to a modal it provides a focused panel, in this case for the user to open additional controls or filters.

Default drawer

To set up a drawer, create an element with class .hc-drawer. Inside, add a checkbox with class .hc-drawer-toggle and then an element with class .hc-drawer-content that contains the content of the drawer.

This default drawer will fill whatever block-level element it’s inside of and will not have a fixed position to it by default. You can modify this later.

This is where all of the main content goes.

This is the right side drawer.

Note that by default, the content behind the drawer is not accessible while the drawer is open. This can be modified with a class.


<div class="w-full h-full flex flex-col items-center justify-center gap-4">
  <p>
    This is where all of the main content goes.
  </p>
  <label class="hc-button hc-button--primary cursor-pointer" for="drawer_basic" role="button" tabindex="0">
    Open a basic drawer
  </label>
</div>
<div class="hc-drawer">
  <input id="drawer_basic" type="checkbox" class="hc-drawer-toggle" />
  <div class="hc-drawer-content">
    <div class="hc-drawer-content-body">
      <p class="hc-body">
        This is the right side drawer.
      </p>
      <p class="hc-body">
        Note that by default, the content behind the drawer is not accessible while the drawer is open. This can be modified with a class.
      </p>
      <label class="hc-button hc-button--primary cursor-pointer" for="drawer_basic">
        Close the drawer
      </label>
    </div>
  </div>
</div>

No matter where it is or how it’s used, the drawer itself must be inside of an element that has position: relative applied to it.

Label used to toggle the drawer

Toggling the drawer is handled by a <label> that has a corresponding for value for the checkbox inside the drawer. This is the default non-JS method of toggling a drawer but you’re free to use any accessible method to do this, JS or not.

Accessibility note

If using the documented label method, in order for the label (acting as a button) to receive a focus state, add role="button" and tabindex="0" to it.

Header and Footer

While options, headers should be present on all drawers and should include the close button. Create a header by adding a header element with class hc-drawer-content-title. The title should use an <h3> and the close “button” (taking advantage of the checkbox) is provided below.

Footers are optional but provide a great space for a CTA or application button. Footers will stick to the bottom of the drawer; long content in the drawer body will scroll inside of itself and not push the footer down.

Application body behind the drawer.

Drawer title

This is the drawer content section.

If this content is long, it will scroll without touching the position of the fixed header and footer.

We're going to make this content very long and move the CTA to the footer, which will stick to the bottom of the drawer if this content was not sufficiently long enough to push the footer there naturally. More words.


<div class="w-full h-full flex flex-col items-center justify-center gap-4">
  <p>
    Application body behind the drawer.
  </p>
  <label class="hc-button hc-button--primary cursor-pointer" for="drawer_full" role="button" tabindex="0">
    Open a full drawer
  </label>
</div>
<div class="hc-drawer">
  <input id="drawer_full" type="checkbox" class="hc-drawer-toggle" />
  <div class="hc-drawer-content">
    <header class="hc-drawer-content-title">
      <h3 class="hc-h3">Drawer title</h3>
      <label class="hc-button hc-button--primary" aria-label="Close drawer" for="drawer_full">
        <i class="hc-icon hc-icon--close hc-icon--20"></i>
      </label>
    </header>
    <div class="hc-drawer-content-body">
      <p class="hc-body">
        This is the drawer content section.
      </p>
      <p class="hc-body">
        If this content is long, it will scroll without touching the position of the fixed header and footer.
      </p>
      <p class="hc-body">
        We're going to make this content very long and move the CTA to the footer, which will stick to the bottom of the drawer if this content was not sufficiently long enough to push the footer there naturally. More words.
      </p>
    </div>
    <footer class="hc-drawer-content-footer">
      <div class="hc-drawer-content-footer-left">
        Footer content
      </div>
      <div class="hc-drawer-content-footer-right">
        <label class="hc-button hc-button--primary hc-button--success cursor-pointer" for="drawer_full">
          Close the drawer
        </label>
      </div>
    </footer>
  </div>
</div>

App drawers

To create a drawer that fills the entire content panel inside of an app and has a fixed position, place the .hc-drawer element at the end of the .hc-app-main container if you’re using the Layout framework. You can also give the drawer the class .hc-drawer--in-main if it needs to sit outside of this element or if you’re not using that framework.

You can use the <aside> element for this. If you do, add the attribute aria-label="Right drawer" or some other more descriptive label for what the drawer contains.

Take a look at the full page layout demo to see this live.

Allow access to background content

By default, the content that sits behind the drawer (i.e., the main page content/scrollable area) will not be accessible to the user while the drawer is open.

To prevent this default, append the class .hc-drawer--allow-bg to the drawer parent element and the user will be able to interact with the main page content.

Mobile handling

Drawers slide in from the right and take up 1/3 of the screen width, with a minimum width of 24rem.

On small screens (up to the md breakpoint) the drawer will instead pull up from the bottom of the screen. This is handled by default and will also occur if you’re using the Layout’s grid container on main content sections that are smaller than 512px.

Test this drawer out when this content window is less than 32rem wide.

Mobile drawer example

On small screens this will slide up from the bottom.

On larger screens this will slide in from the right.

Adding a ton of breaks here to see what happens when the content is forced to scroll.













<div class="w-full h-full flex flex-col items-center justify-center gap-4">
  <p class="text-center">
    Test this drawer out when this content window is less than 32rem wide.
  </p>
  <label class="hc-button hc-button--primary cursor-pointer" for="drawer_mobile" role="button" tabindex="0">
    Open a basic drawer
  </label>
</div>
<div class="hc-drawer">
  <input id="drawer_mobile" type="checkbox" class="hc-drawer-toggle" />
  <div class="hc-drawer-content">
    <div class="hc-drawer-content-title">
      <h3 class="hc-h3">
        Mobile drawer example
      </h3>
      <label class="hc-button hc-button--primary cursor-pointer" aria-label="Close drawer" for="drawer_mobile">
        <i class="hc-icon hc-icon--close hc-icon--20"></i>
      </label>
    </div>
    <div class="hc-drawer-content-body">
      <p class="hc-body">
        On small screens this will slide up from the bottom.
      </p>
      <p class="hc-body">
        On larger screens this will slide in from the right.
      </p>
      <p class="hc-body">
        Adding a ton of breaks here to see what happens when the content is forced to scroll.
        <br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />
      </p>
    </div>
  </div>
</div>