Skip to content

Commit

Permalink
feat(VAppBar): don't truncate title with shrink-on-scroll (#12516)
Browse files Browse the repository at this point in the history
closes #12514
  • Loading branch information
KaelWD committed Nov 3, 2020
1 parent 8e5554d commit 8c5ee02
Show file tree
Hide file tree
Showing 11 changed files with 128 additions and 25 deletions.
10 changes: 10 additions & 0 deletions packages/api-generator/src/maps/v-app-bar-title.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module.exports = {
'v-app-bar-title': {
slots: [
{
name: 'default',
props: undefined,
},
],
},
}
2 changes: 1 addition & 1 deletion packages/docs/src/examples/v-app-bar/prop-img-fade.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

<v-app-bar-nav-icon></v-app-bar-nav-icon>

<v-toolbar-title>Title</v-toolbar-title>
<v-app-bar-title>Title</v-app-bar-title>

<v-spacer></v-spacer>

Expand Down
2 changes: 1 addition & 1 deletion packages/docs/src/examples/v-app-bar/prop-img.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

<v-app-bar-nav-icon></v-app-bar-nav-icon>

<v-toolbar-title>Title</v-toolbar-title>
<v-app-bar-title>Title</v-app-bar-title>

<v-spacer></v-spacer>

Expand Down
2 changes: 1 addition & 1 deletion packages/docs/src/examples/v-app-bar/prop-prominent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
>
<v-app-bar-nav-icon></v-app-bar-nav-icon>

<v-toolbar-title>Title</v-toolbar-title>
<v-app-bar-title>Title</v-app-bar-title>

<v-spacer></v-spacer>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

<v-app-bar-nav-icon></v-app-bar-nav-icon>

<v-toolbar-title>Title</v-toolbar-title>
<v-app-bar-title>Title</v-app-bar-title>

<v-spacer></v-spacer>

Expand Down
5 changes: 5 additions & 0 deletions packages/docs/src/pages/en/components/app-bars.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,18 @@ The `v-app-bar` component is used for application-wide actions and information.

- [v-app-bar](/api/v-app-bar)
- [v-app-bar-nav-icon](/api/v-app-bar-nav-icon)
- [v-app-bar-title](/api/v-app-bar-title)

## Sub-components

### v-app-bar-nav-icon

A styled icon button component created specifically for use with [v-toolbar](/components/toolbars) and `v-app-bar`. Typically seen on the left side of a toolbar as a hamburger menu, it is often used to control the state of a navigation drawer. The `default` slot can be used to customize the icon and function of this component. This is a **functional** component.

### v-app-bar-title

