diff options
| author | Shpuld Shpuldson <shp@cock.li> | 2020-06-18 16:47:37 +0300 |
|---|---|---|
| committer | Shpuld Shpuldson <shp@cock.li> | 2020-06-18 16:47:37 +0300 |
| commit | 8a9654b511268338d46f351da43a6bd85fbcb972 (patch) | |
| tree | 66d477ba0dc307e1074b5025933918da5ef31478 /src/components/tab_switcher | |
| parent | 6d2befa452d6b42e47968f382a7ff62d4eb0d9b9 (diff) | |
| parent | ebf4321e645a34a40c00b0884546e9da86361952 (diff) | |
Merge branch 'develop' into features/favicons
Diffstat (limited to 'src/components/tab_switcher')
| -rw-r--r-- | src/components/tab_switcher/tab_switcher.js | 45 | ||||
| -rw-r--r-- | src/components/tab_switcher/tab_switcher.scss | 268 |
2 files changed, 238 insertions, 75 deletions
diff --git a/src/components/tab_switcher/tab_switcher.js b/src/components/tab_switcher/tab_switcher.js index 008e1e95..7891cb78 100644 --- a/src/components/tab_switcher/tab_switcher.js +++ b/src/components/tab_switcher/tab_switcher.js @@ -24,6 +24,11 @@ export default Vue.component('tab-switcher', { required: false, type: Boolean, default: false + }, + sideTabBar: { + required: false, + type: Boolean, + default: false } }, data () { @@ -55,6 +60,9 @@ export default Vue.component('tab-switcher', { this.onSwitch.call(null, this.$slots.default[index].key) } this.active = index + if (this.scrollableTabs) { + this.$refs.contents.scrollTop = 0 + } } } }, @@ -64,7 +72,6 @@ export default Vue.component('tab-switcher', { if (!slot.tag) return const classesTab = ['tab'] const classesWrapper = ['tab-wrapper'] - if (this.activeIndex === index) { classesTab.push('active') classesWrapper.push('active') @@ -87,8 +94,14 @@ export default Vue.component('tab-switcher', { <button disabled={slot.data.attrs.disabled} onClick={this.activateTab(index)} - class={classesTab.join(' ')}> - {slot.data.attrs.label}</button> + class={classesTab.join(' ')} + type="button" + > + {!slot.data.attrs.icon ? '' : (<i class={'tab-icon icon-' + slot.data.attrs.icon}/>)} + <span class="text"> + {slot.data.attrs.label} + </span> + </button> </div> ) }) @@ -96,20 +109,32 @@ export default Vue.component('tab-switcher', { const contents = this.$slots.default.map((slot, index) => { if (!slot.tag) return const active = this.activeIndex === index - if (this.renderOnlyFocused) { - return active - ? <div class="active">{slot}</div> - : <div class="hidden"></div> + const classes = [ active ? 'active' : 'hidden' ] + if (slot.data.attrs.fullHeight) { + classes.push('full-height') } - return <div class={active ? 'active' : 'hidden' }>{slot}</div> + const renderSlot = (!this.renderOnlyFocused || active) + ? slot + : '' + + return ( + <div class={classes}> + { + this.sideTabBar + ? <h1 class="mobile-label">{slot.data.attrs.label}</h1> + : '' + } + {renderSlot} + </div> + ) }) return ( - <div class="tab-switcher"> + <div class={'tab-switcher ' + (this.sideTabBar ? 'side-tabs' : 'top-tabs')}> <div class="tabs"> {tabs} </div> - <div class={'contents' + (this.scrollableTabs ? ' scrollable-tabs' : '')}> + <div ref="contents" class={'contents' + (this.scrollableTabs ? ' scrollable-tabs' : '')}> {contents} </div> </div> diff --git a/src/components/tab_switcher/tab_switcher.scss b/src/components/tab_switcher/tab_switcher.scss index df585faa..d2ef4857 100644 --- a/src/components/tab_switcher/tab_switcher.scss +++ b/src/components/tab_switcher/tab_switcher.scss @@ -2,7 +2,144 @@ .tab-switcher { display: flex; - flex-direction: column; + + .tab-icon { + font-size: 2em; + display: block; + } + + &.top-tabs { + flex-direction: column; + + > .tabs { + width: 100%; + overflow-y: hidden; + overflow-x: auto; + padding-top: 5px; + flex-direction: row; + + &::after, &::before { + content: ''; + flex: 1 1 auto; + border-bottom: 1px solid; + border-bottom-color: $fallback--border; + border-bottom-color: var(--border, $fallback--border); + } + .tab-wrapper { + height: 28px; + + &:not(.active)::after { + left: 0; + right: 0; + bottom: 0; + border-bottom: 1px solid; + border-bottom-color: $fallback--border; + border-bottom-color: var(--border, $fallback--border); + } + } + .tab { + width: 100%; + min-width: 1px; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + padding-bottom: 99px; + margin-bottom: 6px - 99px; + } + } + .contents.scrollable-tabs { + flex-basis: 0; + } + } + + &.side-tabs { + flex-direction: row; + + @media all and (max-width: 800px) { + overflow-x: auto; + } + + > .contents { + flex: 1 1 auto; + } + + > .tabs { + flex: 0 0 auto; + overflow-y: auto; + overflow-x: hidden; + flex-direction: column; + + &::after, &::before { + flex-shrink: 0; + flex-basis: .5em; + content: ''; + border-right: 1px solid; + border-right-color: $fallback--border; + border-right-color: var(--border, $fallback--border); + } + + &::after { + flex-grow: 1; + } + + &::before { + flex-grow: 0; + } + + .tab-wrapper { + min-width: 10em; + display: flex; + flex-direction: column; + + @media all and (max-width: 800px) { + min-width: 1em; + } + + &:not(.active)::after { + top: 0; + right: 0; + bottom: 0; + border-right: 1px solid; + border-right-color: $fallback--border; + border-right-color: var(--border, $fallback--border); + } + + &::before { + flex: 0 0 6px; + content: ''; + border-right: 1px solid; + border-right-color: $fallback--border; + border-right-color: var(--border, $fallback--border); + } + + &:last-child .tab { + margin-bottom: 0; + } + } + + .tab { + flex: 1; + box-sizing: content-box; + min-width: 10em; + min-width: 1px; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + padding-left: 1em; + padding-right: calc(1em + 200px); + margin-right: -200px; + margin-left: 1em; + + @media all and (max-width: 800px) { + padding-left: .25em; + padding-right: calc(.25em + 200px); + margin-right: calc(.25em - 200px); + margin-left: .25em; + .text { + display: none + } + } + } + } + } .contents { flex: 1 0 auto; @@ -11,88 +148,89 @@ .hidden { display: none; } + .full-height:not(.hidden) { + height: 100%; + display: flex; + flex-direction: column; + > *:not(.mobile-label) { + flex: 1; + } + } &.scrollable-tabs { - flex-basis: 0; overflow-y: auto; } } - .tabs { - display: flex; + + .tab { position: relative; - width: 100%; - overflow-y: hidden; - overflow-x: auto; - padding-top: 5px; - box-sizing: border-box; + white-space: nowrap; + padding: 6px 1em; + background-color: $fallback--fg; + background-color: var(--tab, $fallback--fg); - &::after, &::before { - display: block; - content: ''; - flex: 1 1 auto; - border-bottom: 1px solid; - border-bottom-color: $fallback--border; - border-bottom-color: var(--border, $fallback--border); + &, &:active .tab-icon { + color: $fallback--text; + color: var(--tabText, $fallback--text); } - .tab-wrapper { - height: 28px; - position: relative; - display: flex; - flex: 0 0 auto; + &:not(.active) { + z-index: 4; - .tab { - width: 100%; - min-width: 1px; - position: relative; - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; - padding: 6px 1em; - padding-bottom: 99px; - margin-bottom: 6px - 99px; - white-space: nowrap; + &:hover { + z-index: 6; + } + } - color: $fallback--text; - color: var(--tabText, $fallback--text); - background-color: $fallback--fg; - background-color: var(--tab, $fallback--fg); + &.active { + background: transparent; + z-index: 5; + color: $fallback--text; + color: var(--tabActiveText, $fallback--text); + } - &:not(.active) { - z-index: 4; + img { + max-height: 26px; + vertical-align: top; + margin-top: -5px; + } + } - &:hover { - z-index: 6; - } - } + .tabs { + display: flex; + position: relative; + box-sizing: border-box; - &.active { - background: transparent; - z-index: 5; - color: $fallback--text; - color: var(--tabActiveText, $fallback--text); - } + &::after, &::before { + display: block; + flex: 1 1 auto; + } + } - img { - max-height: 26px; - vertical-align: top; - margin-top: -5px; - } - } + .tab-wrapper { + position: relative; + display: flex; + flex: 0 0 auto; - &:not(.active) { - &::after { - content: ''; - position: absolute; - left: 0; - right: 0; - bottom: 0; - z-index: 7; - border-bottom: 1px solid; - border-bottom-color: $fallback--border; - border-bottom-color: var(--border, $fallback--border); - } + &:not(.active) { + &::after { + content: ''; + position: absolute; + z-index: 7; } } + } + .mobile-label { + padding-left: .3em; + padding-bottom: .25em; + margin-top: .5em; + margin-left: .2em; + margin-bottom: .25em; + border-bottom: 1px solid var(--border, $fallback--border); + + @media all and (min-width: 800px) { + display: none; + } } } |
