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

Allow other components inside TabList #123

Merged
merged 7 commits into from
Sep 14, 2016

Conversation

patrick91
Copy link
Contributor

Allows to add additional elements inside a TabList.
I've disabled the check that was throwing a warning when an element different from Tab was added to the TabList. Seems working well.

I needed to do this since I need to add a fake tab at the end of the TabList, like this:

<Tabs>
  <TabList>
    <Tab>Foo</Tab>
    <div>+</div>
  </TabList>

  <TabPanel>Hello</TabPanel>
</Tabs>

Maybe we can do the same for TabPanels, if needed.
Let me know your thoughts :)

@danez
Copy link
Collaborator

danez commented Jul 29, 2016

Nice, I think we could also optimize this and if we don't need to not clone the element. Because with this approach right now it would clone the <span> or whatever is supplied besides <tab> although not really necessary. (Correct me if I'm wrong)

@patrick91
Copy link
Contributor Author

Any idea on how to test this? I've tried with:

it('should not clone non tabs element', () => {
    const plus = <div>+</div>;

    const wrapper = mount(<Tabs>
    <TabList>
        <Tab>Foo</Tab>
        {plus}
    </TabList>

    <TabPanel>Hello Baz</TabPanel>
    </Tabs>);

    expect(wrapper.childAt(0).childAt(1) === plus).toBe(true);
});

but it is not working

@danez
Copy link
Collaborator

danez commented Aug 4, 2016

I'm not sure how to do this. childAt() returns a ReactWrapper and not the instance so they will be always different. And it doesn't seem that enzyme offers a way to retrieve the instance of children currently.

I asked on gitter, lets see if I can get an answer there.

};
}

return React.cloneElement(child, clonedProps);
Copy link
Collaborator

@danez danez Aug 4, 2016

Choose a reason for hiding this comment

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

This would still clone everytime.

    if (child.type.displayName === 'Tab') {
      return React.cloneElement(child, {
        activeTabClassName: props.activeTabClassName,
        disabledTabClassName: props.disabledTabClassName,
      });
    }

    return child;

@patrick91 patrick91 force-pushed the feature/allow-other-components branch from 3255935 to d76292a Compare August 4, 2016 16:22
@patrick91
Copy link
Contributor Author

Thanks! Don't know why I did that :D

Anyway, now it should be ok! In which gitter chat did you ask the question?

@danez
Copy link
Collaborator

danez commented Aug 4, 2016

It is this one: https://gitter.im/airbnb/enzyme

@patrick91
Copy link
Contributor Author

patrick91 commented Aug 10, 2016

@danez can you check the last commit?

I've been digging into the test suite of the cloneElement function and I got inspiration from the ref test: https://github.com/facebook/react/blob/2d74280679e17d33ac25d3e24c860bfffa9ae661/src/isomorphic/classic/element/__tests__/ReactElementClone-test.js#L102

Since we are cloning elements overriding the ref I've tried to make a test where I check that the original ref attribute is preserved. Seems working fine :)

EDIT: can I disable react/no-multi-comp for the test file?

Copy link
Collaborator

@danez danez left a comment

Choose a reason for hiding this comment

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

Awesome work, sorry for the late reply. Good to merge, just two more small things.

Thank you.

// if child is not a tab we don't need to clone it
// since we don't need to add custom props

if (child.type.displayName !== 'Tab') {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Was there a reason to use the displayName. If not I think it would be better to do child.type !== Type and import Tab from './Tab' at the top.

selected,
focus,
});
if (tab.type.displayName === 'Tab') {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here: tab.type === Tab

@@ -185,6 +185,27 @@ describe('react-tabs', () => {
expect(wrapper.childAt(2).text()).toBe('Hello Bar');
expect(wrapper.childAt(3).text()).toBe('Hello Baz');
});

it('should not clone non tabs element', () => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nice to figure out how to test this 👍
You can just add /* eslint-disable react/no-multi-comp */ at the top of the test to disable the lint.

@patrick91
Copy link
Contributor Author

Done!

@masad-frost
Copy link

Just FYI, you should avoid divs and other elements inside TabList, the HTML spec only permits li elements inside ul.

Thanks for this btw.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 28, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants