Skip to content

Commit

Permalink
Merge pull request #83 from phorest/feature/listbox-transitions
Browse files Browse the repository at this point in the history
✨ Feature: listbox transitions
  • Loading branch information
alexlafroscia authored Sep 16, 2021
2 parents 139bcf5 + 1854f46 commit 7794733
Show file tree
Hide file tree
Showing 5 changed files with 195 additions and 4 deletions.
24 changes: 24 additions & 0 deletions tests/dummy/app/controllers/listbox/listbox-with-transition.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Controller from '@ember/controller';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';

const PEOPLE = [
{ id: 1, name: 'Durward Reynolds', unavailable: false },
{ id: 2, name: 'Kenton Towne', unavailable: false },
{ id: 3, name: 'Therese Wunsch', unavailable: false },
{ id: 4, name: 'Benedict Kessler', unavailable: true },
{ id: 5, name: 'Katelyn Rohan', unavailable: false },
];

export default class ListboxWithTransitionController extends Controller {
@tracked selectedPerson = PEOPLE[0];

get people() {
return PEOPLE;
}

@action
setSelectedPerson(person) {
this.selectedPerson = person;
}
}
1 change: 1 addition & 0 deletions tests/dummy/app/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Router.map(function () {

this.route('listbox', function () {
this.route('listbox-basic');
this.route('listbox-with-transition');
});

this.route('switch', function () {
Expand Down
4 changes: 4 additions & 0 deletions tests/dummy/app/templates/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
<li>
<LinkTo @route='listbox.listbox-basic'>Listbox (basic)</LinkTo>
</li>
<li>
<LinkTo @route='listbox.listbox-with-transition'>Listbox with
Transition</LinkTo>
</li>
</ul>
</li>
<li>
Expand Down
98 changes: 98 additions & 0 deletions tests/dummy/app/templates/listbox/listbox-with-transition.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<div class='w-72 top-16'>
<Listbox
@value={{this.selectedPerson}}
@onChange={{this.setSelectedPerson}}
as |listbox|
>
<listbox.Label>Select a person:</listbox.Label>
<listbox.Button
class='h-9 relative w-full py-2 pl-3 pr-10 text-left bg-white rounded-lg shadow-md cursor-default focus:outline-none focus-visible:ring-2 focus-visible:ring-opacity-75 focus-visible:ring-white focus-visible:ring-offset-orange-300 focus-visible:ring-offset-2 focus-visible:border-indigo-500 sm:text-sm'
>
<span class='block truncate'>{{this.selectedPerson.name}}</span>
<span
class='absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none'
>
<svg
xmlns='http://www.w3.org/2000/svg'
class='inline h-6 w-6 text-gray-400'
aria-hidden='true'
fill='none'
viewBox='0 0 24 24'
stroke='currentColor'
>
<path
stroke-linecap='round'
stroke-linejoin='round'
stroke-width='2'
d='M8 9l4-4 4 4m0 6l-4 4-4-4'
></path>
</svg>
</span>
</listbox.Button>
<Transition
@show={{listbox.isOpen}}
@appear={{true}}
@enter='transition duration-300'
@enterFrom='opacity-0'
@enterTo='opacity-100'
@leave='transition duration-300'
@leaveFrom='opacity-100'
@leaveTo='opacity-0'
class='absolute w-full'
>
<listbox.Options
@isOpen={{true}}
class='z-30 max-w-md w-full py-1 mt-1 overflow-auto text-base bg-white rounded-md shadow-lg max-h-60 ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm'
as |options|
>
{{#each this.people as |person|}}
<options.Option
@key={{person.id}}
@value={{person}}
@disabled={{person.unavailable}}
class='outline-none'
as |option|
>
<span
class='block truncate cursor-default select-none relative py-2 pl-10 pr-4
{{if option.selected 'font-medium' 'font-normal'}}
{{if
option.active
'text-yellow-900 bg-yellow-100'
'text-gray-900'
}}
'
>
<span class='{{if option.disabled 'text-gray-500'}}'>
{{person.name}}
</span>
{{#if option.selected}}
<span
class='absolute inset-y-0 left-0 flex items-center pl-3
{{if option.active 'text-yellow-600' 'text-yellow-600'}}
'
>
<svg
xmlns='http://www.w3.org/2000/svg'
class='inline h-6 w-6'
aria-hidden='true'
fill='none'
viewBox='0 0 24 24'
stroke='currentColor'
>
<path
stroke-linecap='round'
stroke-linejoin='round'
stroke-width='2'
d='M5 13l4 4L19 7'
></path>
</svg>
</span>
{{/if}}
</span>
</options.Option>
{{/each}}
</listbox.Options>
</Transition>
</Listbox>
</div>
72 changes: 68 additions & 4 deletions tests/integration/components/listbox-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
getListbox,
getListboxes,
} from '../../accessibility-assertions';
import Component from '@glimmer/component';

async function typeWord(word) {
word.split('').forEach((char) => {
Expand Down Expand Up @@ -372,10 +373,73 @@ module('Integration | Component | <Listbox>', function (hooks) {
});

module('Listbox composition', () => {
todo(
'test should be possible to wrap the Listbox.Options with a Transition component',
async function () {}
);
test('test should be possible to wrap the Listbox.Options with a Transition component', async function (assert) {
let order = [];

this.set('orderFn', (value) => {
order.push(value);
});

this.owner.register(
'component:debug',
class DebugComponent extends Component {
constructor() {
super(...arguments);
this.args.fn('Mounting - ' + this.args.name);
}

willDestroy() {
this.args.fn('Unmounting - ' + this.args.name);
}
}
);

await render(hbs`
<Listbox as |listbox|>
<listbox.Button data-test="headlessui-listbox-button-1">Trigger</listbox.Button>
<Debug @name="Listbox" @fn={{this.orderFn}}/>
<Transition @show={{listbox.isOpen}}>
<Debug @name="Transition" @fn={{this.orderFn}}/>
<listbox.Options
@isOpen={{true}}
as |options|>
<options.Option as |option|>
{{option.active}} {{option.selected}} {{option.disabled}}
<Debug @name="Listbox.Option" @fn={{this.orderFn}}/>
</options.Option>
</listbox.Options>
</Transition>
</Listbox>
`);

assertListboxButton({
state: ListboxState.InvisibleUnmounted,
attributes: { 'data-test': 'headlessui-listbox-button-1' },
});
assertListbox({ state: ListboxState.InvisibleUnmounted });

await click(getListboxButton());

assertListboxButton({
state: ListboxState.Visible,
attributes: { 'data-test': 'headlessui-listbox-button-1' },
});
assertListbox({
state: ListboxState.Visible,
textContent: 'false false false',
});

await click(getListboxButton());

// Verify that we tracked the `mounts` and `unmounts` in the correct order
assert.deepEqual(order, [
'Mounting - Listbox',
'Mounting - Transition',
'Mounting - Listbox.Option',
'Unmounting - Transition',
'Unmounting - Listbox.Option',
]);
});
});

module('Listbox keyboard actions', () => {
Expand Down

0 comments on commit 7794733

Please sign in to comment.