homepage

Brown Markup Library

Tab Switcher

Change the content presented based on the tab button selected.

Rendered Component

Displaying content for Brown Community

content one

HTML

<div>
    <div role="tablist" aria-label="file generation tools">
        <button
            aria-controls="tabpanel-1"
            aria-selected="true"
            class="tab-button"
            id="tab-1"
            onclick="onButtonPress(1)"
            role="tab"
            type="button"
            >Community</button>
        <button
            aria-controls="tabpanel-2"
            aria-selected="false"
            class="tab-button"
            id="tab-2"
            onclick="onButtonPress(2)"
            role="tab"
            type="button"
            >Users</button>
        <button
            aria-controls="tabpanel-3"
            aria-selected="false"
            class="tab-button"
            id="tab-3"
            onclick="onButtonPress(3)"
            role="tab"
            type="button"
            >Groups</button>
    </div>
    <p class="screen_reader_text" aria-live="polite" id="content-update">Displaying content for Brown Community</p>
    <div
        aria-labelledby="tab-1"
        class="content-panel"
        id="tabpanel-1"
        role="tabpanel"
        style=""
        tabIndex="0"
        >
        <p>content one</p>
    </div>
    <div
        aria-labelledby="tab-2"
        class="content-panel"
        id="tabpanel-2"
        role="tabpanel"
        style="display:none;"
        tabIndex="-1"
        >
        <p>content two</p>
    </div>
    <div
        aria-labelledby="tab-3"
        class="content-panel"
        id="tabpanel-3"
        role="tabpanel"
        style="display:none;"
        tabIndex="-1"
        >
        <p>content three</p>
    </div>
<div>

CSS

.content-panel {
    padding: 2rem;
    border: 1px solid #b7b09c;
    display: flex;
    flex-direction: column;
    margin-top: 1rem;
}
.screen_reader_text {
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    height: 1px;
    overflow: hidden;
    position: absolute;
    white-space: nowrap;
    width: 1px;
}
.tab-button {
    background: transparent;
    border: 0;
    display: inline-block;
    font-size: 0.9375rem;
    font-weight: 700;
    padding: 1.25rem;
    position: relative;
    text-align: center;
    width: auto;
    vertical-align: middle;
}
.tab-button:before {
    border: 6px solid transparent;
    border-top-color: #c00404;
    content: "";
    left: 45%;
    margin-top: 6px;
    opacity: 0;
    position: absolute;
    top: 100%;
    transform: translate(0, -50%);
}
.tab-button:after {
    background: inherit;
    border: 1px solid #b7b09c;
    border-color: #b7b09c;
    bottom: 0;
    content: "";
    display: block;
    height: 6px;
    left: 0;
    position: absolute;
    width: 100%;
}
.tab-button[aria-selected="true"]:before {
    opacity: 1;
}
.tab-button[aria-selected="true"]:after {
    background: #c00404;
    border: 1px solid #c00404;
    border-color: #c00404;
}
@media screen and (prefers-reduced-motion: no-preference) {
    .tab-button:before {
        transition: opacity 0.25s;
    }
}

JS

function onButtonPress(number) {
  const tabButtons = [...document.getElementsByClassName("tab-button")];
  const contentUpdate = document.getElementById("content-update");
  const panels = [...document.getElementsByClassName("content-panel")];
  tabButtons.forEach((button) => {
    if (button.id === `tab-${number}`) {
      button.setAttribute("aria-selected", "true");
      contentUpdate.innerHTML = `displaying content for ${button.innerHTML}`;
    } else {
      button.setAttribute("aria-selected", "false");
    }
  });
  panels.forEach((panel) => {
    if (panel.id === `tabpanel-${number}`) {
      panel.tabIndex = 0;
      panel.setAttribute("style", "");
    } else {
      panel.tabIndex = -1;
      panel.setAttribute("style", "display: none;");
    }
  });
}

Example from the Brown React Component Library

Brown React Component Library Code