Skip to content

Commit e9ea690

Browse files
authored
feat(QTabs): add outside arrow positioning and force arrows on mobile quasarframework#7104, quasarframework#4019 (quasarframework#7357)
1 parent f54a1cc commit e9ea690

File tree

7 files changed

+162
-22
lines changed

7 files changed

+162
-22
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<template>
2+
<div class="q-pa-md">
3+
<div class="q-gutter-y-md" style="max-width: 300px">
4+
<q-tabs
5+
v-model="tab"
6+
inline-label
7+
outside-arrows
8+
mobile-arrows
9+
class="bg-primary text-white shadow-2"
10+
>
11+
<q-tab name="mails" icon="mail" label="Mails" />
12+
<q-tab name="alarms" icon="alarm" label="Alarms" />
13+
<q-tab name="movies" icon="movie" label="Movies" />
14+
<q-tab name="photos" icon="photo" label="Photos" />
15+
<q-tab name="videos" icon="slow_motion_video" label="Videos" />
16+
<q-tab name="addressbook" icon="people" label="Address Book" />
17+
</q-tabs>
18+
19+
<q-tabs
20+
v-model="tab"
21+
inline-label
22+
mobile-arrows
23+
class="bg-purple text-white shadow-2"
24+
>
25+
<q-tab name="mails" icon="mail" label="Mails" />
26+
<q-tab name="alarms" icon="alarm" label="Alarms" />
27+
<q-tab name="movies" icon="movie" label="Movies" />
28+
<q-tab name="photos" icon="photo" label="Photos" />
29+
<q-tab name="videos" icon="slow_motion_video" label="Videos" />
30+
<q-tab name="addressbook" icon="people" label="Address Book" />
31+
</q-tabs>
32+
33+
<q-tabs
34+
v-model="tab"
35+
no-caps
36+
outside-arrows
37+
mobile-arrows
38+
class="bg-orange text-white shadow-2"
39+
>
40+
<q-tab name="mails" label="Mails" />
41+
<q-tab name="alarms" label="Alarms" />
42+
<q-tab name="movies" label="Movies" />
43+
</q-tabs>
44+
</div>
45+
</div>
46+
</template>
47+
48+
<script>
49+
export default {
50+
data () {
51+
return {
52+
tab: 'mails'
53+
}
54+
}
55+
}
56+
</script>

docs/src/pages/vue-components/tabs.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,23 @@ QRouteTab won't and cannot work with the UMD version because in that environment
2727
## Usage
2828

2929
::: tip
30-
QTabs can be scrolled horizontally when the width is longer than the container width. Adjust your browser accordingly to see this in action. On a desktop you will see chevrons on either side that can be clicked. On a mobile, you can pan the tabs with your finger.
30+
QTabs can be scrolled horizontally when the width is longer than the container width. Adjust your browser accordingly to see this in action.
31+
32+
On a desktop you will see chevrons on either side that can be clicked.
33+
34+
On a mobile, you can pan the tabs with your finger.
35+
36+
If you want to force arrows to be visible on mobile use `mobile-arrows` prop.
3137
:::
3238

3339
### Basic
3440

3541
<doc-example title="Basic" file="QTabs/Basic" />
3642

43+
### Outside, inside and visible on mobile arrows
44+
45+
<doc-example title="Outside, inside and visible on mobile arrows" file="QTabs/ArrowsModifiers" />
46+
3747
### Vertical
3848

3949
<doc-example title="Vertical (example with QSplitter)" file="QTabs/Vertical" />

