diff --git a/addons/rose/addon/components/rose/form/fieldset/index.hbs b/addons/rose/addon/components/rose/form/fieldset/index.hbs new file mode 100644 index 000000000..685644822 --- /dev/null +++ b/addons/rose/addon/components/rose/form/fieldset/index.hbs @@ -0,0 +1,20 @@ +
+ + {{yield to='title'}} + +
+ {{yield to='description'}} +
+ +
+ {{yield to='body'}} +
+
\ No newline at end of file diff --git a/addons/rose/addon/components/rose/form/fieldset/index.js b/addons/rose/addon/components/rose/form/fieldset/index.js new file mode 100644 index 000000000..4e2a7790e --- /dev/null +++ b/addons/rose/addon/components/rose/form/fieldset/index.js @@ -0,0 +1,11 @@ +import Component from '@glimmer/component'; +import { generateComponentID } from '../../../../utilities/component-auto-id'; + +export default class RoseFormFieldsetComponent extends Component { + // =attributes + + /** + * @type {string} + */ + id = generateComponentID(); +} diff --git a/addons/rose/addon/components/rose/form/fieldset/index.stories.mdx b/addons/rose/addon/components/rose/form/fieldset/index.stories.mdx new file mode 100644 index 000000000..9dd61a4c6 --- /dev/null +++ b/addons/rose/addon/components/rose/form/fieldset/index.stories.mdx @@ -0,0 +1,29 @@ +import { Meta, Story, Preview } from '@storybook/addon-docs/blocks'; +import { hbs } from 'ember-cli-htmlbars'; +import { action } from '@storybook/addon-actions'; +import { text, boolean, select } from '@storybook/addon-knobs'; + + + +# Form Fieldset + +Renders a simple fieldset with title, description and body. + +```html + + <:title>Title + <:description>Description + <:body>Rest of the form + +``` + + + {{ + template: hbs` + + <:title>Title + <:description>Description + <:body>Rest of the form + ` + }} + \ No newline at end of file diff --git a/addons/rose/addon/styles/rose/components/form/_fieldset.scss b/addons/rose/addon/styles/rose/components/form/_fieldset.scss new file mode 100644 index 000000000..8696ad562 --- /dev/null +++ b/addons/rose/addon/styles/rose/components/form/_fieldset.scss @@ -0,0 +1,14 @@ +@use '../../variables/sizing'; +@use '../../utilities/type'; + +.rose-form-fieldset { + .rose-form-fieldset-title { + @include type.type(l, bold); + } + + .rose-form-fieldset-description { + margin: sizing.rems(xxs) 0; + @include type.type(xs); + color: var(--ui-gray); + } +} diff --git a/addons/rose/addon/styles/rose/components/form/_index.scss b/addons/rose/addon/styles/rose/components/form/_index.scss index 815a1aaf5..73137ac8d 100644 --- a/addons/rose/addon/styles/rose/components/form/_index.scss +++ b/addons/rose/addon/styles/rose/components/form/_index.scss @@ -5,3 +5,4 @@ @import 'checkbox'; @import 'select'; @import 'radio'; +@import 'fieldset'; diff --git a/addons/rose/app/components/rose/form/fieldset.js b/addons/rose/app/components/rose/form/fieldset.js new file mode 100644 index 000000000..9619ad95c --- /dev/null +++ b/addons/rose/app/components/rose/form/fieldset.js @@ -0,0 +1 @@ +export { default } from 'rose/components/rose/form/fieldset'; diff --git a/addons/rose/tests/integration/components/rose/form/fieldset-test.js b/addons/rose/tests/integration/components/rose/form/fieldset-test.js new file mode 100644 index 000000000..d2e2742c1 --- /dev/null +++ b/addons/rose/tests/integration/components/rose/form/fieldset-test.js @@ -0,0 +1,59 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render, find } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; + +module('Integration | Component | rose/form/fieldset', function (hooks) { + setupRenderingTest(hooks); + + // Global values for mocking + this.mockTitle = 'Title'; + this.mockDescription = 'Description'; + this.mockBody = 'Rest of the form'; + + hooks.beforeEach(async function () { + // Render the component before each test + await render(hbs` + + <:title>{{this.mockTitle}} + <:description>{{this.mockDescription}} + <:body>{{this.mockBody}} + + `); + }); + + test('it renders', async function (assert) { + assert.expect(4); + assert.ok(find('.rose-form-fieldset')); + assert.equal( + find('.rose-form-fieldset-title').textContent.trim(), + this.mockTitle + ); + assert.equal( + find('.rose-form-fieldset-description').textContent.trim(), + this.mockDescription + ); + assert.equal( + find('.rose-form-fieldset-body').textContent.trim(), + this.mockBody + ); + }); + + test('it supports aria description for title', async function (assert) { + assert.expect(2); + const titleElement = find('.rose-form-fieldset-title'); + const descriptionElement = find('.rose-form-fieldset-description'); + + assert.equal( + titleElement.getAttribute('aria-describedBy'), + descriptionElement.id, + 'Title is described by description' + ); + + assert.equal( + descriptionElement.getAttribute('aria-labelledBy'), + titleElement.id, + 'Description is labelled by title' + ); + }); +});