React Bootstrap is one version of Bootstrap made for React.
It’s a set of React components that have Bootstrap styles.
In this article, we’ll look at how to work with React Bootstrap’s accordions in our React components.
Accordion
Accordions let us restrict card components to open only one at a time.
To use it, we can write:
import React from "react";
import Accordion from "react-bootstrap/Accordion";
import Card from "react-bootstrap/Card";
import Button from "react-bootstrap/Button";
import "bootstrap/dist/css/bootstrap.min.css";
export default function App() {
return (
<>
<Accordion defaultActiveKey="0">
<Card>
<Card.Header>
<Accordion.Toggle as={Button} variant="link" eventKey="0">
title 1
</Accordion.Toggle>
</Card.Header>
<Accordion.Collapse eventKey="0">
<Card.Body>body 1</Card.Body>
</Accordion.Collapse>
</Card>
<Card>
<Card.Header>
<Accordion.Toggle as={Button} variant="link" eventKey="1">
title 2
</Accordion.Toggle>
</Card.Header>
<Accordion.Collapse eventKey="1">
<Card.Body>body 2</Card.Body>
</Accordion.Collapse>
</Card>
</Accordion>
</>
);
}
We imported the Accordion
and Card
components.
It has the defaultActionKey
is the key for the default card.
Accordion.Toggle
is the toggle to open the card.
as
is the prop to let us specify what component to render the toggle as.
variant
is the style that we want to render the toggle as.
eventKey
is the key for the given card.
Fully Collapsed State
If we don’t specify the defaultActiveKey
, then all cards will be collapsed.
For example, we can write:
import React from "react";
import Accordion from "react-bootstrap/Accordion";
import Card from "react-bootstrap/Card";
import Button from "react-bootstrap/Button";
import "bootstrap/dist/css/bootstrap.min.css";
export default function App() {
return (
<>
<Accordion>
<Card>
<Card.Header>
<Accordion.Toggle as={Button} variant="link" eventKey="0">
title 1
</Accordion.Toggle>
</Card.Header>
<Accordion.Collapse eventKey="0">
<Card.Body>body 1</Card.Body>
</Accordion.Collapse>
</Card>
<Card>
<Card.Header>
<Accordion.Toggle as={Button} variant="link" eventKey="1">
title 2
</Accordion.Toggle>
</Card.Header>
<Accordion.Collapse eventKey="1">
<Card.Body>body 2</Card.Body>
</Accordion.Collapse>
</Card>
</Accordion>
</>
);
}
Make the Entire Header Clickable
We can make the entire header clickable by rendering the header as a Card.Header
.
For instance, we can write:
import React from "react";
import Accordion from "react-bootstrap/Accordion";
import Card from "react-bootstrap/Card";
import "bootstrap/dist/css/bootstrap.min.css";
export default function App() {
return (
<>
<Accordion>
<Card>
<Card.Header>
<Accordion.Toggle as={Card.Header} variant="link" eventKey="0">
title 1
</Accordion.Toggle>
</Card.Header>
<Accordion.Collapse eventKey="0">
<Card.Body>body 1</Card.Body>
</Accordion.Collapse>
</Card>
<Card>
<Card.Header>
<Accordion.Toggle as={Card.Header} variant="link" eventKey="1">
title 2
</Accordion.Toggle>
</Card.Header>
<Accordion.Collapse eventKey="1">
<Card.Body>body 2</Card.Body>
</Accordion.Collapse>
</Card>
</Accordion>
</>
);
}
We make the part outside the text clickable by changing the as
to Card.Header
.
Custom Toggle
We can create our custom toggle component with the useAccordionToggle
hook.
It takes the eventKey
and a callback that runs when the roggle is clicked.
For instance, we can write:
import React from "react";
import Accordion from "react-bootstrap/Accordion";
import Card from "react-bootstrap/Card";
import { useAccordionToggle } from "react-bootstrap/AccordionToggle";
import "bootstrap/dist/css/bootstrap.min.css";
function CustomToggle({ children, eventKey }) {
const decoratedOnClick = useAccordionToggle(eventKey, () =>
console.log("toggle clicked")
);
return (
<button
type="button"
style={{ backgroundColor: "orange" }}
onClick={decoratedOnClick}
>
{children}
</button>
);
}
export default function App() {
return (
<>
<Accordion>
<Card>
<Card.Header>
<CustomToggle eventKey="0">title 1</CustomToggle>
</Card.Header>
<Accordion.Collapse eventKey="0">
<Card.Body>body 1</Card.Body>
</Accordion.Collapse>
</Card>
<Card>
<Card.Header>
<CustomToggle eventKey="0">title 2</CustomToggle>
</Card.Header>
<Accordion.Collapse eventKey="1">
<Card.Body>body 2</Card.Body>
</Accordion.Collapse>
</Card>
</Accordion>
</>
);
}
We have the CustomToggle
component which we created ourselves.
It takes the children
and eventKey
props.
children
lets us display content that we pass inside the component tags.
useAccordingToggle
returns a click handler that opens the card with the given eventKey
.
The 2nd argument is a callback that lets us run anything when the toggle is clicked.
Then we can use the CustomToggle
in place of the toggle that comes with React Bootstrap to toggle our cards.
Custom Toggle with Expansion Awareness
We can also check if the toggle has expanded the card when it’s clicked.
To do that, we use the context API to listen to the accordion to the AccordionContext
.
For instance, we can write:
import React from "react";
import Accordion from "react-bootstrap/Accordion";
import AccordionContext from "react-bootstrap/AccordionContext";
import Card from "react-bootstrap/Card";
import { useAccordionToggle } from "react-bootstrap/AccordionToggle";
import "bootstrap/dist/css/bootstrap.min.css";
function CustomToggle({ children, eventKey, callback }) {
const currentEventKey = React.useContext(AccordionContext);
const decoratedOnClick = useAccordionToggle(
eventKey,
() => callback && callback(eventKey)
);
const isCurrentEventKey = currentEventKey === eventKey;
return (
<button
type="button"
style={{ backgroundColor: isCurrentEventKey ? "orange" : "pink" }}
onClick={decoratedOnClick}
>
{children}
</button>
);
}
export default function App() {
return (
<>
<Accordion>
<Card>
<Card.Header>
<CustomToggle eventKey="0">title 1</CustomToggle>
</Card.Header>
<Accordion.Collapse eventKey="0">
<Card.Body>body 1</Card.Body>
</Accordion.Collapse>
</Card>
<Card>
<Card.Header>
<CustomToggle eventKey="1">title 2</CustomToggle>
</Card.Header>
<Accordion.Collapse eventKey="1">
<Card.Body>body 2</Card.Body>
</Accordion.Collapse>
</Card>
</Accordion>
</>
);
}
We get the eventKey
prop with our CustomToggle
so that we can compare to the currentEventKey
that we have in our context.
Then we have the useAccordionToggle
as we did with the previous example.
It returns a click handler that we pass into onClick
to expand the card.
isCurrentKey
has the result of comparing the eventKey
of the toggle with the one from the context which has the one that’s opened.
So we can use that to style the toggle the way we like when the card is open or closed.
Conclusion
Accordions let us restrict card components to open only one at a time.
We can customize the toggle and the card content.