### Existing implementations
#### Mediawiki software
* OOUI IndexLayout ([[ https://doc.wikimedia.org/oojs-ui/master/js/#!/api/OO.ui.IndexLayout | docs ]], [[ https://doc.wikimedia.org/oojs-ui/master/demos/?page=layouts&theme=wikimediaui&direction=ltr&platform=desktop#IndexLayout-framed | demo ]])
* Structured Data tabs ([[ https://github.com/wikimedia/mediawiki-extensions-MediaSearch/blob/master/resources/components/base/Tabs.vue | code ]])
#### External libraries
* Vuetify Tabs ([[ https://vuetifyjs.com/en/components/tabs/ | docs ]], [[ https://github.com/vuetifyjs/vuetify/tree/master/packages/vuetify/src/components/VTabs | code ]])
* Naive-UI Tabs ([[ https://www.naiveui.com/en-US/os-theme/components/tabs | demo ]], [[ https://github.com/TuSimple/naive-ui/tree/main/src/tabs | code ]])
### Implementation notes
Implementation requires two components, `Tab` and `Tabs`.
The parent `Tabs` component has a slot that should contain one or more child `Tab` components; each `Tab` component in turn has its own slot to contain arbitrary content from the end-user.
The parent `Tabs` component needs to know some things about its children (it needs to know the `label` prop of each child in order to construct a header row, for example); likewise each individual `Tab` looks to the parent to determine whether or not it is the active tab (a tab's `v-show` and `aria-hidden` attributes will change based on this).
We want to share this data between the parent and child components automatically (so that the user doesn't have to worry about manually passing certain props when composing slot contents). Vue's [[ https://v3.vuejs.org/guide/composition-api-provide-inject.html | provide/inject ]] API is used to accomplish this, and since we are using Typescript we can also ensure that the injected data is type-safe (see [[ https://logaretm.com/blog/2020-12-23-type-safe-provide-inject | this blog post ]] for more on using provide/inject in TS).