Skip to content

Commit

Permalink
yield a button that controls the expander
Browse files Browse the repository at this point in the history
  • Loading branch information
amk221 committed Feb 21, 2023
1 parent 591b870 commit a9618df
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 60 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- Remove `tabindex="0"`
- Add `role="region"`
- Swap `aria-expanded` for `data-expanded` and updated example usage
- Yield button to control expanding
- Use function helpers
- Update animation utils

Expand Down
9 changes: 9 additions & 0 deletions addon/components/expander/button.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<button
type="button"
class="expander__button"
aria-controls="{{@aria-controls}}"
aria-expanded="{{@aria-expanded}}"
...attributes
>
{{yield}}
</button>
12 changes: 9 additions & 3 deletions addon/components/expander/index.hbs
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
{{! template-lint-disable no-unsupported-role-attributes }}
{{this.registerContent
(component
this.ExpanderContent onInsert=this.registerContentElement style=this.style
{{this.registerComponents
(hash
Button=(component
this.ExpanderButton aria-controls=this.id aria-expanded=this.isExpanded
)
Content=(component
this.ExpanderContent onInsert=this.registerContentElement style=this.style
)
)
}}
<div
id={{this.id}}
class="expander"
data-transitioning="{{this.isTransitioning}}"
data-expanded="{{this.isExpanded}}"
Expand Down
11 changes: 9 additions & 2 deletions addon/components/expander/index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import Component from '@glimmer/component';
import ExpanderContent from './content';
import ExpanderButton from './button';
import { htmlSafe } from '@ember/template';
import { tracked } from '@glimmer/tracking';
import { waitFor } from '@ember/test-waiters';
import { next, scheduleOnce } from '@ember/runloop';
import { action } from '@ember/object';
import { task } from 'ember-concurrency';
import { guidFor } from '@ember/object/internals';
import { waitForAnimation } from '@zestia/animation-utils';
const { seal, assign } = Object;

Expand All @@ -15,18 +17,23 @@ class ExpanderComponent extends Component {
@tracked renderContent = !!this.args.expanded;
@tracked isTransitioning = false;

id = guidFor(this);

_api = {};
Content = null;
Button = null;
ExpanderContent = ExpanderContent;
ExpanderButton = ExpanderButton;

registerContent = (Content) => {
this.Content = Content;
registerComponents = (components) => {
assign(this, components);
};

get api() {
return seal(
assign(this._api, {
Content: this.renderContent ? this.Content : null,
Button: this.Button,
contentElement: this.contentElement,
toggle: this.toggle,
expand: this.expand,
Expand Down
1 change: 0 additions & 1 deletion app/components/expander/content.js

This file was deleted.

44 changes: 12 additions & 32 deletions tests/dummy/app/templates/application.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,10 @@
</h4>

<div class="demo">
<Expander id="example1" as |expander|>
<button
type="button"
aria-controls="example1"
aria-expanded="{{expander.isExpanded}}"
{{on "click" expander.toggle}}
>
<Expander as |expander|>
<expander.Button {{on "click" expander.toggle}}>
Toggle
</button>
</expander.Button>

<button type="button" {{on "click" this.toggleMore}}>
Toggle more content
Expand All @@ -36,15 +31,10 @@
Pre-expanded
</h4>

<Expander id="example2" @expanded={{true}} as |expander|>
<button
type="button"
aria-controls="example2"
aria-expanded="{{expander.isExpanded}}"
{{on "click" expander.toggle}}
>
<Expander @expanded={{true}} as |expander|>
<expander.Button {{on "click" expander.toggle}}>
Toggle
</button>
</expander.Button>

<expander.Content>
Hello
Expand All @@ -57,25 +47,15 @@
Nested
</h4>

<Expander id="example3" as |expander|>
<button
type="button"
aria-controls="example3"
aria-expanded="{{expander.isExpanded}}"
{{on "click" expander.toggle}}
>
<Expander as |expander|>
<expander.Button {{on "click" expander.toggle}}>
Toggle
</button>
</expander.Button>
<expander.Content>
<Expander id="example4" as |expander|>
<button
type="button"
aria-controls="example4"
aria-expanded="{{expander.isExpanded}}"
{{on "click" expander.toggle}}
>
<Expander as |expander|>
<expander.Button {{on "click" expander.toggle}}>
Toggle
</button>
</expander.Button>

<expander.Content>
Hello
Expand Down
93 changes: 71 additions & 22 deletions tests/integration/components/expander-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,35 @@ module('expander', function (hooks) {
assert.dom('.expander').hasAttribute('role', 'region');
});

test('it render a button', async function (assert) {
assert.expect(2);

await render(hbs`
<Expander as |expander|>
<expander.Button />
</Expander>
`);

assert.ok(
find('.expander')
.getAttribute('id')
.match(/[\w\d]+/)
);

assert
.dom('.expander__button')
.hasAttribute('aria-controls', find('.expander').getAttribute('id'));
});

test('expanding', async function (assert) {
assert.expect(9);
assert.expect(11);

await render(hbs`
<Expander as |expander|>
<button type="button" {{on "click" expander.expand}}></button>
<expander.Button {{on "click" expander.expand}}>
Expand
</expander.Button>
<expander.Content>
<div class="test-internal-height"></div>
</expander.Content>
Expand All @@ -53,14 +76,16 @@ module('expander', function (hooks) {

assert.dom('.expander').hasAttribute('data-expanded', 'false');
assert.dom('.expander').hasAttribute('data-transitioning', 'false');
assert.dom('.expander__button').hasAttribute('aria-expanded', 'false');
assert.dom('.expander__content').doesNotExist();

click('button');
click('.expander__button');

await waitFor('.expander');

assert.dom('.expander').hasAttribute('data-expanded', 'true');
assert.dom('.expander').hasAttribute('data-transitioning', 'true');
assert.dom('.expander__button').hasAttribute('aria-expanded', 'true');
assert.dom('.expander__content').exists();
assert.dom('.expander__content').hasAttribute('style', 'max-height: 10px');

Expand All @@ -73,11 +98,14 @@ module('expander', function (hooks) {
});

test('collapsing', async function (assert) {
assert.expect(9);
assert.expect(11);

await render(hbs`
<Expander @expanded={{true}} as |expander|>
<button type="button" {{on "click" expander.collapse}}></button>
<expander.Button {{on "click" expander.collapse}}>
Collapse
</expander.Button>
<expander.Content>
<div class="test-internal-height"></div>
</expander.Content>
Expand All @@ -86,15 +114,17 @@ module('expander', function (hooks) {

assert.dom('.expander').hasAttribute('data-expanded', 'true');
assert.dom('.expander').hasAttribute('data-transitioning', 'false');
assert.dom('.expander__button').hasAttribute('aria-expanded', 'true');
assert.dom('.expander__content').exists();
assert.dom('.expander__content').hasAttribute('style', '');

click('button');
click('.expander__button');

await waitFor('.expander');

assert.dom('.expander').hasAttribute('data-expanded', 'false');
assert.dom('.expander').hasAttribute('data-transitioning', 'true');
assert.dom('.expander__button').hasAttribute('aria-expanded', 'false');
assert.dom('.expander__content').hasAttribute('style', 'max-height: 0px');

await waitForAnimation('.expander__content', {
Expand All @@ -117,17 +147,20 @@ module('expander', function (hooks) {
@onCollapsed={{this.handleCollapsed}}
as |expander|
>
<button type="button" {{on "click" expander.toggle}}></button>
<expander.Button {{on "click" expander.toggle}}>
Toggle
</expander.Button>
<expander.Content>
Hello World
</expander.Content>
</Expander>
`);

click('button');
click('.expander__button');

await waitUntil(this.midWay);
await click('button');
await click('.expander__button');

assert.verifySteps(['collapsed']);
});
Expand All @@ -142,7 +175,10 @@ module('expander', function (hooks) {
@onCollapsed={{this.handleCollapsed}}
as |expander|
>
<button type="button" {{on "click" expander.toggle}}></button>
<expander.Button {{on "click" expander.toggle}}>
Toggle
</expander.Button>
<expander.Content>
Hello World
</expander.Content>
Expand All @@ -152,10 +188,10 @@ module('expander', function (hooks) {
this.set('handleExpanded', () => assert.step('expanded'));
this.set('handleCollapsed', () => assert.step('collapsed'));

click('button');
click('.expander__button');

await waitUntil(this.midWay);
await click('button');
await click('.expander__button');

assert.verifySteps(['expanded']);
});
Expand All @@ -177,6 +213,7 @@ module('expander', function (hooks) {
keys(this.api),
[
'Content',
'Button',
'contentElement',
'toggle',
'expand',
Expand Down Expand Up @@ -214,18 +251,21 @@ module('expander', function (hooks) {
@onCollapsed={{this.handleCollapsed}}
as |expander|
>
<button type="button" {{on "click" expander.toggle}}></button>
<expander.Button {{on "click" expander.toggle}}>
Toggle
</expander.Button>
<expander.Content>
Hello World
</expander.Content>
</Expander>
`);

await click('button');
await click('.expander__button');

assert.verifySteps(['expanded']);

await click('button');
await click('.expander__button');

assert.verifySteps(['collapsed']);
});
Expand All @@ -241,15 +281,18 @@ module('expander', function (hooks) {
@onCollapsed={{this.handleCollapsed}}
as |expander|
>
<button type="button" {{on "click" expander.collapse}}></button>
<expander.Button {{on "click" expander.collapse}}>
Collapse
</expander.Button>
<expander.Content>
Hello World
</expander.Content>
</Expander>
`);

click('button');
await click('button');
click('.expander__button');
await click('.expander__button');

assert.verifySteps(['collapsed']);
});
Expand All @@ -261,15 +304,18 @@ module('expander', function (hooks) {

await render(hbs`
<Expander @onExpanded={{this.handleExpanded}} as |expander|>
<button type="button" {{on "click" expander.expand}}></button>
<expander.Button {{on "click" expander.expand}}>
Expand
</expander.Button>
<expander.Content>
Hello World
</expander.Content>
</Expander>
`);

click('button');
await click('button');
click('.expander__button');
await click('.expander__button');

assert.verifySteps(['expanded']);
});
Expand All @@ -281,7 +327,10 @@ module('expander', function (hooks) {

await render(hbs`
<Expander @expanded={{true}} @onExpanded={{this.handleExpanded}} as |expander|>
<button type="button" {{on "click" expander.expand}}></button>
<expander.Button {{on "click" expander.expand}}>
Expand
</expander.Button>
<expander.Content>
Hello World
</expander.Content>
Expand Down

0 comments on commit a9618df

Please sign in to comment.