ui/dev/src/pages/components/tabs-dynamic-1.vue

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,19 @@
99
<q-input dark dense borderless input-class="text-right" v-model.number="width" type="number" :min="300" />
1010
</q-item-section>
1111
</q-item>
12+
<q-separator />
13+
<q-item dark class="bg-purple" dense v-ripple clickable @click="outsideArrows = outsideArrows === false">
14+
<q-item-section>
15+
<q-item-label>{{ outsideArrows === true ? 'Arrows outside (change to inside)' : 'Arrows inside (change to outside)'}}</q-item-label>
16+
</q-item-section>
17+
</q-item>
18+
<q-separator />
19+
<q-item dark class="bg-purple" dense v-ripple clickable @click="mobileArrows = mobileArrows === false">
20+
<q-item-section>
21+
<q-item-label>{{ mobileArrows === true ? 'Arrows visible on mobile (change to invisible)' : 'Arrows invisible on mobile (change to visible)'}}</q-item-label>
22+
</q-item-section>
23+
</q-item>
24+
<q-separator />
1225
<q-item dark class="bg-primary" dense v-ripple clickable @click="toggleAll">
1326
<q-item-section>
1427
<q-item-label>Toggle all</q-item-label>
@@ -43,6 +56,8 @@
4356
inline-label
4457
shrink
4558
stretch
59+
:outside-arrows="outsideArrows"
60+
:mobile-arrows="mobileArrows"
4661
>
4762
<q-tab v-for="t in tabs" :key="t.name" v-bind="t" />
4863
</q-tabs>
@@ -56,6 +71,8 @@
5671
inline-label
5772
shrink
5873
stretch
74+
:outside-arrows="outsideArrows"
75+
:mobile-arrows="mobileArrows"
5976
>
6077
<q-tab v-for="t in tabs" :key="t.name" v-bind="t" />
6178
</q-tabs>
@@ -78,6 +95,8 @@ export default {
7895
return {
7996
tab: 'mails',
8097
width: 300,
98+
mobileArrows: false,
99+
outsideArrows: false,
81100
tabs: allTabs.slice(0, 1)
82101
}
83102
},

