Search code examples
vuejs3vue-composition-api

How to create modal like macOS settings app


Here's a reference

macOS settings app window

I have an example structure that describes how I want this to look, but I don't know how to implement it.

Here is a structure example

<Modal ref="modal" @close="close()">
  <!-- 
    the names of the tabs automatically go to the sidebar (only first-level tabs), their structure is as follows:
    <div class="sidebar">
      <span> tab1 </span>
      <span> tab2 </span>
      ...
    <div> 
    these tabs in sidebar is created automatically in Modal component based on tab names from <ModalTab       name="tabName">
    clicking on span goes to tab with same name (like modal.goto('tab1'))
  -->

  <ModalTab name="tab1">
    <template #content>
      tab1 content

      <button @click="modal.goto('childTab1')">go to childTab1</button>
      <button @click="modal.goto('childTab2')">go to childTab2</button>
    </template>

    <ModalTab name="childTab1" @goback="doSome()"> <!-- "goback" emit triggers when back arrow is clicked, then it goes back to "tab1", and you can change some data inside modal -->
      <template #content>
        child content
      </template>

      <template #footer>
        <button @click="saveInnerData(), modal.goto('tab1')">save inner data</button>
      </template>
    </ModalTab>

    <ModalTab name="childTab2" @goback="doSome()"> <!-- "goback" emit triggers when back arrow is clicked, then it goes back to "tab1", and you can change some data inside modal -->
      <template #content>
        child content
      </template>
      
      <!-- child footer that displays when child tab is active -->
      <template #footer>
        <button @click="saveInnerData(), modal.goto('tab1')">save inner data</button>
      </template>
    </ModalTab>
  </ModalTab>

  <ModalTab name="tab2">
    <template #content>
      content
    </template>
  </ModalTab>
  
  <!-- main footer that displays one of first level tabs is active -->
  <template #footer>
    <button @click="saveAndClose()">save</button>
  </template>
</Modal>

As you can see, there are two components: Modal and ModalTab. In ModalTab back arrow appears when one of the childTabs is active. Also, when one of childTabs is active, main tab's content not rendered. I guess it can be done with a custom component plugin, that allows import multiple components at once, like import {Modal, ModalTab} from 'myCustomModal or even import both components globally.


Solution

  • Well, because nobody gave me some examples or plugins, i've created my own plugin for vue 3! Check it out on github or npmjs!