diff --git a/source/_meta/_01-foot.twig b/source/_meta/_01-foot.twig
index 27aa0c5a625da770ab3cc46b81b8d6dce81badb9..5c3ea1ee72d08a83cc94044bc1c40dac592e5ad4 100644
--- a/source/_meta/_01-foot.twig
+++ b/source/_meta/_01-foot.twig
@@ -13,6 +13,7 @@
     <script src="../../../js/dist/scripts.min.js?{{ cacheBuster }}"></script>
     <script src="https://cdnjs.cloudflare.com/ajax/libs/OwlCarousel2/2.3.4/owl.carousel.min.js?{{ cacheBuster }}"></script>
     <script src="../../../../js/component_scripts.min.js"></script>
+    <script src="../../../source/_patterns/04-components/whos-online/whos-online.js?{{ cacheBuster }}"></script>
 
     <!--DO NOT REMOVE-->
     {{ patternLabFoot | raw }}
diff --git a/source/_patterns/04-components/whos-online/_whos-online.scss b/source/_patterns/04-components/whos-online/_whos-online.scss
new file mode 100644
index 0000000000000000000000000000000000000000..9d9a8679ea04b915b24cfe6fecba178fba4d9a89
--- /dev/null
+++ b/source/_patterns/04-components/whos-online/_whos-online.scss
@@ -0,0 +1,32 @@
+.uw-whos-online-block {
+  h3 {
+    font-size: 15px;
+    margin: 0 0 0 -5px;
+  }
+
+  span {
+    display: inline;
+
+    &:last-child {
+      display: inline;
+      font-size: 80%;
+      font-weight: bold;
+    }
+  }
+
+  button {
+    background: none;
+    border: 0;
+    color: inherit;
+    cursor: pointer;
+    font-family: inherit;
+    font-size: inherit;
+    margin: 0;
+    padding: 0;
+
+    &:focus {
+      border-bottom: 1px dotted #000;
+      margin-bottom: -1px;
+    }
+  }
+}
diff --git a/source/_patterns/04-components/whos-online/whos-online.js b/source/_patterns/04-components/whos-online/whos-online.js
new file mode 100644
index 0000000000000000000000000000000000000000..7422361278cdca82ced50b9fa74558591d279721
--- /dev/null
+++ b/source/_patterns/04-components/whos-online/whos-online.js
@@ -0,0 +1,29 @@
+(function($) {
+  Drupal.behaviors.responsive_menu_combined = {
+    attach: function (context, settings) {
+      'use strict';
+
+      // Close "other users" by default.
+      $('.uw_other h3 span:first-child').html('&#9656;');
+      $('.uw_other ul').hide();
+      // Since we're making the headers visible, wrap them in a button.
+      $('.uw-whos-online-block h3').wrapInner('<button></button>');
+      // Add appropriate ARIA attributes for default states.
+      $('.uw_privileged button').attr('aria-expanded', 'true');
+      $('.uw_other button').attr('aria-expanded', 'false');
+      // Handle show/hide.
+      $('.uw-whos-online-block button').on('click', function() {
+        let $list = $(this).closest('div').find('ul');
+        if ($list.is(":visible")) {
+          $list.hide();
+          $('span:first-child',this).html('&#9656;');
+          $(this).attr('aria-expanded', 'false');
+        } else {
+          $list.show();
+          $('span:first-child',this).html('&#9662;');
+          $(this).attr('aria-expanded', 'true');
+        }
+      });
+    }
+  };
+})(jQuery);
diff --git a/source/_patterns/04-components/whos-online/whos-online.md b/source/_patterns/04-components/whos-online/whos-online.md
new file mode 100644
index 0000000000000000000000000000000000000000..8969780cf8984b95cc6ef1420b60ea5e86900fcb
--- /dev/null
+++ b/source/_patterns/04-components/whos-online/whos-online.md
@@ -0,0 +1,8 @@
+---
+el: .whos-online
+title: Who's online
+---
+
+__Variables:__
+* privileged [list] List of users with privileged roles.
+* others [list] List of users with all other roles.
diff --git a/source/_patterns/04-components/whos-online/whos-online.twig b/source/_patterns/04-components/whos-online/whos-online.twig
new file mode 100644
index 0000000000000000000000000000000000000000..747809e086e1c8108eee3874e80234b07a8c697f
--- /dev/null
+++ b/source/_patterns/04-components/whos-online/whos-online.twig
@@ -0,0 +1,30 @@
+<div class="uw-whos-online-block">
+  {% if privileged or others %}
+    <div class="uw_privileged">
+      <h3><span>&#9662;</span> Privileged users <span>({{ privileged|length }})</span></h3>
+      <ul>
+        {% if privileged %}
+          {% for name in privileged %}
+            <li>{{ name }}</li>
+          {% endfor %}
+        {% else %}
+          {{ 'No online users.'|t }}
+        {% endif %}
+      </ul>
+    </div>
+    <div class="uw_other">
+      <h3><span>&#9662;</span> Other users <span>({{ others|length }})</span></h3>
+      <ul>
+        {% if others %}
+          {% for name in others %}
+            <li>{{ name }}</li>
+          {% endfor %}
+        {% else %}
+          <li>None</li>
+        {% endif %}
+      </ul>
+    </div>
+  {% else %}
+    {{ 'No online users.'|t }}
+  {% endif %}
+</div>
diff --git a/source/_patterns/04-components/whos-online/whos-online.yml b/source/_patterns/04-components/whos-online/whos-online.yml
new file mode 100644
index 0000000000000000000000000000000000000000..e615bbd742064a3f59bef18cae38d13cbb012a30
--- /dev/null
+++ b/source/_patterns/04-components/whos-online/whos-online.yml
@@ -0,0 +1,6 @@
+privileged:
+  - user1
+  - user3
+
+others:
+  - user2