Skip to content

Commit

Permalink
fix(VListItem): allow default color to change when inactive (#14207)
Browse files Browse the repository at this point in the history
fixes #9285
  • Loading branch information
Tofandel authored Oct 31, 2021
1 parent da5493b commit 3df308f
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 10 deletions.
3 changes: 2 additions & 1 deletion packages/vuetify/src/components/VList/VListItem.sass
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
color: map-deep-get($material, 'text', 'disabled')

&:not(.v-list-item--active):not(.v-list-item--disabled)
color: map-deep-get($material, 'text', 'primary') !important
color: map-deep-get($material, 'text', 'primary')

.v-list-item__mask
color: map-deep-get($material, 'text', 'disabled')
Expand Down Expand Up @@ -265,3 +265,4 @@
-webkit-line-clamp: 2
-webkit-box-orient: vertical
display: -webkit-box

8 changes: 7 additions & 1 deletion packages/vuetify/src/components/VList/VListItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,12 @@ export default baseMixins.extend<options>().extend({

return attrs
},
toggle () {
if (this.to && this.inputValue === undefined) {
this.isActive = !this.isActive
}
this.$emit('change')
},
},

render (h): VNode {
Expand Down Expand Up @@ -182,6 +188,6 @@ export default baseMixins.extend<options>().extend({
})
: this.$slots.default

return h(tag, this.setTextColor(this.color, data), children)
return h(tag, this.isActive ? this.setTextColor(this.color, data) : data, children)
},
})
16 changes: 16 additions & 0 deletions packages/vuetify/src/components/VList/__tests__/VListItem.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,4 +218,20 @@ describe('VListItem.ts', () => {
})
expect(wrapper5.element.getAttribute('role')).toBe('listitem')
})

it('should not have an internal state unless its a router-link', async () => {
const wrapper = mountFunction({})

expect(wrapper.vm.isActive).toBeFalsy()
wrapper.vm.toggle()
expect(wrapper.vm.isActive).toBeFalsy()
wrapper.vm.toggle()
expect(wrapper.vm.isActive).toBeFalsy()

const wrapper2 = mountFunction({ propsData: { to: { name: 'test' } }, stubs: ['router-link'] })

expect(wrapper2.vm.isActive).toBeFalsy()
wrapper2.vm.toggle()
expect(wrapper2.vm.isActive).toBeTruthy()
})
})
87 changes: 82 additions & 5 deletions packages/vuetify/src/mixins/routable/__tests__/routable.spec.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,94 @@
import Routable from '../'
import { mount } from '@vue/test-utils'
import { createLocalVue, mount, Wrapper } from '@vue/test-utils'
import Router from 'vue-router'
import Vue, { VNode } from 'vue'

describe('routable.ts', () => {
let mountFunction: (options?: object) => Wrapper<Vue>
let router: Router
let localVue: typeof Vue

beforeEach(() => {
router = new Router()
localVue = createLocalVue()
localVue.use(Router)

mountFunction = (options = {}) => {
return mount({
mixins: [Routable],
props: {
activeClass: {
default: 'active',
},
exactActiveClass: {
default: 'exact-active',
},
},
render (h): VNode {
const { tag, data } = this.generateRouteLink()

data.attrs = {
...data.attrs,
}
data.on = {
...data.on,
}

return h(tag, data, this.$slots.default)
},
}, {
localVue,
router,
...options,
})
}
})
it('should generate exact route link with to="/" and undefined exact', async () => {
const wrapper = mount({
mixins: [Routable],
render: h => h('div'),
}, {
const wrapper = mountFunction({
propsData: {
to: '/',
},
})

expect(wrapper.vm.generateRouteLink().data.props.exact).toBe(true)
})

it('should reflect the link state to isActive', async () => {
const wrapper = mountFunction({
propsData: {
to: '/',
},
})
await wrapper.vm.$nextTick()
expect(wrapper.vm.isActive).toBe(true)

// Simulate route changing
wrapper.vm.$router.push('/foo')

await wrapper.vm.$nextTick()
await wrapper.vm.$nextTick()
expect(wrapper.vm.isActive).toBe(false)

wrapper.vm.$router.push('/')
await wrapper.vm.$nextTick()
await wrapper.vm.$nextTick()
expect(wrapper.vm.isActive).toBe(true)
})

it('should reflect the link state to isActive if not exact', async () => {
const wrapper = mountFunction({
propsData: {
to: '/foo',
},
})
await wrapper.vm.$nextTick()
expect(wrapper.vm.isActive).toBe(false)

// Simulate route changing
wrapper.vm.$router.push('/foo')

await wrapper.vm.$nextTick()
await wrapper.vm.$nextTick()
expect(wrapper.vm.isActive).toBe(true)
})
})
13 changes: 10 additions & 3 deletions packages/vuetify/src/mixins/routable/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ export default Vue.extend({
$route: 'onRouteChange',
},

mounted () {
this.onRouteChange()
},

methods: {
click (e: MouseEvent): void {
this.$emit('click', e)
Expand Down Expand Up @@ -140,16 +144,19 @@ export default Vue.extend({
onRouteChange () {
if (!this.to || !this.$refs.link || !this.$route) return
const activeClass = `${this.activeClass} ${this.proxyClass || ''}`.trim()
const exactActiveClass = `${this.exactActiveClass} ${this.proxyClass || ''}`.trim() || activeClass

const path = `_vnode.data.class.${activeClass}`
const path = '_vnode.data.class.' + (this.exact ? exactActiveClass : activeClass)

this.$nextTick(() => {
/* istanbul ignore else */
if (getObjectValueByPath(this.$refs.link, path)) {
if (!getObjectValueByPath(this.$refs.link, path) === this.isActive) {
this.toggle()
}
})
},
toggle: () => { /* noop */ },
toggle () {
this.isActive = !this.isActive
},
},
})

0 comments on commit 3df308f

Please sign in to comment.