Tabs in React plugin

Hi, I am struggling a lot with tabs for my plugin in react/typescript.
For vanilla plugin I used code from ui-kitchen-sink plugin sample

    <div class="sp-tabs">
      <div class="sp-tab selected" id="sp-spectrum-typography-tab"><sp-label>Spectrum Typography</sp-label></div>
      <div class="sp-tab" id="sp-spectrum-widgets-tab"><sp-label>Spectrum Widgets</sp-label></div>
      <div class="sp-tab" id="sp-native-tab"><sp-label>Native</sp-label></div>
      <div class="sp-tab" id="sp-html-tab"><sp-label>HTML</sp-label></div>
      <div class="sp-tab" id="sp-events-tab"><sp-label>Events</sp-label></div>
    <div class="sp-tab-page visible" id="sp-spectrum-typography-tab-page">
    //content
    </div>
 ...
   </div>

and

  theTab.onclick = () => {
    localStorage.setItem("currentTab", theTab.getAttribute("id"));
    Array.from(document.querySelectorAll(".sp-tab")).forEach(aTab => {
      if (aTab.getAttribute("id") === theTab.getAttribute("id")) {
        aTab.classList.add("selected");
      } else {
        aTab.classList.remove("selected");
      }
    });
    Array.from(document.querySelectorAll(".sp-tab-page")).forEach(tabPage => {
      if (tabPage.getAttribute("id").startsWith(theTab.getAttribute("id"))) {
        tabPage.classList.add("visible");
      } else {
        tabPage.classList.remove("visible");
      }
    });
  }
});

unfortunately I can’t make it work for React.
Can anyone help me a little bit with that?

Could you share your React component example? I’m guessing you’re not setting the active tab state (by which you should define selected and visible classes). It should be something like:

export default () => {
  let tabName

  useEffect(() => {
    tabName = localStorage.getItem("currentTab")
  }, [])

  const [activeTab, setActiveTab] = useState(tabName)

  const setActiveTabData = (tabName) => {
    localStorage.setItem("currentTab", tabName)
    setActiveTab(tabName)
  }

  return (
    <div class="sp-tabs">
      <div class={`sp-tab ${activeTab === "spectrum-typography-tab" ? "selected" : ""}`} onClick={() => setActiveTabData("spectrum-typography-tab")}><sp-label>Spectrum Typography</sp-label></div>
      <div class={`sp-tab ${activeTab === "spectrum-widgets-tab" ? "selected" : ""}`} onClick={() => setActiveTabData("spectrum-widgets-tab")}><sp-label>Spectrum Widgets</sp-label></div>

      <div class={`sp-tab-page ${activeTab === "spectrum-typography-tab" ? "visible" : ""}`}>
        //content
      </div>
      ...
    </div>
  )
}

I strongly suggest having tabs map somewhere to loop through them so you wouldn’t have to repeat yourself. Note: I didn’t test this code and it can still be optimized quite a bit, but you should get the idea

1 Like

Thank you, that will do