From 662c00beaa7dd069beb26ee9d124217fcb62f373 Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Fri, 3 Jul 2020 13:49:27 -0500 Subject: [PATCH 1/5] Disallowed accessibility audit in development (to avoid runloop error) --- tests/dummy/config/environment.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/dummy/config/environment.js b/tests/dummy/config/environment.js index 9f239369..4b46d128 100644 --- a/tests/dummy/config/environment.js +++ b/tests/dummy/config/environment.js @@ -23,6 +23,12 @@ module.exports = function(environment) { } }; + ENV['ember-a11y-testing'] = { + componentOptions: { + turnAuditOff: true + } + } + if (environment === 'development') { // ENV.APP.LOG_RESOLVER = true; // ENV.APP.LOG_ACTIVE_GENERATION = true; From 112ee41089744ee83d9123d853d686d5c88f563c Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Fri, 3 Jul 2020 13:50:00 -0500 Subject: [PATCH 2/5] Allowed dynamic tag, but restricted it to be immutable --- addon/components/container-query.hbs | 34 +++++++++++++++------------- addon/components/container-query.js | 7 ++++++ package.json | 7 +++--- yarn.lock | 31 ++++++++++++++++--------- 4 files changed, 49 insertions(+), 30 deletions(-) diff --git a/addon/components/container-query.hbs b/addon/components/container-query.hbs index e9191a38..83d4a3a2 100644 --- a/addon/components/container-query.hbs +++ b/addon/components/container-query.hbs @@ -1,16 +1,18 @@ -
- {{yield (hash - features=this.queryResults - dimensions=(hash - aspectRatio=this.aspectRatio - height=this.height - width=this.width - ) - )}} -
\ No newline at end of file +{{#let (element this.tagName) as |Tag|}} + + {{yield (hash + features=this.queryResults + dimensions=(hash + aspectRatio=this.aspectRatio + height=this.height + width=this.width + ) + )}} + +{{/let}} \ No newline at end of file diff --git a/addon/components/container-query.js b/addon/components/container-query.js index 50cc38d6..12080105 100644 --- a/addon/components/container-query.js +++ b/addon/components/container-query.js @@ -20,6 +20,13 @@ export default class ContainerQueryComponent extends Component { return this.args.debounce ?? 0; } + constructor() { + super(...arguments); + + // The dynamic tag is restricted to be immutable + this.tagName = this.args.tagName || 'div'; + } + @action queryContainer(element) { this.measureDimensions(element); this.evaluateQueries(); diff --git a/package.json b/package.json index 631525c2..82cfbc16 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,8 @@ "@ember/render-modifiers": "^1.0.2", "ember-cli-babel": "^7.21.0", "ember-cli-htmlbars": "^5.2.0", - "ember-did-resize-modifier": "^1.0.0" + "ember-did-resize-modifier": "^1.0.0", + "ember-element-helper": "^0.3.1" }, "devDependencies": { "@ember/optional-features": "^1.3.0", @@ -91,8 +92,8 @@ "ember-template-lint": "^2.9.0", "ember-test-selectors": "^4.1.0", "ember-try": "^1.4.0", - "eslint": "^7.3.1", - "eslint-plugin-ember": "^8.9.0", + "eslint": "^7.4.0", + "eslint-plugin-ember": "^8.9.1", "eslint-plugin-node": "^11.1.0", "lerna-changelog": "^1.0.1", "loader.js": "^4.7.0", diff --git a/yarn.lock b/yarn.lock index 5d5c57fd..49f8ce0e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5889,7 +5889,7 @@ ember-cli-babel-plugin-helpers@^1.0.0, ember-cli-babel-plugin-helpers@^1.1.0: resolved "https://registry.yarnpkg.com/ember-cli-babel-plugin-helpers/-/ember-cli-babel-plugin-helpers-1.1.0.tgz#de3baedd093163b6c2461f95964888c1676325ac" integrity sha512-Zr4my8Xn+CzO0gIuFNXji0eTRml5AxZUTDQz/wsNJ5AJAtyFWCY4QtKdoELNNbiCVGt1lq5yLiwTm4scGKu6xA== -ember-cli-babel@7.21.0, ember-cli-babel@^7.21.0: +ember-cli-babel@7.21.0, ember-cli-babel@^7.17.2, ember-cli-babel@^7.21.0: version "7.21.0" resolved "https://registry.yarnpkg.com/ember-cli-babel/-/ember-cli-babel-7.21.0.tgz#c79e888876aee87dfc3260aee7cb580b74264bbc" integrity sha512-jHVi9melAibo0DrAG3GAxid+29xEyjBoU53652B4qcu3Xp58feZGTH/JGXovH7TjvbeNn65zgNyoV3bk1onULw== @@ -6039,7 +6039,7 @@ ember-cli-htmlbars@^4.0.0: strip-bom "^4.0.0" walk-sync "^2.0.2" -ember-cli-htmlbars@^5.2.0: +ember-cli-htmlbars@^5.1.0, ember-cli-htmlbars@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ember-cli-htmlbars/-/ember-cli-htmlbars-5.2.0.tgz#5ceccd0d18163dd810dea29f6fd777d0baa01e23" integrity sha512-EdjuUc7sq9ve6sgsG59qIzOj4svWjgYhO/QEhuV1UbOQ3ATeqNPiD++bFeAGjUhravw9HPhQPPoHnMlAikqLIw== @@ -6291,7 +6291,7 @@ ember-cli@~3.19.0: watch-detector "^1.0.0" yam "^1.0.0" -ember-compatibility-helpers@^1.1.2, ember-compatibility-helpers@^1.2.0: +ember-compatibility-helpers@^1.1.2, ember-compatibility-helpers@^1.2.0, ember-compatibility-helpers@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ember-compatibility-helpers/-/ember-compatibility-helpers-1.2.1.tgz#87c92c4303f990ff455c28ca39fb3ee11441aa16" integrity sha512-6wzYvnhg1ihQUT5yGqnLtleq3Nv5KNv79WhrEuNU9SwR4uIxCO+KpyC7r3d5VI0EM7/Nmv9Nd0yTkzmTMdVG1A== @@ -6339,6 +6339,15 @@ ember-disable-prototype-extensions@^1.1.3: resolved "https://registry.yarnpkg.com/ember-disable-prototype-extensions/-/ember-disable-prototype-extensions-1.1.3.tgz#1969135217654b5e278f9fe2d9d4e49b5720329e" integrity sha1-GWkTUhdlS14nj5/i2dTkm1cgMp4= +ember-element-helper@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/ember-element-helper/-/ember-element-helper-0.3.1.tgz#dd6017a64a9952058c16050c7a9eb0fff5ebfe90" + integrity sha512-U3tXkhiPsL1uIz2jCBZS4Lot0Le0wt7RM7TArYAR5OZRLGdCaLkRjQ0Xx5IlwWbBS0KOrfARevc1OLnX1AIgZQ== + dependencies: + ember-cli-babel "^7.17.2" + ember-cli-htmlbars "^5.1.0" + ember-compatibility-helpers "^1.2.1" + ember-export-application-global@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/ember-export-application-global/-/ember-export-application-global-2.0.1.tgz#b120a70e322ab208defc9e2daebe8d0dfc2dcd46" @@ -6783,10 +6792,10 @@ escodegen@^1.11.0: optionalDependencies: source-map "~0.6.1" -eslint-plugin-ember@^8.9.0: - version "8.9.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-ember/-/eslint-plugin-ember-8.9.0.tgz#010f720665b00847df151d5ae64f41e4671c825a" - integrity sha512-wSZuQM5AkDBc/FRL7jAIMVPQxzXSMUBgzGYzxhLNc4HOSBKVu6qqh2XZg7PTUmhst39VdYjDvep9QHmeRWdLkA== +eslint-plugin-ember@^8.9.1: + version "8.9.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-ember/-/eslint-plugin-ember-8.9.1.tgz#6d76440bd7bb1954ed61c7ebbb1a1cd8c8e1afa6" + integrity sha512-A7TFksLfLLoQEWOHCvJX6SvxxL99yDEPwDZIh28TOgwsPsXpVYJNk22UT5ZrufUyVtdnOH4IsF3jIkRIIE91IA== dependencies: "@ember-data/rfc395-data" "^0.0.4" ember-rfc176-data "^0.3.13" @@ -6846,10 +6855,10 @@ eslint-visitor-keys@^1.2.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.2.0.tgz#74415ac884874495f78ec2a97349525344c981fa" integrity sha512-WFb4ihckKil6hu3Dp798xdzSfddwKKU3+nGniKF6HfeW6OLd2OUDEPP7TcHtB5+QXOKg2s6B2DaMPE1Nn/kxKQ== -eslint@^7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.3.1.tgz#76392bd7e44468d046149ba128d1566c59acbe19" - integrity sha512-cQC/xj9bhWUcyi/RuMbRtC3I0eW8MH0jhRELSvpKYkWep3C6YZ2OkvcvJVUeO6gcunABmzptbXBuDoXsjHmfTA== +eslint@^7.4.0: + version "7.4.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.4.0.tgz#4e35a2697e6c1972f9d6ef2b690ad319f80f206f" + integrity sha512-gU+lxhlPHu45H3JkEGgYhWhkR9wLHHEXC9FbWFnTlEkbKyZKWgWRLgf61E8zWmBuI6g5xKBph9ltg3NtZMVF8g== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.10.0" From 22e1cdf48f191f87f23dd02ce4ff370cd043e5ef Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Wed, 8 Jul 2020 20:29:18 -0500 Subject: [PATCH 3/5] Applied @tagName to the demo app --- tests/dummy/app/components/widgets/widget-1/index.hbs | 1 + tests/dummy/app/components/widgets/widget-2/index.hbs | 1 + tests/dummy/app/components/widgets/widget-3/index.hbs | 4 ++-- tests/dummy/app/components/widgets/widget-4/index.hbs | 4 ++-- tests/dummy/app/components/widgets/widget-4/memo/index.hbs | 1 + tests/dummy/app/components/widgets/widget-5/index.hbs | 1 + 6 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/dummy/app/components/widgets/widget-1/index.hbs b/tests/dummy/app/components/widgets/widget-1/index.hbs index 30844699..ef5774cd 100644 --- a/tests/dummy/app/components/widgets/widget-1/index.hbs +++ b/tests/dummy/app/components/widgets/widget-1/index.hbs @@ -4,6 +4,7 @@ square=(cq-aspect-ratio min=0.8 max=1.25) wide=(cq-aspect-ratio min=1.25) }} + @tagName="section" local-class="container" >
diff --git a/tests/dummy/app/components/widgets/widget-2/index.hbs b/tests/dummy/app/components/widgets/widget-2/index.hbs index c47b53c7..3d09c489 100644 --- a/tests/dummy/app/components/widgets/widget-2/index.hbs +++ b/tests/dummy/app/components/widgets/widget-2/index.hbs @@ -4,6 +4,7 @@ tall=(cq-height min=200 max=480) very-tall=(cq-height min=480) }} + @tagName="section" local-class="container" as |CQ| > diff --git a/tests/dummy/app/components/widgets/widget-3/index.hbs b/tests/dummy/app/components/widgets/widget-3/index.hbs index 1434b89e..141de826 100644 --- a/tests/dummy/app/components/widgets/widget-3/index.hbs +++ b/tests/dummy/app/components/widgets/widget-3/index.hbs @@ -1,4 +1,4 @@ -
+

Widget 3

@@ -17,4 +17,4 @@ @concert={{this.concertData}} />
- \ No newline at end of file + \ No newline at end of file diff --git a/tests/dummy/app/components/widgets/widget-4/index.hbs b/tests/dummy/app/components/widgets/widget-4/index.hbs index b168b5d0..d727606a 100644 --- a/tests/dummy/app/components/widgets/widget-4/index.hbs +++ b/tests/dummy/app/components/widgets/widget-4/index.hbs @@ -1,4 +1,4 @@ -
+

Widget 4

@@ -12,4 +12,4 @@ All memos
- \ No newline at end of file + \ No newline at end of file diff --git a/tests/dummy/app/components/widgets/widget-4/memo/index.hbs b/tests/dummy/app/components/widgets/widget-4/memo/index.hbs index 6a101e38..0326a8bf 100644 --- a/tests/dummy/app/components/widgets/widget-4/memo/index.hbs +++ b/tests/dummy/app/components/widgets/widget-4/memo/index.hbs @@ -4,6 +4,7 @@ large=(cq-width min=200) short=(cq-height max=200) }} + @tagName="article" local-class="container" as |CQ| > diff --git a/tests/dummy/app/components/widgets/widget-5/index.hbs b/tests/dummy/app/components/widgets/widget-5/index.hbs index f4f96e16..e583b186 100644 --- a/tests/dummy/app/components/widgets/widget-5/index.hbs +++ b/tests/dummy/app/components/widgets/widget-5/index.hbs @@ -3,6 +3,7 @@ large=(cq-width min=224) tall=(cq-height min=120) }} + @tagName="section" local-class="container" as |CQ| > From 13cb77131fab7f056966dbe6d9facf48059098dd Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Wed, 8 Jul 2020 21:46:37 -0500 Subject: [PATCH 4/5] Added rendering tests for @tagName --- .../container-query/tagName-test.js | 222 ++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 tests/integration/components/container-query/tagName-test.js diff --git a/tests/integration/components/container-query/tagName-test.js b/tests/integration/components/container-query/tagName-test.js new file mode 100644 index 00000000..389eb9fe --- /dev/null +++ b/tests/integration/components/container-query/tagName-test.js @@ -0,0 +1,222 @@ +import { set } from '@ember/object'; +import { render, settled } from '@ember/test-helpers'; +import setupContainerQueryTest from 'dummy/tests/helpers/container-query'; +import resizeContainer from 'dummy/tests/helpers/resize-container'; +import { hbs } from 'ember-cli-htmlbars'; +import { setupRenderingTest } from 'ember-qunit'; +import { module, test } from 'qunit'; + +module('Integration | Component | container-query', function(hooks) { + setupRenderingTest(hooks); + setupContainerQueryTest(hooks); + + + module('When @tagName is undefined', function(hooks) { + hooks.beforeEach(async function() { + await render(hbs` +
+ +

{{CQ.features.small}}

+

{{CQ.features.medium}}

+

{{CQ.features.large}}

+ +

{{CQ.features.short}}

+

{{CQ.features.tall}}

+ +

{{CQ.features.ratio-type-A}}

+

{{CQ.features.ratio-type-B}}

+

{{CQ.features.ratio-type-C}}

+ +

{{CQ.dimensions.width}} x {{CQ.dimensions.height}}

+

{{CQ.dimensions.aspectRatio}}

+
+
+ `); + }); + + + test('The component has the
tag', async function(assert) { + assert.dom('[data-test-container-query]') + .hasTagName('div', 'Tag name is correct.'); + }); + + + test('The component continues to have the
tag when it is resized', async function(assert) { + await resizeContainer(500, 300); + + assert.dom('[data-test-container-query]') + .hasTagName('div', 'Tag name is correct.'); + + + await resizeContainer(800, 400); + + assert.dom('[data-test-container-query]') + .hasTagName('div', 'Tag name is correct.'); + + + await resizeContainer(1000, 600); + + assert.dom('[data-test-container-query]') + .hasTagName('div', 'Tag name is correct.'); + }); + }); + + + module('When @tagName is passed', function(hooks) { + hooks.beforeEach(async function() { + await render(hbs` +
+ +

{{CQ.features.small}}

+

{{CQ.features.medium}}

+

{{CQ.features.large}}

+ +

{{CQ.features.short}}

+

{{CQ.features.tall}}

+ +

{{CQ.features.ratio-type-A}}

+

{{CQ.features.ratio-type-B}}

+

{{CQ.features.ratio-type-C}}

+ +

{{CQ.dimensions.width}} x {{CQ.dimensions.height}}

+

{{CQ.dimensions.aspectRatio}}

+
+
+ `); + }); + + + test('The component has the correct tag', async function(assert) { + assert.dom('[data-test-container-query]') + .hasTagName('section', 'Tag name is correct.'); + }); + + + test('The component continues to have the correct tag when it is resized', async function(assert) { + await resizeContainer(500, 300); + + assert.dom('[data-test-container-query]') + .hasTagName('section', 'Tag name is correct.'); + + + await resizeContainer(800, 400); + + assert.dom('[data-test-container-query]') + .hasTagName('section', 'Tag name is correct.'); + + + await resizeContainer(1000, 600); + + assert.dom('[data-test-container-query]') + .hasTagName('section', 'Tag name is correct.'); + }); + }); + + + module('When @tagName is updated', function(hooks) { + hooks.beforeEach(async function() { + this.tagName = 'section'; + + await render(hbs` +
+ +

{{CQ.features.small}}

+

{{CQ.features.medium}}

+

{{CQ.features.large}}

+ +

{{CQ.features.short}}

+

{{CQ.features.tall}}

+ +

{{CQ.features.ratio-type-A}}

+

{{CQ.features.ratio-type-B}}

+

{{CQ.features.ratio-type-C}}

+ +

{{CQ.dimensions.width}} x {{CQ.dimensions.height}}

+

{{CQ.dimensions.aspectRatio}}

+
+
+ `); + + set(this, 'tagName', 'article'); + + await settled(); + }); + + + test('The component doesn\'t update the tag', async function(assert) { + assert.dom('[data-test-container-query]') + .hasTagName('section', 'Tag name is correct.') + .doesNotHaveTagName('article', 'Tag name did not change.'); + }); + + + test('The component continues to not update the tag when it is resized', async function(assert) { + await resizeContainer(500, 300); + + assert.dom('[data-test-container-query]') + .hasTagName('section', 'Tag name is correct.') + .doesNotHaveTagName('article', 'Tag name did not change.'); + + + await resizeContainer(800, 400); + + assert.dom('[data-test-container-query]') + .hasTagName('section', 'Tag name is correct.') + .doesNotHaveTagName('article', 'Tag name did not change.'); + + + await resizeContainer(1000, 600); + + assert.dom('[data-test-container-query]') + .hasTagName('section', 'Tag name is correct.') + .doesNotHaveTagName('article', 'Tag name did not change.'); + }); + }); +}); \ No newline at end of file From a08b2b7f197a71170fa37b073087ac1de8439e32 Mon Sep 17 00:00:00 2001 From: ijlee2 Date: Wed, 8 Jul 2020 22:36:51 -0500 Subject: [PATCH 5/5] Updated README --- README.md | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index fb8843d6..09ebd43f 100644 --- a/README.md +++ b/README.md @@ -114,17 +114,35 @@ The addon provides 1 Glimmer component and 3 helpers:
<ContainerQuery> -The component uses `...attributes` so that you can pass `class` or [`local-class`](https://github.com/salsify/ember-css-modules) _for styling_.1 +### Arguments -It also accepts these arguments: +You can pass these arguments to the component. | Name | Required | Description | Type | |--|:--:|--|--| -| @features | Yes2 | Container query definitions | POJO | +| @features | Yes1 | Container query definitions | POJO | | @dataAttributePrefix | No | Prefix for data attributes | string | | @debounce | No | Debounce time for resize (ms) | number ≥ 0 | +| @tagName | No | Container tag name2 | HTML tag name | -The component returns a few values that you can consume: +1. The component renders without error when `@features` isn't provided. In practice, you will always want to set `@features`. + +2. By default, the component is a `
` element. You can pass a valid HTML tag name to facilitate accessibility and semantic HTML. + +### Attributes + +You _may_1 pass attributes to the component for these reasons: + +- Style (e.g. `class`, [`local-class`](https://github.com/salsify/ember-css-modules)) +- Accessibility (e.g. ARIA attributes2, roles) + +1. Do refrain from overusing splattributes (e.g. pass a `{{did-insert}}` modifier to fetch data), since the component's API may change and cause unexpected results. Practice separation of concerns when possible. For example, data fetching can be handled by another element or [`@use` decorator](https://github.com/emberjs/rfcs/blob/use-and-resources/text/0567-use-and-resources.md). + +2. When an [ARIA attribute has multiple values](https://github.com/ijlee2/ember-container-query/issues/38#issuecomment-647017665), the order of values can matter. At the moment, splattributes doesn't guarantee the order. + +### Outputs + +You can consume these values in your app or addon. | Name | Yielded | Description | Type | |--|:--:|--|--| @@ -132,16 +150,14 @@ The component returns a few values that you can consume: | dimensions | Yes | Container dimensions | POJO | | data-container-query-_{featureName}_ | No | Data attributes for CSS selector | HTML data attribute | -1. Do refrain from overusing splattributes (e.g. pass a `{{did-insert}}` modifier to fetch data), since the component's API may change and cause unexpected results. Practice separation of concerns when possible. For example, data fetching can be handled by another element or [`@use` decorator](https://github.com/emberjs/rfcs/blob/use-and-resources/text/0567-use-and-resources.md). - -2. The component renders without error when `@features` isn't provided. In practice, you will always want to set `@features`. -
{{cq-aspect-ratio}}, {{cq-height}}, {{cq-width}} +### Arguments + All helpers accept these arguments: | Name | Required | Description | Type |