ui/src/components/tabs/QTabs.js

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ export default Vue.extend({
8080
leftIcon: String,
8181
rightIcon: String,
8282

83+
outsideArrows: Boolean,
84+
mobileArrows: Boolean,
85+
8386
switchIndicator: Boolean,
8487

8588
narrowIndicator: Boolean,
@@ -148,10 +151,23 @@ export default Vue.extend({
148151

149152
noCaps (v) {
150153
this.tabs.noCaps = v
154+
},
155+
156+
outsideArrows () {
157+
this.$nextTick(this.__recalculateScroll())
158+
},
159+
160+
arrowsEnabled (v) {
161+
this.__updateArrows = v === true ? this.__updateArrowsFn : noop
162+
this.$nextTick(this.__recalculateScroll())
151163
}
152164
},
153165

154166
computed: {
167+
arrowsEnabled () {
168+
return this.mobileArrows === true || this.$q.platform.is.desktop === true
169+
},
170+
155171
alignClass () {
156172
const align = this.scrollable === true
157173
? 'left'
@@ -163,6 +179,7 @@ export default Vue.extend({
163179
classes () {
164180
return `q-tabs--${this.scrollable === true ? '' : 'not-'}scrollable` +
165181
` q-tabs--${this.vertical === true ? 'vertical' : 'horizontal'}` +
182+
` q-tabs__arrows--${this.arrowsEnabled === true && this.outsideArrows === true ? 'outside' : 'inside'}` +
166183
(this.dense === true ? ' q-tabs--dense' : '') +
167184
(this.shrink === true ? ' col-shrink' : '') +
168185
(this.stretch === true ? ' self-stretch' : '')
@@ -320,7 +337,7 @@ export default Vue.extend({
320337
}
321338
},
322339

323-
__updateArrows () {
340+
__updateArrowsFn () {
324341
const
325342
content = this.$refs.content,
326343
rect = content.getBoundingClientRect(),
@@ -384,9 +401,7 @@ export default Vue.extend({
384401
created () {
385402
this.buffer = []
386403

387-
if (this.$q.platform.is.desktop !== true) {
388-
this.__updateArrows = noop
389-
}
404+
this.__updateArrows = this.arrowsEnabled === true ? this.__updateArrowsFn : noop
390405
},
391406

392407
beforeDestroy () {
@@ -407,7 +422,7 @@ export default Vue.extend({
407422
}, slot(this, 'default'))
408423
]
409424

410-
this.$q.platform.is.desktop === true && child.push(
425+
this.arrowsEnabled === true && child.push(
411426
h(QIcon, {
412427
staticClass: 'q-tabs__arrow q-tabs__arrow--left absolute q-tab__icon',
413428
class: this.leftArrow === true ? '' : 'q-tabs__arrow--faded',

ui/src/components/tabs/QTabs.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,20 @@
2121
"category": "content"
2222
},
2323

24+
"outside-arrows": {
25+
"type": "Boolean",
26+
"desc": "Reserve space for arrows to place them on each side of the tabs (the arrows fade when inactive)",
27+
"category": "content",
28+
"addedIn": "v1.12.9"
29+
},
30+
31+
"mobile-arrows": {
32+
"type": "Boolean",
33+
"desc": "Force display of arrows (if needed) on mobile",
34+
"category": "content",
35+
"addedIn": "v1.12.9"
36+
},
37+
2438
"align": {
2539
"type": "String",
2640
"desc": "Horizontal alignment the tabs within the tabs container",

ui/src/components/tabs/QTabs.sass

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,24 @@
7575
position: relative
7676
transition: color .3s, background-color .3s
7777

78+
&--scrollable
79+
&.q-tabs__arrows--outside
80+
&.q-tabs--horizontal
81+
padding-left: 36px
82+
padding-right: 36px
83+
84+
&.q-tabs--vertical
85+
padding-top: 36px
86+
padding-bottom: 36px
87+
88+
.q-tabs__arrow--faded
89+
opacity: 0.3
90+
pointer-events: none
91+
92+
&.q-tabs__arrows--inside
93+
.q-tabs__arrow--faded
94+
display: none
95+
7896
&--not-scrollable
7997
.q-tabs__arrow
8098
display: none
@@ -86,9 +104,7 @@
86104
font-size: 32px
87105
min-width: 36px
88106
text-shadow: 0 0 3px #fff, 0 0 1px #fff, 0 0 1px #000
89-
90-
&--faded
91-
display: none
107+
transition: opacity .3s
92108

93109
&__content
94110
overflow: hidden
@@ -113,12 +129,12 @@
113129

114130
&--left
115131
top: 0
116-
left: 0
132+
left: 0 #{"/* rtl:ignore */"}
117133
bottom: 0
118134

119135
&--right
120136
top: 0
121-
right: 0
137+
right: 0 #{"/* rtl:ignore */"}
122138
bottom: 0
123139

124140
&--vertical
@@ -171,9 +187,6 @@ body.mobile .q-tabs
171187
&__content
172188
overflow: auto
173189

174-
&__arrow
175-
display: none
176-
177190
@media (min-width: $breakpoint-lg-min)
178191
.q-header, .q-footer
179192
.q-tab__content

ui/src/components/tabs/QTabs.styl

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,24 @@
7575
position: relative
7676
transition: color .3s, background-color .3s
7777

78+
&--scrollable
79+
&.q-tabs__arrows--outside
80+
&.q-tabs--horizontal
81+
padding-left: 36px
82+
padding-right: 36px
83+
84+
&.q-tabs--vertical
85+
padding-top: 36px
86+
padding-bottom: 36px
87+
88+
.q-tabs__arrow--faded
89+
opacity: 0.3
90+
pointer-events: none
91+
92+
&.q-tabs__arrows--inside
93+
.q-tabs__arrow--faded
94+
display: none
95+
7896
&--not-scrollable
7997
.q-tabs__arrow
8098
display: none
@@ -86,9 +104,7 @@
86104
font-size: 32px
87105
min-width: 36px
88106
text-shadow: 0 0 3px #fff, 0 0 1px #fff, 0 0 1px #000
89-
90-
&--faded
91-
display: none
107+
transition: opacity .3s
92108

93109
&__content
94110
overflow: hidden
@@ -113,12 +129,12 @@
113129

114130
&--left
115131
top: 0
116-
left: 0
132+
left: 0 /* rtl:ignore */
117133
bottom: 0
118134

119135
&--right
120136
top: 0
121-
right: 0
137+
right: 0 /* rtl:ignore */
122138
bottom: 0
123139

124140
&--vertical
@@ -171,9 +187,6 @@ body.mobile .q-tabs
171187
&__content
172188
overflow: auto
173189

174-
&__arrow
175-
display: none
176-
177190
@media (min-width: $breakpoint-lg-min)
178191
.q-header, .q-footer
179192
.q-tab__content

0 commit comments

Comments
 (0)