remove classname feature (#607)

* change className to class

Co-authored-by: Ryan Johnston <ryan@magic.nz>

* drop className as a function in Vue

* update changelog

Co-authored-by: Ryan Johnston <ryan@magic.nz>
This commit is contained in:
Robin Malfait
2021-06-09 13:42:00 +02:00
committed by GitHub
parent 045b843f5b
commit f73491f4ac
8 changed files with 17 additions and 162 deletions
+1
View File
@@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Improve React peer dependency version range ([#544](https://github.com/tailwindlabs/headlessui/pull/544))
- Improve types for the `open` prop in the `Dialog` component ([#550](https://github.com/tailwindlabs/headlessui/pull/550))
- Improve `aria-expanded` logic ([#592](https://github.com/tailwindlabs/headlessui/pull/592))
- Remove undocumented `:className` prop ([#607](https://github.com/tailwindlabs/headlessui/pull/607))
## [Unreleased - Vue]
@@ -1,6 +1,6 @@
<template>
<div className="container my-24">
<div className="prose">
<div class="container my-24">
<div class="prose">
<h2>Examples</h2>
<Examples :examples="examples" />
</div>
@@ -479,84 +479,6 @@ describe('Rendering', () => {
})
describe('Rendering composition', () => {
it(
'should be possible to conditionally render classNames (aka className can be a function?!)',
suppressConsoleLogs(async () => {
renderTemplate({
template: html`
<Listbox v-model="value">
<ListboxButton>Trigger</ListboxButton>
<ListboxOptions>
<ListboxOption value="a" :className="JSON.stringify">
Option A
</ListboxOption>
<ListboxOption value="b" disabled :className="JSON.stringify">
Option B
</ListboxOption>
<ListboxOption value="c" className="no-special-treatment">
Option C
</ListboxOption>
</ListboxOptions>
</Listbox>
`,
setup: () => ({ value: ref(null) }),
})
assertListboxButton({
state: ListboxState.InvisibleUnmounted,
attributes: { id: 'headlessui-listbox-button-1' },
})
assertListbox({ state: ListboxState.InvisibleUnmounted })
// Open Listbox
await click(getListboxButton())
let options = getListboxOptions()
// Verify correct classNames
expect('' + options[0].classList).toEqual(
JSON.stringify({ active: false, selected: false, disabled: false })
)
expect('' + options[1].classList).toEqual(
JSON.stringify({ active: false, selected: false, disabled: true })
)
expect('' + options[2].classList).toEqual('no-special-treatment')
// Double check that nothing is active
assertNoActiveListboxOption(getListbox())
// Make the first option active
await press(Keys.ArrowDown)
// Verify the classNames
expect('' + options[0].classList).toEqual(
JSON.stringify({ active: true, selected: false, disabled: false })
)
expect('' + options[1].classList).toEqual(
JSON.stringify({ active: false, selected: false, disabled: true })
)
expect('' + options[2].classList).toEqual('no-special-treatment')
// Double check that the first option is the active one
assertActiveListboxOption(options[0])
// Let's go down, this should go to the third option since the second option is disabled!
await press(Keys.ArrowDown)
// Verify the classNames
expect('' + options[0].classList).toEqual(
JSON.stringify({ active: false, selected: false, disabled: false })
)
expect('' + options[1].classList).toEqual(
JSON.stringify({ active: false, selected: false, disabled: true })
)
expect('' + options[2].classList).toEqual('no-special-treatment')
// Double check that the last option is the active one
assertActiveListboxOption(options[2])
})
)
it(
'should be possible to swap the Listbox option with a button for example',
suppressConsoleLogs(async () => {
@@ -19,7 +19,6 @@ import { Features, render, omit } from '../../utils/render'
import { useId } from '../../hooks/use-id'
import { Keys } from '../../keyboard'
import { calculateActiveIndex, Focus } from '../../utils/calculate-active-index'
import { resolvePropValue } from '../../utils/resolve-prop-value'
import { dom } from '../../utils/dom'
import { useWindowEvent } from '../../hooks/use-window-event'
import { useOpenClosed, State, useOpenClosedProvider } from '../../internal/open-closed'
@@ -474,7 +473,6 @@ export let ListboxOption = defineComponent({
value: { type: [Object, String] },
disabled: { type: Boolean, default: false },
class: { type: [String, Function], required: false },
className: { type: [String, Function], required: false },
},
setup(props, { slots, attrs }) {
let api = useListboxContext('ListboxOption')
@@ -548,13 +546,13 @@ export let ListboxOption = defineComponent({
}
return () => {
let { disabled, class: defaultClass, className = defaultClass } = props
let { disabled, class: defaultClass } = props
let slot = { active: active.value, selected: selected.value, disabled }
let propsWeControl = {
id,
role: 'option',
tabIndex: disabled === true ? undefined : -1,
class: resolvePropValue(className, slot),
class: defaultClass,
'aria-disabled': disabled === true ? true : undefined,
'aria-selected': selected.value === true ? selected.value : undefined,
disabled: undefined, // Never forward the `disabled` prop
@@ -633,60 +633,6 @@ describe('Rendering', () => {
})
describe('Rendering composition', () => {
it('should be possible to conditionally render classNames (aka className can be a function?!)', async () => {
renderTemplate(jsx`
<Menu>
<MenuButton>Trigger</MenuButton>
<MenuItems>
<MenuItem as="a" :className="JSON.stringify">Item A</MenuItem>
<MenuItem as="a" disabled :className="JSON.stringify">Item B</MenuItem>
<MenuItem as="a" class="no-special-treatment">Item C</MenuItem>
</MenuItems>
</Menu>
`)
assertMenuButton({
state: MenuState.InvisibleUnmounted,
attributes: { id: 'headlessui-menu-button-1' },
})
assertMenu({ state: MenuState.InvisibleUnmounted })
// Open menu
await click(getMenuButton())
let items = getMenuItems()
// Verify correct classNames
expect('' + items[0].classList).toEqual(JSON.stringify({ active: false, disabled: false }))
expect('' + items[1].classList).toEqual(JSON.stringify({ active: false, disabled: true }))
expect('' + items[2].classList).toEqual('no-special-treatment')
// Double check that nothing is active
assertNoActiveMenuItem()
// Make the first item active
await press(Keys.ArrowDown)
// Verify the classNames
expect('' + items[0].classList).toEqual(JSON.stringify({ active: true, disabled: false }))
expect('' + items[1].classList).toEqual(JSON.stringify({ active: false, disabled: true }))
expect('' + items[2].classList).toEqual('no-special-treatment')
// Double check that the first item is the active one
assertMenuLinkedWithMenuItem(items[0])
// Let's go down, this should go to the third item since the second item is disabled!
await press(Keys.ArrowDown)
// Verify the classNames
expect('' + items[0].classList).toEqual(JSON.stringify({ active: false, disabled: false }))
expect('' + items[1].classList).toEqual(JSON.stringify({ active: false, disabled: true }))
expect('' + items[2].classList).toEqual('no-special-treatment')
// Double check that the last item is the active one
assertMenuLinkedWithMenuItem(items[2])
})
it(
'should be possible to swap the menu item with a button for example',
suppressConsoleLogs(async () => {
@@ -734,22 +680,22 @@ describe('Rendering composition', () => {
template: jsx`
<Menu>
<MenuButton>Trigger</MenuButton>
<div className="outer">
<div class="outer">
<MenuItems>
<div className="py-1 inner">
<div class="py-1 inner">
<MenuItem as="button">Item A</MenuItem>
<MenuItem as="button">Item B</MenuItem>
</div>
<div className="py-1 inner">
<div class="py-1 inner">
<MenuItem as="button">Item C</MenuItem>
<MenuItem>
<div>
<div className="outer">Item D</div>
<div class="outer">Item D</div>
</div>
</MenuItem>
</div>
<div className="py-1 inner">
<form className="inner">
<div class="py-1 inner">
<form class="inner">
<MenuItem as="button">Item E</MenuItem>
</form>
</div>
@@ -15,7 +15,6 @@ import { Features, render } from '../../utils/render'
import { useId } from '../../hooks/use-id'
import { Keys } from '../../keyboard'
import { Focus, calculateActiveIndex } from '../../utils/calculate-active-index'
import { resolvePropValue } from '../../utils/resolve-prop-value'
import { dom } from '../../utils/dom'
import { useWindowEvent } from '../../hooks/use-window-event'
import { useTreeWalker } from '../../hooks/use-tree-walker'
@@ -413,7 +412,6 @@ export let MenuItem = defineComponent({
as: { type: [Object, String], default: 'template' },
disabled: { type: Boolean, default: false },
class: { type: [String, Function], required: false },
className: { type: [String, Function], required: false },
},
setup(props, { slots, attrs }) {
let api = useMenuContext('MenuItem')
@@ -467,13 +465,13 @@ export let MenuItem = defineComponent({
}
return () => {
let { disabled, class: defaultClass, className = defaultClass } = props
let { disabled, class: defaultClass } = props
let slot = { active: active.value, disabled }
let propsWeControl = {
id,
role: 'menuitem',
tabIndex: disabled === true ? undefined : -1,
class: resolvePropValue(className, slot),
class: defaultClass,
'aria-disabled': disabled === true ? true : undefined,
onClick: handleClick,
onFocus: handleFocus,
@@ -20,7 +20,6 @@ import { useId } from '../../hooks/use-id'
import { render } from '../../utils/render'
import { Label, useLabels } from '../label/label'
import { Description, useDescriptions } from '../description/description'
import { resolvePropValue } from '../../utils/resolve-prop-value'
import { useTreeWalker } from '../../hooks/use-tree-walker'
interface Option {
@@ -234,16 +233,9 @@ export let RadioGroupOption = defineComponent({
value: { type: [Object, String, Number, Boolean] },
disabled: { type: Boolean, default: false },
class: { type: [String, Function], required: false },
className: { type: [String, Function], required: false },
},
render() {
let {
value,
disabled,
class: defaultClass,
className = defaultClass,
...passThroughProps
} = this.$props
let { value, disabled, class: defaultClass, ...passThroughProps } = this.$props
let slot = {
checked: this.checked,
@@ -255,7 +247,7 @@ export let RadioGroupOption = defineComponent({
id: this.id,
ref: 'el',
role: 'radio',
class: resolvePropValue(className, slot),
class: defaultClass,
'aria-checked': this.checked ? 'true' : 'false',
'aria-labelledby': this.labelledby,
'aria-describedby': this.describedby,
@@ -12,7 +12,6 @@ import {
import { render } from '../../utils/render'
import { useId } from '../../hooks/use-id'
import { Keys } from '../../keyboard'
import { resolvePropValue } from '../../utils/resolve-prop-value'
import { Label, useLabels } from '../label/label'
import { Description, useDescriptions } from '../description/description'
@@ -63,11 +62,10 @@ export let Switch = defineComponent({
as: { type: [Object, String], default: 'button' },
modelValue: { type: Boolean, default: false },
class: { type: [String, Function], required: false },
className: { type: [String, Function], required: false },
},
render() {
let api = inject(GroupContext, null)
let { class: defaultClass, className = defaultClass } = this.$props
let { class: defaultClass } = this.$props
let slot = { checked: this.$props.modelValue }
let propsWeControl = {
@@ -75,7 +73,7 @@ export let Switch = defineComponent({
ref: api === null ? undefined : api.switchRef,
role: 'switch',
tabIndex: 0,
class: resolvePropValue(className, slot),
class: defaultClass,
'aria-checked': this.$props.modelValue,
'aria-labelledby': this.labelledby,
'aria-describedby': this.describedby,