PL
React - tworzenie prostego animowanego ekspandera
0
points
W tym krótkim artykule chcielibyśmy pokazać, jak stworzyć prosty ekspander w Reakcie.
Szybkie rozwiązanie:
// ONLINE-RUNNER:browser;
// Uwaga: Odkomentuj wiersze importu podczas pracy z kompilatorem JSX.
// import React from 'react';
// import ReactDOM from 'react-dom';
const expanderStyle = {
margin: '6px 0',
padding: '2px',
border: '1px solid silver'
};
const headerStyle = {
display: 'flex',
cursor: 'pointer'
};
const titleStyle = {
padding: '3px',
flex: 'none'
};
const spacerStyle = {
flex: '1'
};
const iconStyle = {
padding: '3px',
flex: 'none'
};
const contentStyle = {
overflow: 'hidden',
transition: 'all 0.3s'
};
const contentExpandedStyle = {
...contentStyle,
padding: '4px 0',
border: '1px solid silver',
height: 'auto',
filter: 'opacity(1)'
};
const contentCollapsedStyle = {
...contentStyle,
padding: '0 0',
border: '1px solid transparent',
height: '0',
filter: 'opacity(0)'
};
const Expander = ({title, children}) => {
const [expanded, setExpanded] = React.useState(false);
const handleHeaderClick = () => {
setExpanded(expanded => !expanded);
};
return (
<div style={expanderStyle}>
<div style={headerStyle} onClick={handleHeaderClick}>
<div style={titleStyle}>{title}</div>
<div style={spacerStyle} />
<div style={iconStyle}>{expanded ? '△' : '▽'}</div>
</div>
<div style={expanded ? contentExpandedStyle : contentCollapsedStyle}>
{children}
</div>
</div>
);
};
// Przykład użycia:
const App = () => {
return (
<div style={{height: '260px'}}>
<Expander title="🍏🍌🍊 Owoce">
<ul>
<li>🍏 Jabłko</li>
<li>🍌 Banan</li>
<li>🍊 Pomarańcza</li>
</ul>
</Expander>
<Expander title="🥕🥒🍅 Warzywa">
<ul>
<li>🥕 Marchewka</li>
<li>🥒 Ogórek</li>
<li>🍅 Pomidor</li>
</ul>
</Expander>
</div >
);
};
const root = document.querySelector('#root');
ReactDOM.render(<App/>, root );
Ekspander z przykładem jednego aktywnego elementu
W tej sekcji elementy ekspandera używają wspólnego kontekstu, co nie pozwala rozwinąć więcej niż jednego elementu w tym samym czasie.
// ONLINE-RUNNER:browser;
//Uwaga: Odkomentuj wiersze importu podczas pracy z kompilatorem JSX.
// import React from 'react';
// import ReactDOM from 'react-dom';
const expanderStyle = {
padding: '0 2px',
border: '1px solid silver'
};
const itemStyle = {
margin: '2px 0',
padding: '2px',
border: '1px solid silver'
};
const headerStyle = {
display: 'flex',
cursor: 'pointer'
};
const titleStyle = {
padding: '3px',
flex: 'none'
};
const spacerStyle = {
flex: '1'
};
const iconStyle = {
padding: '3px',
flex: 'none'
};
const contentStyle = {
overflow: 'hidden',
transition: 'all 0.3s'
};
const contentExpandedStyle = {
...contentStyle,
padding: '4px 0',
border: '1px solid silver',
height: 'auto',
filter: 'opacity(1)'
};
const contentCollapsedStyle = {
...contentStyle,
padding: '0 0',
border: '1px solid transparent',
height: '0',
filter: 'opacity(0)'
};
const ExpanderContext = React.createContext();
const Expander = ({children}) => {
const [expandedItem, setExpandedItem] = React.useState(null);
const expander = {
isExpandedItem: (title) => title === expandedItem,
setExpandedItem: (title) => {
setExpandedItem(expandedItem === title ? null : title);
}
};
return (
<ExpanderContext.Provider value={expander}>
<div style={expanderStyle}>
{children}
</div>
</ExpanderContext.Provider>
);
};
const Item = ({title, children}) => {
const expander = React.useContext(ExpanderContext);
const expanded = expander.isExpandedItem(title);
const handleHeaderClick = () => {
expander.setExpandedItem(title);
};
return (
<div style={itemStyle}>
<div style={headerStyle} onClick={handleHeaderClick}>
<div style={titleStyle}>{title}</div>
<div style={spacerStyle} />
<div style={iconStyle}>{expanded ? '△' : '▽'}</div>
</div>
<div style={expanded ? contentExpandedStyle : contentCollapsedStyle}>
{children}
</div>
</div>
);
};
// Przykład użycia:
const App = () => {
return (
<div style={{width: '500px', height: '250px'}}>
<Expander>
<Item title="🍏🍌🍊 Owoce">
<ul>
<li>🍏 Jabłko</li>
<li>🍌 Banan</li>
<li>🍊 Pomarańcza</li>
</ul>
</Item>
<Item title="🥕🥒🍅 Warzywa">
<ul>
<li>🥕 Marchewka</li>
<li>🥒 Ogórek</li>
<li>🍅 Pomidor</li>
</ul>
</Item>
</Expander>
</div >
);
};
const root = document.querySelector('#root');
ReactDOM.render(<App/>, root );