Kebab file names
This commit is contained in:
95
snippets/tabs.md
Normal file
95
snippets/tabs.md
Normal file
@ -0,0 +1,95 @@
|
||||
---
|
||||
title: Tabs
|
||||
tags: components,state,children
|
||||
cover: by-the-lighthouse
|
||||
firstSeen: 2019-01-27T11:59:52+02:00
|
||||
lastUpdated: 2021-10-13T19:29:39+02:00
|
||||
---
|
||||
|
||||
Renders a tabbed menu and view component.
|
||||
|
||||
- Define a `Tabs` component. Use the `useState()` hook to initialize the value of the `bindIndex` state variable to `defaultIndex`.
|
||||
- Define a `TabItem` component and filter `children` passed to the `Tabs` component to remove unnecessary nodes except for `TabItem` by identifying the function's name.
|
||||
- Define `changeTab`, which will be executed when clicking a `<button>` from the menu.
|
||||
- `changeTab` executes the passed callback, `onTabClick`, and updates `bindIndex` based on the clicked element.
|
||||
- Use `Array.prototype.map()` on the collected nodes to render the menu and view of the tabs.
|
||||
- Use the value of `bindIndex` to determine the active tab and apply the correct `className`.
|
||||
|
||||
```css
|
||||
.tab-menu > button {
|
||||
cursor: pointer;
|
||||
padding: 8px 16px;
|
||||
border: 0;
|
||||
border-bottom: 2px solid transparent;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.tab-menu > button.focus {
|
||||
border-bottom: 2px solid #007bef;
|
||||
}
|
||||
|
||||
.tab-menu > button:hover {
|
||||
border-bottom: 2px solid #007bef;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tab-content.selected {
|
||||
display: block;
|
||||
}
|
||||
```
|
||||
|
||||
```jsx
|
||||
const TabItem = props => <div {...props} />;
|
||||
|
||||
const Tabs = ({ defaultIndex = 0, onTabClick, children }) => {
|
||||
const [bindIndex, setBindIndex] = React.useState(defaultIndex);
|
||||
const changeTab = newIndex => {
|
||||
if (typeof onTabClick === 'function') onTabClick(newIndex);
|
||||
setBindIndex(newIndex);
|
||||
};
|
||||
const items = children.filter(item => item.type.name === 'TabItem');
|
||||
|
||||
return (
|
||||
<div className="wrapper">
|
||||
<div className="tab-menu">
|
||||
{items.map(({ props: { index, label } }) => (
|
||||
<button
|
||||
key={`tab-btn-${index}`}
|
||||
onClick={() => changeTab(index)}
|
||||
className={bindIndex === index ? 'focus' : ''}
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<div className="tab-view">
|
||||
{items.map(({ props }) => (
|
||||
<div
|
||||
{...props}
|
||||
className={`tab-content ${
|
||||
bindIndex === props.index ? 'selected' : ''
|
||||
}`}
|
||||
key={`tab-content-${props.index}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
```jsx
|
||||
ReactDOM.createRoot(document.getElementById('root')).render(
|
||||
<Tabs defaultIndex="1" onTabClick={console.log}>
|
||||
<TabItem label="A" index="1">
|
||||
Lorem ipsum
|
||||
</TabItem>
|
||||
<TabItem label="B" index="2">
|
||||
Dolor sit amet
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
);
|
||||
```
|
||||
Reference in New Issue
Block a user