A modified [v-toolbar-title](/components/toolbars/) specifically for use with the `shrink-on-scroll` prop. `v-toolbar-title` will be truncated on small screens (see [issue #12514](https://github.com/vuetifyjs/vuetify/issues/12514)) but this component uses absolute positioning to be fully visible when expanded. We don't recommend using `v-app-bar-title` without `shrink-on-scroll` as it does add a resize watcher and some extra calculations.

## Caveats

<alert type="warning">
Expand Down
10 changes: 10 additions & 0 deletions packages/vuetify/src/components/VAppBar/VAppBar.sass
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,13 @@
.v-app-bar.v-app-bar--shrink-on-scroll
.v-toolbar__title
font-size: inherit

.v-app-bar-title
&__placeholder,
&__content
overflow: hidden
text-overflow: ellipsis
white-space: nowrap

&__content
position: absolute
34 changes: 15 additions & 19 deletions packages/vuetify/src/components/VAppBar/VAppBar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ export default baseMixins.extend({

directives: { Scroll },

provide (): object {
return { VAppBar: this }
},

props: {
clippedLeft: Boolean,
clippedRight: Boolean,
Expand Down Expand Up @@ -77,7 +81,7 @@ export default baseMixins.extend({
this.hideOnScroll ||
this.collapseOnScroll ||
this.isBooted ||
// If falsey, user has provided an
// If falsy, user has provided an
// explicit value which should
// overwrite anything we do
!this.value
Expand All @@ -98,28 +102,25 @@ export default baseMixins.extend({
'v-app-bar--shrink-on-scroll': this.shrinkOnScroll,
}
},
scrollRatio (): number {
const threshold = this.computedScrollThreshold
return Math.max((threshold - this.currentScroll) / threshold, 0)
},
computedContentHeight (): number {
if (!this.shrinkOnScroll) return VToolbar.options.computed.computedContentHeight.call(this)

const height = this.computedOriginalHeight

const min = this.dense ? 48 : 56
const max = height
const difference = max - min
const iteration = difference / this.computedScrollThreshold
const offset = this.currentScroll * iteration
const max = this.computedOriginalHeight

return Math.max(min, max - offset)
return min + (max - min) * this.scrollRatio
},
computedFontSize (): number | undefined {
if (!this.isProminent) return undefined

const max = this.dense ? 96 : 128
const difference = max - this.computedContentHeight
const increment = 0.00347
const min = 1.25
const max = 1.5

// 1.5rem to a minimum of 1.25rem
return Number((1.50 - difference * increment).toFixed(2))
return min + (max - min) * this.scrollRatio
},
computedLeft (): number {
if (!this.app || this.clippedLeft) return 0
Expand All @@ -134,12 +135,7 @@ export default baseMixins.extend({
computedOpacity (): number | undefined {
if (!this.fadeImgOnScroll) return undefined

const opacity = Math.max(
(this.computedScrollThreshold - this.currentScroll) / this.computedScrollThreshold,
0
)

return Number(parseFloat(opacity).toFixed(2))
return this.scrollRatio
},
computedOriginalHeight (): number {
let height = VToolbar.options.computed.computedContentHeight.call(this)
Expand Down
80 changes: 80 additions & 0 deletions packages/vuetify/src/components/VAppBar/VAppBarTitle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Mixins
import { inject } from '../../mixins/registrable'

// Types
import { VNode } from 'vue'
import { ExtractVue } from '../../util/mixins'
import VAppBar from './VAppBar'

// Utilities
import { convertToUnit } from '../../util/helpers'
import { easeInOutCubic } from '../../services/goto/easing-patterns'

const base = inject<'VAppBar', typeof VAppBar>('VAppBar', 'v-app-bar-title', 'v-app-bar')

interface options extends ExtractVue<typeof base> {
$refs: {
content: Element
placeholder: Element
}
}

export default base.extend<options>().extend({
name: 'v-app-bar-title',

data: () => ({
contentWidth: 0,
left: 0,
width: 0,
}),

watch: {
'$vuetify.breakpoint.width': 'updateDimensions',
},

computed: {
styles (): object {
if (!this.contentWidth) return {}

const min = this.width
const max = this.contentWidth
const ratio = easeInOutCubic(Math.min(1, this.VAppBar.scrollRatio * 1.5))
return {
width: convertToUnit(min + (max - min) * ratio),
visibility: this.VAppBar.scrollRatio ? 'visible' : 'hidden',
}
},
},

mounted () {
this.updateDimensions()
},

methods: {
updateDimensions (): void {
const dimensions = this.$refs.placeholder.getBoundingClientRect()
this.width = dimensions.width
this.left = dimensions.left
this.contentWidth = this.$refs.content.scrollWidth
},
},

render (h): VNode {
return h('div', {
class: 'v-toolbar__title v-app-bar-title',
}, [
h('div', {
class: 'v-app-bar-title__content',
style: this.styles,
ref: 'content',
}, [this.$slots.default]),
h('div', {
class: 'v-app-bar-title__placeholder',
style: {
visibility: this.VAppBar.scrollRatio ? 'hidden' : 'visible',
},
ref: 'placeholder',
}, [this.$slots.default]),
])
},
})
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ describe('AppBar.ts', () => {
expect(wrapper.vm.computedOpacity).toBe(1)

wrapper.setData({ currentScroll: 5 })
expect(wrapper.vm.computedOpacity).toBe(0.38)
expect(wrapper.vm.computedOpacity).toBe(0.375)

wrapper.setData({ currentScroll: 100 })
expect(wrapper.vm.computedOpacity).toBe(0)
Expand Down
4 changes: 3 additions & 1 deletion packages/vuetify/src/components/VAppBar/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import VAppBar from './VAppBar'
import VAppBarNavIcon from './VAppBarNavIcon'
import VAppBarTitle from './VAppBarTitle'

export { VAppBar, VAppBarNavIcon }
export { VAppBar, VAppBarNavIcon, VAppBarTitle }

export default {
$_vuetify_subcomponents: {
VAppBar,
VAppBarNavIcon,
VAppBarTitle,
},
}

0 comments on commit 8c5ee02

Please sign in to comment.