Skip to content
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

Merged
merged 5 commits into from
May 1, 2018
Merged

Add EuiTabbedContent. #737

merged 5 commits into from
May 1, 2018

Conversation

cjcenizal
Copy link
Contributor

@cjcenizal cjcenizal commented Apr 30, 2018

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!

@cjcenizal cjcenizal force-pushed the tabbed-content branch 2 times, most recently from 42ce61e to 4540cf6 Compare April 30, 2018 00:36
Copy link
Contributor

@snide snide left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Styling and function look proper. Thanks for passing down the size prop as well. Might want to doc your props.

image

Copy link
Contributor

@arkwright arkwright left a 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
Copy link
Contributor

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.

Copy link
Contributor Author

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}>
{
Copy link
Contributor

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}`,
Copy link
Contributor

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; },
Copy link
Contributor

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', () => {
Copy link
Contributor

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.

Copy link
Contributor

@cchaos cchaos left a 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,
Copy link
Contributor

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],
Copy link
Contributor

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 })
Copy link
Contributor

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

@cjcenizal
Copy link
Contributor Author

Thanks @chandlerprall! I've addressed your feedback. Can you take another look?

Copy link
Contributor

@chandlerprall chandlerprall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@cjcenizal
Copy link
Contributor Author

jenkins test this

1 similar comment
@chandlerprall
Copy link
Contributor

jenkins test this

@cjcenizal cjcenizal merged commit 537f19b into elastic:master May 1, 2018
@cjcenizal cjcenizal deleted the tabbed-content branch May 1, 2018 15:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants