working prototype
This commit is contained in:
parent
50ede338e7
commit
7c57be22e4
15 changed files with 266 additions and 215 deletions
|
|
@ -37,19 +37,13 @@ export default {
|
|||
required: false,
|
||||
type: Boolean,
|
||||
default: null
|
||||
},
|
||||
hideHeader: {
|
||||
required: false,
|
||||
type: Boolean,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
active: findFirstUsable(this.slots()),
|
||||
resizeHandler: null,
|
||||
navMode: false,
|
||||
navSide: 'content'
|
||||
navSide: 'tabs'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -71,16 +65,6 @@ export default {
|
|||
mobileLayout: store => store.layoutType === 'mobile'
|
||||
}),
|
||||
},
|
||||
created () {
|
||||
this.resizeHandler = throttle(this.onResize, 200)
|
||||
window.addEventListener('resize', this.resizeHandler)
|
||||
},
|
||||
mounted () {
|
||||
this.resizeHandler()
|
||||
},
|
||||
unmounted () {
|
||||
window.removeEventListener('resize', this.resizeHandler)
|
||||
},
|
||||
beforeUpdate () {
|
||||
const currentSlot = this.slots()[this.active]
|
||||
if (!currentSlot.props) {
|
||||
|
|
@ -92,7 +76,6 @@ export default {
|
|||
return (e) => {
|
||||
e.preventDefault()
|
||||
this.setTab(index)
|
||||
this.onResize()
|
||||
}
|
||||
},
|
||||
setTab (index) {
|
||||
|
|
@ -105,30 +88,6 @@ export default {
|
|||
changeNavSide (side) {
|
||||
if (this.navSide !== side) {
|
||||
this.navSide = side
|
||||
this.onResize()
|
||||
}
|
||||
},
|
||||
getNavMode () {
|
||||
return this.navMode
|
||||
},
|
||||
onResize () {
|
||||
// All other tabs are hidden and their width is most likely 0
|
||||
const activeTab = this.$refs.root.querySelector('.tab-content-wrapper.-active')
|
||||
const tabContent = activeTab.querySelector('.tab-content')
|
||||
const tabContentWidth = tabContent.clientWidth
|
||||
|
||||
const rootWidth = this.$refs.root.clientWidth
|
||||
const navWidth = this.$refs.nav.clientWidth
|
||||
const contentsWidth = rootWidth - navWidth
|
||||
|
||||
// if contents takes more space than its container
|
||||
if (contentsWidth < tabContentWidth) {
|
||||
this.hideNav()
|
||||
// If we (theoretically) have enough space to fit it in
|
||||
} else if (contentsWidth - navWidth >= tabContentWidth){
|
||||
// First expand the inner layer, then outer
|
||||
// if use same logic as above order will be reversed
|
||||
this.showNav()
|
||||
}
|
||||
},
|
||||
// DO NOT put it to computed, it doesn't work (caching?)
|
||||
|
|
@ -145,7 +104,7 @@ export default {
|
|||
const props = slot.props
|
||||
if (!props) return
|
||||
const classesTab = ['vertical-tab', 'menu-item']
|
||||
if (this.activeIndex === index) {
|
||||
if (this.activeIndex === index && useInterfaceStore().layoutType !== 'mobile') {
|
||||
classesTab.push('-active')
|
||||
}
|
||||
return (
|
||||
|
|
@ -183,14 +142,21 @@ export default {
|
|||
: ''
|
||||
|
||||
const headerClasses = ['tab-content-label']
|
||||
if (this.hideHeader === true) {
|
||||
headerClasses.push('-hidden')
|
||||
}
|
||||
const header = (
|
||||
<h1 class={headerClasses}>
|
||||
<button type="button" onClick={() => this.changeNavSide('tabs')}>LOL</button>
|
||||
<h2 class={headerClasses}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => this.changeNavSide('tabs')}
|
||||
class="button-unstyled"
|
||||
>
|
||||
<FAIcon
|
||||
size="lg"
|
||||
class="back-button-icon"
|
||||
icon="chevron-left"
|
||||
/>
|
||||
</button>
|
||||
{props.label}
|
||||
</h1>
|
||||
</h2>
|
||||
)
|
||||
|
||||
return (
|
||||
|
|
@ -204,13 +170,14 @@ export default {
|
|||
})
|
||||
|
||||
const rootClasses = ['vertical-tab-switcher']
|
||||
if (this.navMode) {
|
||||
rootClasses.push('-nav-mode')
|
||||
if (this.navSide === 'content') {
|
||||
rootClasses.push('-nav-content')
|
||||
} else {
|
||||
rootClasses.push('-nav-tabs')
|
||||
}
|
||||
if (useInterfaceStore().layoutType === 'mobile') {
|
||||
rootClasses.push('-mobile')
|
||||
}
|
||||
|
||||
if (this.navSide === 'tabs') {
|
||||
rootClasses.push('-nav-tabs')
|
||||
} else {
|
||||
rootClasses.push('-nav-contents')
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,16 +1,19 @@
|
|||
.vertical-tab-switcher {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
container-type: inline-size;
|
||||
|
||||
> .tabs {
|
||||
flex: 0 0 auto;
|
||||
flex: 0 0 15em;
|
||||
flex-direction: column;
|
||||
overflow: hidden auto;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
width: 15em;
|
||||
min-width: 15em;
|
||||
border-right: 1px solid;
|
||||
border-right-color: var(--border);
|
||||
box-sizing: border-box;
|
||||
|
||||
> .menu-item {
|
||||
padding: 0.5em 1em;
|
||||
|
|
@ -23,18 +26,13 @@
|
|||
}
|
||||
|
||||
> .contents {
|
||||
flex: 1 1 auto;
|
||||
overflow-x: hidden;
|
||||
|
||||
.tab-content-label {
|
||||
display: none
|
||||
}
|
||||
flex: 1 0 35em;
|
||||
|
||||
.tab-content {
|
||||
align-self: center;
|
||||
|
||||
&:not(.-full-width) {
|
||||
width: 30em;
|
||||
max-width: 40em;
|
||||
}
|
||||
|
||||
&.-full-width {
|
||||
|
|
@ -42,16 +40,23 @@
|
|||
}
|
||||
}
|
||||
|
||||
.tab-content-label {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
border-bottom: 1px solid var(--border);
|
||||
display: none;
|
||||
|
||||
button {
|
||||
box-sizing: border-box;
|
||||
padding: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-content-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.tab-content-label {
|
||||
font-size: 1.5em;
|
||||
padding: 0.5em 1em;
|
||||
margin: 0;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
overflow-y: auto;
|
||||
height: 100%;
|
||||
|
||||
&.-hidden {
|
||||
display: none;
|
||||
|
|
@ -69,38 +74,104 @@
|
|||
}
|
||||
}
|
||||
|
||||
&.-nav-mode {
|
||||
&.-nav-tabs {
|
||||
> .tabs {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
> .nav-content {
|
||||
width: 0%;
|
||||
&.-mobile {
|
||||
> .contents {
|
||||
.tab-content-label {
|
||||
display: block
|
||||
}
|
||||
}
|
||||
|
||||
&.-nav-content {
|
||||
&.-nav-contents {
|
||||
> .contents {
|
||||
> .tab-content-wrapper {
|
||||
> .tab-content-label {
|
||||
display: block;
|
||||
display: block;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
&.-hidden {
|
||||
display: none;
|
||||
}
|
||||
> .tabs {
|
||||
display: none;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&.-nav-tabs {
|
||||
> .tabs {
|
||||
display: block;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
> .contents {
|
||||
display: none;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@supports (container-type: inline-size) {
|
||||
&,
|
||||
&.-mobile {
|
||||
&.-nav-contents,
|
||||
&.-nav-tabs {
|
||||
/* I THINK it's a false positive and eslint doesn't understand the @-rule */
|
||||
/* stylelint-disable no-descending-specificity */
|
||||
> .contents {
|
||||
display: block;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
> .tabs {
|
||||
display: block;
|
||||
flex-grow: 0;
|
||||
}
|
||||
/* stylelint-enable no-descending-specificity */
|
||||
}
|
||||
}
|
||||
|
||||
@container (width < 50em) {
|
||||
> .contents {
|
||||
.tab-content-label {
|
||||
display: block
|
||||
}
|
||||
}
|
||||
|
||||
&.-mobile {
|
||||
> .contents {
|
||||
.tab-content-label {
|
||||
display: block
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .tabs {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
}
|
||||
&,
|
||||
&.-mobile {
|
||||
&.-nav-contents {
|
||||
> .contents {
|
||||
display: block;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
> .nav-content {
|
||||
width: 100%;
|
||||
> .tabs {
|
||||
display: none;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&.-nav-tabs {
|
||||
/* stylelint-disable no-descending-specificity */
|
||||
> .tabs {
|
||||
display: block;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
> .contents {
|
||||
display: none;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 1;
|
||||
}
|
||||
/* stylelint-enable no-descending-specificity */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue