-
Notifications
You must be signed in to change notification settings - Fork 842
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
Add EuiTabbedContent. #737
Conversation
42ce61e
to
4540cf6
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.
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.
Looking great! I left a few semantic considerations.
} = this.props; | ||
|
||
// Allow the consumer to control tab selection. | ||
const selectedTab = externalSelectedTab || this.state.selectedTab |
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.
Just thinking out loud here, but if I was searching for use of the selectedTab
prop it would trip me up to see it renamed to externalSelectedTab
. I think it might be easier to figure out what's going on to write this as this.props.selectedTab
. I guess it depends how heavily we want to lean on the implicit statement that props are externally 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.
I definitely see what you're saying. We have to destructure this prop anyway so that we can pass ...rest
onto the rendered root element, which would also be confusing because we would destructure it, declare it as unused (via an eslint comment), and then refer to it anyway via this.props
. I'm going to be lazy and leave this as-is for now. 😄
return ( | ||
<div className={className} {...rest}> | ||
<EuiTabs size={size}> | ||
{ |
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 like the indentation for these braces is off a bit.
...tabProps, | ||
onClick: () => this.onTabClick(tab), | ||
isSelected: tab === selectedTab, | ||
'aria-controls': `${this.rootId}-${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.
👍
|
||
// Mock the htmlIdGenerator to generate predictable ids for snapshot tests | ||
jest.mock('../../../services/accessibility/html_id_generator', () => ({ | ||
htmlIdGenerator: () => { return () => 42; }, |
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.
😂
}); | ||
|
||
describe('selectedTab', () => { | ||
test('is rendered', () => { |
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 understand what this means, but it might be unclear for the next person what is being rendered in this case.
6b9a5bc
to
f257d3a
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.
WFM
/** | ||
* Each tab needs an id property, so we can associate it with its panel for accessibility | ||
*/ | ||
tabs: PropTypes.arrayOf(PropTypes.shape({ id: PropTypes.string.isRequired })).isRequired, |
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.
name
should be required as it's the user-readable label on the tab
content
should be required because this component combines tab+content
this.rootId = makeId(); | ||
|
||
this.state = { | ||
selectedTab: selectedTab || initialSelectedTab || tabs[0], |
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.
if this component is controlled it should not track its own state independently, instead setting this to null
onTabClick(selectedTab) | ||
} | ||
|
||
this.setState({ selectedTab }) |
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.
likewise, if this component is controlled it should not store the selected tab in its own state
Thanks @chandlerprall! I've addressed your feedback. Can you take another look? |
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.
LGTM
jenkins test this |
1 similar comment
jenkins test this |
This component makes it easy to connect tabs with the content they display. You can either delegate state management to the component or provide props to control its state. Thanks @arkwright for building the initial version of this!