-
Notifications
You must be signed in to change notification settings - Fork 841
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
Allow accordions to change height while open, and permit value on radio inputs #613
Allow accordions to change height while open, and permit value on radio inputs #613
Conversation
8b134a1
to
a86f9df
Compare
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.
Great fix for the radio button group! I just had a couple minor suggestions.
For the accordion, is it possible to update the docs with an example of your use case? Even if it's an oversimplified example, it will be useful for maintainers to ensure we don't lose this behavior by accident.
CHANGELOG.md
Outdated
@@ -4,7 +4,7 @@ | |||
|
|||
- Visual fix for the focus state of disabled `EuiButton` ([603](https://github.com/elastic/eui/pull/603)) | |||
- `EuiSelect` can pass any node as a value rather than just a string ([603](https://github.com/elastic/eui/pull/603)) | |||
|
|||
- Allow accordions to dynamically change height, and support values on radio inputs ([#613](https://github.com/elastic/eui/pull/613)) |
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.
Minor nit, but can we break this into 2 bullets? I think it will be more helpful people reading the notes because then they can scan for individual fixes per bullet.
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've split these and marked the radio change as break, since it is now.
onToggle() { | ||
const currentState = this.state.isOpen; | ||
const height = this.childContent.clientHeight; | ||
const isOpen = !this.state.isOpen; |
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.
Since we're changing state based on previous state, I think we should be technically using the setState callback:
this.setState(prevState => ({
isOpen: !prevState.isOpen,
}));
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.
Done.
this.childWrapper.setAttribute('style', `height: 0px`); | ||
} | ||
const height = isOpen ? this.childContent.clientHeight : 0; | ||
this.childWrapper.setAttribute('style', `height: ${height}px`); |
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.
Since we're calling setState
, the render
method will be called, and then componentDidUpdate
should be called immediately after, right? In which case, do we need this logic here?
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've removed it.
disabled={disabled} | ||
onChange={onChange.bind(null, option.id)} | ||
onChange={onChange.bind(null, option.value || option.id)} |
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.
Can we make this more explicit by passing both id
and value
?
onChange={onChange.bind(null, option.value, option.id)}
I don't like that this now requires every consume to handle both arguments, but I also think it's clearer this way, because the behavior doesn't change depending on whether value is specified.
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.
Done, and marked as a breaking change. I also realised there was an existing radio behaviour test that duplicated but in a less good way what I've written, so I've removed the other file.
@snide @cjcenizal this is ready for re-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.
This works for me. @pugnascotia if you don't mind can you add a responsive={false}
prop on the EuiFlexGroup
in accordion.js
. It'll fix the issue of the rows stacking in mobile.
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.
Looks good! I had a couple suggestions on ways to make the tests simpler and a bit easier to read. Here are the docs for the functions I used:
- https://facebook.github.io/jest/docs/en/expect.html#tohavebeencalledwitharg1-arg2-
- https://facebook.github.io/jest/docs/en/expect.html#expectanyconstructor
Also, this is totally optional since ideally the linter should be catching this, but you could add semi-colons to end your lines. I see a few lines which are written in the Cloud-style. :D
CHANGELOG.md
Outdated
|
||
**Breaking changes** | ||
|
||
- Support values on radio inputs. This is breaking because now the second argument to the radio `onChange` callback is the value, which bumps the change event to the third argument ([#613](https://github.com/elastic/eui/pull/613)) |
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 always forget about this. Great catch.
|
||
expect(callback.mock.calls[0][0]).toEqual('2'); | ||
expect(callback.mock.calls[0][1]).toBeUndefined(); | ||
// The callback is also invoked with the event, but that's not assert-able. |
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.
Lines 101-106 can become:
expect(callback).toHaveBeenCalledTimes(1);
const event = expect.any(Object);
expect(callback).toHaveBeenCalledWith('2', undefined, event);
|
||
expect(callback.mock.calls[0][0]).toEqual('2'); | ||
expect(callback.mock.calls[0][1]).toEqual('Value #2'); | ||
// The callback is also invoked with the event, but that's not assert-able. |
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.
Lines 125-130 can become:
expect(callback).toHaveBeenCalledTimes(1);
const event = expect.any(Object);
expect(callback).toHaveBeenCalledWith('2', 'Value #2', event);
8c83b09
to
56cb55b
Compare
Thanks @snide and @cjcenizal, I've applied more changes. Re: the Jest changes, that's just what I was hoping would exist but didn't come across before. Nice! |
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.
Thanks for the ;;;!
Fixes two issues:
Firstly, I noticed that if I have some accordion content that changes height while the accordion is open, it doesn't resize. Fix that.
Secondly, allow a value attribute to be set on radio inputs, and also use it in a radio group's callback. At preset, the radio's ID is passed in the callback, but that's unhelpful on a page with multiple, identical sets of radio groups, since the IDs have to all be unique. It feels horrible to embed the radio value in a unique ID and extract it later when a radio control has a perfectly good value attribute.