From 02b6afa5e752d5e077c65574bace96a4a3e0c3dd Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Fri, 11 Nov 2022 13:45:35 -0800 Subject: [PATCH] refactor: migrate to HDS select form fields (#1447) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: 🤖 install HDS and associated assets * chore: 🤖 bump HDS version * refactor: 💡 optimize hds/icon addon content build * test: 💍 fix intermittent test failure * refactor: 💡 replace auth method selects with HDS select * refactor: 💡 update storybook and tests to reflect HDS selects * style: 💄 fix style linting issue * fix: 🐛 fix bad scss syntax * fix: 🐛 fix scss syntax again * refactor: 💡 remove references to rose/form/select * chore: 🤖 experimental HDS dark mode * refactor: 💡 add custom set helper to replace action helper * chore: 🤖 remove HDS dark mode, to be implemented in another pr * refactor: 💡 apply custom dark mode for HDS * chore: 🤖 add tier 2 color tweaks for better dark mode contrast * chore: 🤖 tweak HDS form borders in dark mode * docs: ✏️ add set function comment Co-authored-by: Dharini Jeeva --- .../rose/addon/components/rose/form/index.hbs | 2 +- .../components/rose/form/index.stories.mdx | 56 +++--- .../components/rose/form/select/index.hbs | 57 ------ .../components/rose/form/select/index.js | 8 - .../rose/form/select/index.stories.mdx | 146 ++++----------- .../rose/form/select/select/index.hbs | 13 -- addons/rose/addon/helpers/set-from-event.js | 11 ++ .../styles/hds/themes/dark-mode/index.scss | 1 + .../rose/app/components/rose/form/select.js | 1 - .../app/components/rose/form/select/select.js | 1 - addons/rose/app/helpers/set-from-event.js | 1 + .../styles/rose/components/table/_table.scss | 4 +- addons/rose/package.json | 1 - .../integration/components/rose/form-test.js | 24 ++- .../components/rose/form/select-test.js | 174 ------------------ .../helpers/set-from-event-test.js | 56 ++++++ .../form/auth-method/oidc/index.hbs | 118 +++++++----- yarn.lock | 35 +--- 18 files changed, 228 insertions(+), 481 deletions(-) delete mode 100644 addons/rose/addon/components/rose/form/select/index.hbs delete mode 100644 addons/rose/addon/components/rose/form/select/index.js delete mode 100644 addons/rose/addon/components/rose/form/select/select/index.hbs create mode 100644 addons/rose/addon/helpers/set-from-event.js delete mode 100644 addons/rose/app/components/rose/form/select.js delete mode 100644 addons/rose/app/components/rose/form/select/select.js create mode 100644 addons/rose/app/helpers/set-from-event.js delete mode 100644 addons/rose/tests/integration/components/rose/form/select-test.js create mode 100644 addons/rose/tests/integration/helpers/set-from-event-test.js diff --git a/addons/rose/addon/components/rose/form/index.hbs b/addons/rose/addon/components/rose/form/index.hbs index ff5e57f75..eec51ee3b 100644 --- a/addons/rose/addon/components/rose/form/index.hbs +++ b/addons/rose/addon/components/rose/form/index.hbs @@ -22,7 +22,6 @@ 'rose/form/checkbox/group' disabled=this.disabled ) input=(component 'rose/form/input' disabled=this.disabled) - select=(component 'rose/form/select' disabled=this.disabled) textarea=(component 'rose/form/textarea' disabled=this.disabled) fieldset=(component 'rose/form/fieldset') actions=(component @@ -37,6 +36,7 @@ enableEdit=this.enableEdit ) isEditable=this.isEditable + disabled=this.disabled ) }} \ No newline at end of file diff --git a/addons/rose/addon/components/rose/form/index.stories.mdx b/addons/rose/addon/components/rose/form/index.stories.mdx index ec9fc6288..5a90b6327 100644 --- a/addons/rose/addon/components/rose/form/index.stories.mdx +++ b/addons/rose/addon/components/rose/form/index.stories.mdx @@ -19,19 +19,22 @@ export const Template = (args) => ({ > - - - Choose an option - Value 1 - Value 2 - Value 3 - - + Label + Helper text + + + + + + + @@ -76,19 +79,24 @@ export const Template = (args) => ({ > - - - Choose an option - Value 1 - Value 2 - Value 3 - - + Label + Helper text + + + + + + + + diff --git a/addons/rose/addon/components/rose/form/select/index.hbs b/addons/rose/addon/components/rose/form/select/index.hbs deleted file mode 100644 index 742e291ea..000000000 --- a/addons/rose/addon/components/rose/form/select/index.hbs +++ /dev/null @@ -1,57 +0,0 @@ -{{#if @contextual}} - {{yield - (hash - label=(component 'rose/form/label' for=this.id error=@error) - helperText=(component - 'rose/form/helper-text' id=(concat 'helper-text-' this.id) error=@error - ) - field=(component - 'rose/form/select/select' - id=this.id - name=@name - value=@value - onChange=@onChange - disabled=@disabled - error=@error - aria-describedby=(concat - (if @helperText (concat 'helper-text-' this.id)) - (if @error (concat ' errors-' this.id)) - ) - ) - errors=(component 'rose/form/errors' id=(concat 'errors-' this.id)) - ) - }} -{{else}} -
- - - {{@label}} - - - {{#if @helperText}} - - {{@helperText}} - - {{/if}} - - {{yield - (hash - field=(component - 'rose/form/select/select' - id=this.id - name=@name - value=@value - onChange=@onChange - disabled=@disabled - error=@error - aria-describedby=(concat - (if @helperText (concat 'helper-text-' this.id)) - (if @error (concat ' errors-' this.id)) - ) - ) - errors=(component 'rose/form/errors' id=(concat 'errors-' this.id)) - ) - }} - -
-{{/if}} \ No newline at end of file diff --git a/addons/rose/addon/components/rose/form/select/index.js b/addons/rose/addon/components/rose/form/select/index.js deleted file mode 100644 index fddc7dd2b..000000000 --- a/addons/rose/addon/components/rose/form/select/index.js +++ /dev/null @@ -1,8 +0,0 @@ -import Component from '@glimmer/component'; -import { generateComponentID } from '../../../../utilities/component-auto-id'; - -export default class RoseFormSelectComponent extends Component { - // =attributes - - id = generateComponentID(); -} diff --git a/addons/rose/addon/components/rose/form/select/index.stories.mdx b/addons/rose/addon/components/rose/form/select/index.stories.mdx index 26016a9c3..360707dd6 100644 --- a/addons/rose/addon/components/rose/form/select/index.stories.mdx +++ b/addons/rose/addon/components/rose/form/select/index.stories.mdx @@ -1,50 +1,52 @@ import { Meta, Story, Preview } from '@storybook/addon-docs'; import { hbs } from 'ember-cli-htmlbars'; - + -# Form Select +# Select (removed) -Renders a form select element. +Rose/Form/Select has been removed in favor of +[HDS::Form::Select](https://design-system-components-hashicorp.vercel.app/components/form/select). ```handlebars - - - Choose a color - Red - Green - Blue - - + Color + Set your desired color + + + + + + + ``` export const Template = (args) => ({ template: hbs` - - - Choose an option - Value 1 - Value 2 - Value 3 - - `, + {{label}} + {{helperText}} + + + + + + + `, context: args, }); @@ -53,10 +55,11 @@ export const Template = (args) => ({ name="Basic" height="10rem" args={{ - name: 'select-name', + name: 'select_name', label: 'Label', helperText: 'Helper text', disabled: false, + error: false, }} argTypes={{ value: { control: 'select', options: ['value-1', 'value-2', 'value-3'] }, @@ -66,78 +69,3 @@ export const Template = (args) => ({ {Template.bind({})} - -export const ErrorTemplate = (args) => ({ - template: hbs` - - - Choose an option - Value 1 - Value 2 - Value 3 - - - An error occurred. - - `, - context: args, -}); - - - - {ErrorTemplate.bind({})} - - - -export const ContextualTemplate = (args) => ({ - template: hbs` - -
- Label -
- Help -
- - Value 1 - Value 2 - Value 3 - -
- - An error occurred. - -
-
`, - context: args, -}); - - - {ContextualTemplate.bind({})} - diff --git a/addons/rose/addon/components/rose/form/select/select/index.hbs b/addons/rose/addon/components/rose/form/select/select/index.hbs deleted file mode 100644 index 9857b6cd0..000000000 --- a/addons/rose/addon/components/rose/form/select/select/index.hbs +++ /dev/null @@ -1,13 +0,0 @@ - - {{yield xs}} - \ No newline at end of file diff --git a/addons/rose/addon/helpers/set-from-event.js b/addons/rose/addon/helpers/set-from-event.js new file mode 100644 index 000000000..7544acee9 --- /dev/null +++ b/addons/rose/addon/helpers/set-from-event.js @@ -0,0 +1,11 @@ +import { helper } from '@ember/component/helper'; +import { set } from '@ember/object'; + +export function setFromEvent([context, field]) { + // The Ember `set` function is used here because `field` may be in dotted + // notation, refering to nested fields within `context`. + return (event) => + event?.target?.value ? set(context, field, event.target.value) : null; +} + +export default helper(setFromEvent); diff --git a/addons/rose/addon/styles/hds/themes/dark-mode/index.scss b/addons/rose/addon/styles/hds/themes/dark-mode/index.scss index c2a7265b7..0b20eb719 100644 --- a/addons/rose/addon/styles/hds/themes/dark-mode/index.scss +++ b/addons/rose/addon/styles/hds/themes/dark-mode/index.scss @@ -70,6 +70,7 @@ --token-color-foreground-warning-on-surface: var(--token-color-palette-amber-400); --token-color-foreground-critical-on-surface: var(--token-color-palette-red-400); --token-color-surface-strong: var(--token-color-palette-neutral-50); + --token-form-control-base-border-color-default: var(--token-color-palette-neutral-200); } // HDS Light Mode diff --git a/addons/rose/app/components/rose/form/select.js b/addons/rose/app/components/rose/form/select.js deleted file mode 100644 index 5d3b4b606..000000000 --- a/addons/rose/app/components/rose/form/select.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from 'rose/components/rose/form/select'; diff --git a/addons/rose/app/components/rose/form/select/select.js b/addons/rose/app/components/rose/form/select/select.js deleted file mode 100644 index 4fdbc3925..000000000 --- a/addons/rose/app/components/rose/form/select/select.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from 'rose/components/rose/form/select/select'; diff --git a/addons/rose/app/helpers/set-from-event.js b/addons/rose/app/helpers/set-from-event.js new file mode 100644 index 000000000..33357b8d2 --- /dev/null +++ b/addons/rose/app/helpers/set-from-event.js @@ -0,0 +1 @@ +export { default } from 'rose/helpers/set-from-event'; diff --git a/addons/rose/app/styles/rose/components/table/_table.scss b/addons/rose/app/styles/rose/components/table/_table.scss index 40e5ae838..8416b7ab2 100644 --- a/addons/rose/app/styles/rose/components/table/_table.scss +++ b/addons/rose/app/styles/rose/components/table/_table.scss @@ -19,8 +19,8 @@ // This styles are add to stop the input to apply extra margin (default on forms) .rose-form-input, .rose-form-input-field, - .rose-form-select, - .rose-form-select-field { + .hds-form-select, + [class^='hds-form-field-'] .hds-form-select:not(:first-child) { margin: 0; width: 100%; } diff --git a/addons/rose/package.json b/addons/rose/package.json index d1fe87765..87a4ce02a 100644 --- a/addons/rose/package.json +++ b/addons/rose/package.json @@ -46,7 +46,6 @@ "ember-named-blocks-polyfill": "^0.2.5", "ember-radio-button": "github:yapplabs/ember-radio-button.git#b2ab65f", "ember-uuid": "^2.1.0", - "emberx-select": "github:adopted-ember-addons/emberx-select#bc5f774", "sass": "^1.55.0" }, "devDependencies": { diff --git a/addons/rose/tests/integration/components/rose/form-test.js b/addons/rose/tests/integration/components/rose/form-test.js index 19700869c..cbeb2ebc9 100644 --- a/addons/rose/tests/integration/components/rose/form-test.js +++ b/addons/rose/tests/integration/components/rose/form-test.js @@ -42,14 +42,24 @@ module('Integration | Component | rose/form', function (hooks) { > - - - + Select + Helper text + + + + + + + + {}; - await render(hbs` - - - Choose an option - Value 1 - Value 2 - Value 3 - - - `); - assert.strictEqual(find('label').textContent.trim(), 'Label'); - assert.ok(find('select')); - assert.strictEqual(findAll('option').length, 4); - }); - - test('it displays optional helper text', async function (assert) { - this.onChange = () => {}; - await render(hbs` - - - Choose an option - - - `); - const fieldEl = find('select'); - const id = fieldEl.id; - const helperId = `helper-text-${id}`; - const helperTextEl = find('.rose-form-helper-text'); - assert.strictEqual(helperTextEl.textContent.trim(), 'Help me'); - assert.strictEqual(helperTextEl.id, helperId); - assert.strictEqual( - fieldEl.getAttribute('aria-describedby').trim(), - helperId - ); - }); - - test('it displays optional errors', async function (assert) { - this.onChange = () => {}; - await render(hbs` - - - Choose an option - - - An error occurred. - - - `); - const fieldEl = find('select'); - const id = fieldEl.id; - const errorsId = `errors-${id}`; - const errorMessageEl = find('.rose-form-errors'); - assert.strictEqual(errorMessageEl.id, errorsId); - assert.strictEqual(errorMessageEl.textContent.trim(), 'An error occurred.'); - assert.strictEqual( - fieldEl.getAttribute('aria-describedby').split(' ')[1], - errorsId - ); - }); - - test('it supports disabled attribute', async function (assert) { - this.onChange = () => {}; - await render(hbs` - - - Choose an option - - - `); - assert.ok(find('[disabled]')); - }); - - test('its value is bound to and udpated by @value', async function (assert) { - this.onChange = () => {}; - this.value = 'value-1'; - await render(hbs` - - - value-1 - value-2 - - - `); - assert.strictEqual(find('select').value, 'value-1'); - this.set('value', 'value-2'); - assert.strictEqual(find('select').value, 'value-2'); - }); - - test('it triggers an action on change', async function (assert) { - assert.expect(2); - this.onChange1 = (value) => { - assert.strictEqual( - value, - null, - 'On initial render, onChange is triggered with null' - ); - this.set('onChange', this.onChange2); - }; - this.onChange2 = (value) => { - assert.strictEqual(value, 'value-1', 'On change, value is passed in.'); - }; - this.onChange = this.onChange1; - await render(hbs` - - - Choose an option - value-1 - - - `); - await fillIn('[name="my-select"]', 'value-1'); - }); - - test('it supports a fully contextual usage', async function (assert) { - assert.expect(5); - await render(hbs` - - Label - Help - - value-1 - - - An error occurred. - - - `); - assert.notOk( - find('.rose-form-input'), - 'The form field wrapper element is not present in contextual mode' - ); - assert.ok(find('.rose-form-label.error')); - assert.ok(find('.rose-form-helper-text.error')); - assert.ok(find('.rose-form-select-field.error')); - assert.ok(find('.rose-form-error-message')); - }); -}); diff --git a/addons/rose/tests/integration/helpers/set-from-event-test.js b/addons/rose/tests/integration/helpers/set-from-event-test.js new file mode 100644 index 000000000..52d26cc03 --- /dev/null +++ b/addons/rose/tests/integration/helpers/set-from-event-test.js @@ -0,0 +1,56 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render, click, select } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; +import { setFromEvent } from 'rose/helpers/set-from-event'; + +module('Integration | Helper | set-from-event', function (hooks) { + setupRenderingTest(hooks); + + test('it returns a function that sets the specified value to event.target.value', async function (assert) { + assert.expect(2); + this.set('inputValue', '1234'); + assert.deepEqual(this.inputValue, '1234'); + const handler = setFromEvent([this, 'inputValue']); + handler({ target: { value: 'foobar' } }); + assert.deepEqual(this.inputValue, 'foobar'); + }); + + test('it can be used with the on modifier to set a specified field with the value of event.target.value', async function (assert) { + assert.expect(2); + this.set('inputValue', '1234'); + await render( + hbs`