Skip to content

Commit

Permalink
Merge pull request #469 from appuniversum/chore/accordion-default-ope…
Browse files Browse the repository at this point in the history
…n-state

Add a `isOpenInitially` argument to the `AuAccordion` component
  • Loading branch information
Windvis authored Feb 16, 2024
2 parents 40bf920 + 7b6bdb0 commit 0916aec
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 65 deletions.
Original file line number Diff line number Diff line change
@@ -1,22 +1,43 @@
import {
AuButton,
AuContent,
AuIcon,
AuLoader,
AuToolbar,
} from '@appuniversum/ember-appuniversum';
import { on } from '@ember/modifier';
import { action } from '@ember/object';
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { modifier } from 'ember-modifier';
import AuButton from './au-button';
import AuContent from './au-content';
import AuIcon from './au-icon';
import AuLoader from './au-loader';
import AuToolbar from './au-toolbar';

const autofocus = modifier(function autofocus(element) {
const autofocus = modifier(function autofocus(element: HTMLElement) {
element.focus();
});

export default class AuAccordion extends Component {
@tracked isOpen = false;
export interface AuAccordionSignature {
Args: {
buttonLabel?: string;
iconClosed?: string;
iconOpen?: string;
isOpenInitially?: boolean;
loading?: boolean;
reverse?: boolean;
skin?: 'border';
subtitle?: string;
};
Blocks: {
default: [];
};
Element: HTMLDivElement;
}

export default class AuAccordion extends Component<AuAccordionSignature> {
@tracked isOpen;

constructor(owner: unknown, args: AuAccordionSignature['Args']) {
super(owner, args);

this.isOpen = Boolean(this.args.isOpenInitially);
}

get loading() {
if (this.args.loading) return 'is-loading';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
import type { TOC } from '@ember/component/template-only';
import Component from '@glimmer/component';

export default class AuToolbar extends Component {
export interface AuToolbarSignature {
Args: {
reverse?: boolean;
border?: 'top' | 'bottom';
skin?: 'tint';
size?: 'small' | 'medium' | 'large';
nowrap?: boolean;
};
Blocks: {
default: [typeof Group];
};
Element: HTMLDivElement;
}

export default class AuToolbar extends Component<AuToolbarSignature> {
get reverse() {
if (this.args.reverse) return 'au-c-toolbar--reverse';
else return '';
Expand Down Expand Up @@ -44,7 +59,14 @@ export default class AuToolbar extends Component {
</template>
}

const Group = <template>
interface GroupSignature {
Blocks: {
default: [];
};
Element: HTMLDivElement;
}

const Group: TOC<GroupSignature> = <template>
<div class="au-c-toolbar__group" ...attributes>
{{yield}}
</div>
Expand Down
4 changes: 4 additions & 0 deletions addon/template-registry.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Components
import type AuAccordion from '@appuniversum/ember-appuniversum/components/au-accordion';
import type AuAlert from '@appuniversum/ember-appuniversum/components/au-alert';
import type AuApp from '@appuniversum/ember-appuniversum/components/au-app';
import type AuBadge from '@appuniversum/ember-appuniversum/components/au-badge';
Expand All @@ -18,12 +19,14 @@ import type AuLinkExternal from '@appuniversum/ember-appuniversum/components/au-
import type AuLink from '@appuniversum/ember-appuniversum/components/au-link';
import type AuList from '@appuniversum/ember-appuniversum/components/au-list';
import type AuLoader from '@appuniversum/ember-appuniversum/components/au-loader';
import type AuToolbar from '@appuniversum/ember-appuniversum/components/au-toolbar';

// Modifiers
import type AuDateInputModifier from '@appuniversum/ember-appuniversum/modifiers/au-date-input';

export default interface AppuniversumRegistry {
// Components
AuAccordion: typeof AuAccordion;
AuAlert: typeof AuAlert;
AuApp: typeof AuApp;
AuBadge: typeof AuBadge;
Expand All @@ -43,6 +46,7 @@ export default interface AppuniversumRegistry {
AuLink: typeof AuLink;
AuList: typeof AuList;
AuLoader: typeof AuLoader;
AuToolbar: typeof AuToolbar;

// Modifiers
'au-date-input': typeof AuDateInputModifier;
Expand Down
7 changes: 7 additions & 0 deletions stories/5-components/Content/AuAccordion.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ export default {
control: 'boolean',
description: 'Adds a loading state to the button',
},
isOpenInitially: {
control: 'boolean',
description:
'When set to `true`, this will render the accordion in the "open" state from the start.',
},
},
parameters: {
layout: 'padded',
Expand All @@ -50,6 +55,7 @@ const Template = (args) => ({
@iconClosed={{this.iconClosed}}
@buttonLabel={{this.buttonLabel}}
@loading={{this.loading}}
@isOpenInitially={{this.isOpenInitially}}
>
<p>I am information. I can even contain a <AuLink>A Link</AuLink>!</p>
</AuAccordion>`,
Expand All @@ -65,4 +71,5 @@ Component.args = {
iconClosed: 'nav-right',
buttonLabel: 'Accordion with arrows',
loading: false,
isOpenInitially: false,
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { module, test } from 'qunit';
import AuAccordion from '@appuniversum/ember-appuniversum/components/au-accordion';
import { click, settled, render } from '@ember/test-helpers';
import { tracked } from '@glimmer/tracking';
import { setupRenderingTest } from 'ember-qunit';
import { click, render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
import { module, test } from 'qunit';

const ACCORDION = {
TOGGLE: '[data-test-accordion-toggle]',
Expand All @@ -13,25 +14,47 @@ const ACCORDION = {
LOADER: '[data-test-accordion-loader]',
};

class TestState {
@tracked iconClosed?: string;
@tracked iconOpen?: string;
@tracked isLoading?: boolean;
}

module('Integration | Component | au-accordion', function (hooks) {
setupRenderingTest(hooks);

test("it doesn't render any content when initially rendered", async function (assert) {
await render(hbs`
<AuAccordion>
Content
</AuAccordion>
`);
await render(
<template>
<AuAccordion>
Content
</AuAccordion>
</template>,
);

assert.dom(ACCORDION.CONTENT).doesNotExist();
});

test('it renders the content by default if `isOpenInitially` is set to `true`', async function (assert) {
await render(
<template>
<AuAccordion @isOpenInitially={{true}}>
Content
</AuAccordion>
</template>,
);

assert.dom(ACCORDION.CONTENT).exists().hasText('Content');
});

test('it toggles its content rendering when clicking it', async function (assert) {
await render(hbs`
<AuAccordion>
Some content
</AuAccordion>
`);
await render(
<template>
<AuAccordion>
Some content
</AuAccordion>
</template>,
);

await toggleAccordion();
assert.dom(ACCORDION.CONTENT).exists().hasText('Some content');
Expand All @@ -41,31 +64,37 @@ module('Integration | Component | au-accordion', function (hooks) {
});

test('it can display a subtitle', async function (assert) {
await render(hbs`
<AuAccordion @subtitle="Foo">
Some content
</AuAccordion>
`);
await render(
<template>
<AuAccordion @subtitle="Foo">
Some content
</AuAccordion>
</template>,
);

assert.dom(ACCORDION.SUBTITLE).exists().hasText('Foo');
});

test('it supports changing the label of the toggle button', async function (assert) {
await render(hbs`
<AuAccordion @buttonLabel="Foo button">
Some content
</AuAccordion>
`);
await render(
<template>
<AuAccordion @buttonLabel="Foo button">
Some content
</AuAccordion>
</template>,
);

assert.dom(ACCORDION.BUTTON).exists().hasText('Foo button');
});

test('it shows a different icon depending on the open state', async function (assert) {
await render(hbs`
<AuAccordion>
Some content
</AuAccordion>
`);
await render(
<template>
<AuAccordion>
Some content
</AuAccordion>
</template>,
);

assert.dom(ACCORDION.ICON_OPEN).doesNotExist();
assert.dom(ACCORDION.ICON_CLOSED).exists();
Expand All @@ -76,17 +105,24 @@ module('Integration | Component | au-accordion', function (hooks) {
});

test('it supports choosing different icons', async function (assert) {
await render(hbs`
<AuAccordion @iconOpen={{this.iconOpen}} @iconClosed={{this.iconClosed}}>
Some content
</AuAccordion>
`);
const state = new TestState();
await render(
<template>
<AuAccordion
@iconOpen={{state.iconOpen}}
@iconClosed={{state.iconClosed}}
>
Some content
</AuAccordion>
</template>,
);

assert
.dom(ACCORDION.ICON_CLOSED)
.hasAttribute('data-test-accordion-icon-closed', 'nav-right');

this.set('iconClosed', 'other-closed-icon');
state.iconClosed = 'other-closed-icon';
await settled();

assert
.dom(ACCORDION.ICON_CLOSED)
Expand All @@ -97,35 +133,42 @@ module('Integration | Component | au-accordion', function (hooks) {
.dom(ACCORDION.ICON_OPEN)
.hasAttribute('data-test-accordion-icon-open', 'nav-down');

this.set('iconOpen', 'other-open-icon');
state.iconOpen = 'other-open-icon';
await settled();

assert
.dom(ACCORDION.ICON_OPEN)
.hasAttribute('data-test-accordion-icon-open', 'other-open-icon');
});

test('it can show a loading indicator instead of content', async function (assert) {
this.isLoading = true;
const state = new TestState();
state.isLoading = true;

await render(hbs`
<AuAccordion @loading={{this.isLoading}}>Some content</AuAccordion>
`);
await render(
<template>
<AuAccordion @loading={{state.isLoading}}>Some content</AuAccordion>
</template>,
);

assert.dom(ACCORDION.LOADER).doesNotExist();

await toggleAccordion();
assert.dom(ACCORDION.LOADER).exists();
assert.dom(ACCORDION.CONTENT).doesNotContainText('Some content');

this.set('isLoading', false);
state.isLoading = false;
await settled();
assert.dom(ACCORDION.LOADER).doesNotExist();
assert.dom(ACCORDION.CONTENT).containsText('Some content');
});

test("it's possible to add extra html attributes", async function (assert) {
await render(hbs`
<AuAccordion class="test" data-test-accordion-external></AuAccordion>
`);
await render(
<template>
<AuAccordion class="test" data-test-accordion-external />
</template>,
);

assert.dom('[data-test-accordion-external]').exists().hasClass('test');
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
import AuToolbar from '@appuniversum/ember-appuniversum/components/au-toolbar';

module('Integration | Component | au-toolbar', function (hooks) {
setupRenderingTest(hooks);

test('it yields a group component', async function (assert) {
await render(hbs`
<AuToolbar as |Group|>
<Group data-test-foo>Foo</Group>
<Group data-test-bar>Bar</Group>
</AuToolbar>
`);
await render(
<template>
<AuToolbar as |Group|>
<Group data-test-foo>Foo</Group>
<Group data-test-bar>Bar</Group>
</AuToolbar>
</template>,
);

assert.dom('[data-test-foo]').hasText('Foo');
assert.dom('[data-test-bar]').hasText('Bar');
});

test('it passes through extra html attributes', async function (assert) {
await render(hbs`
<AuToolbar data-test-foo="bar"></AuToolbar>
`);
await render(<template><AuToolbar data-test-foo="bar" /></template>);

assert.dom('[data-test-foo]').exists();
});
Expand Down
Loading

0 comments on commit 0916aec

Please sign in to comment.