-
Notifications
You must be signed in to change notification settings - Fork 44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable programmatic close on dropdown component #399
Conversation
We rename the `deactivate` function to `close` (to ease the adoption and keep it simple) and expose it as part of the disclosure utility component API
We forward the `close` function from disclosure to dropdown and expose it as part of the dropdown component API
🦋 Changeset detectedLatest commit: 899dec3 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@alex-ju added a couple of comments related to the documentation (the other code is OK, actually very nice implementation and refactoring).
await click('button#test-toggle-button'); | ||
assert.dom('#test-dropdown #test-list-item-interactive').exists(); | ||
await click('#test-list-item-interactive'); | ||
assert.dom('#test-dropdown #test-list-item-interactive').doesNotExist(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[potential issue] what if it doesn't exist anymore, because in the meantime the page has navigated away? probably to avoid this risk in the render
above (line 100) instead of a route to a different "page" I would use a @href="#"
? (similar to what you did in the other test)
PS: if you want to test the actual behaviour you can
- add a line after line 106, with this code:
await pauseTest();
(the method needs to be imported from@ember/test-helpers
) - launch the tests via
ember test --server --filter 'Integration | Component | hds/dropdown/index'
- this will launch a new browser that renders the content, and pause the test wherever you put thepauseTest()
call, and you can inspect the DOM and see what it does
(FYI I did the test, and strangely enough it shows both the dropdown and the content of the target webpage, so not sure how to interpret this).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair concern. I forgot the trigger in this example is not a simple HTML button element, but an interactive component with a set route which renders as a link.
<ul class="dummy-disclosure-content-list-of-links"> | ||
<li> | ||
<a href="https://google.com">Link to Google</a> | ||
</li> | ||
<li> | ||
<a href="https://apple.com">Link with a much longer text</a> | ||
<a href="https://apple.com" {{on "click" c.close}}>Link to Apple (closes the disclosed content on click)</a> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] probably in order to be able to see that actually closes the dropdown, it would be better to add target="_blank"
to the link (otherwise it opens in the same window and everything disappears). Another option would be to have a <button>
instead of a link, that does nothing more that closing the disclosure?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested it locally with command+click so I preserve the current page, but yes, button would be more suitable. Same for integration testing.
@@ -444,7 +448,7 @@ | |||
<dd.Interactive @route="..." @text="Item One" /> | |||
<dd.Interactive @route="..." @text="Item Two" /> | |||
<dd.Interactive @route="..." @text="Item Three" /> | |||
<dd.Interactive @route="..." @text="Item Four" /> | |||
<dd.Interactive @route="..." @text="Item Four (closes on click)" \{{on "click" dd.close}} /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] same as above: this reloads the page, so there is no way to check that actually works. If you remove the @route
it will render a <button>
and when you click it you see that it closes.
Interactive without @route renders a button
Good points about using buttons for clarity in examples and accuracy in tests. I've updated based on feedback and it's good for a 2nd review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice!
Thanks for this! |
I just discovered a fun little footgun related to this feature that others may run into… So, given the use case from the description: <Hds::Dropdown id="test-dropdown" as |dd|>
<dd.ToggleButton @text="toggle button" />
<dd.Interactive
@route="components.dropdown"
@text="interactive"
{{on "click" dd.close}}
/>
</Hds::Dropdown> My assumption was that Unfortunately, this was a faulty assumption. A peek at link-to.hbs reveals the truth: <a
{{!-- for compatibility --}}
id={{this.id}}
class={{this.class}}
{{!-- deprecated attribute bindings --}}
role={{this.role}}
title={{this.title}}
rel={{this.rel}}
tabindex={{this.tabindex}}
target={{this.target}}
...attributes <---------------+
|
href={{this.href}} | OH MY
|
{{on 'click' this.click}} <---+
>{{yield}}</a> Splattributes are applied before the click handler 😬 Which means Funnily enough, the result almost looks like it’s working, because we still have a perfectly functional href, so it’s easy not to notice the browser is doing a full page load. The solution is to schedule the {{! my-component.hbs}}
<Hds::Dropdown id="test-dropdown" as |dd|>
<dd.ToggleButton @text="toggle button" />
<dd.Interactive
@route="components.dropdown"
@text="interactive"
{{on "click" (fn this.later dd.close)}}
/>
</Hds::Dropdown> // my-component.js
export default class extends Component {
@action
later(fn) {
// Runs fn in the next event cycle (after sync listeners)
setTimeout(fn);
}
} |
📌 Summary
Enable programmatic close on dropdown component.
🛠️ Detailed description
Based on feedback from @jgwhite we realised that we're not exposing a way for developers to close a dropdown component. In this PR we start by renaming the
deactivate
function in disclosure utility component toclose
then forward it to the dropdown component.A simplified example of a call would look like this:
🔗 External links
Jira issue
👀 How to review
👉 Review commit-by-commit
Reviewer's checklist:
💬 Please consider using conventional comments when reviewing this PR.