This is a card with some text on it, it's the first one in the
deck.
@@ -256,8 +256,8 @@ const Demo = () => (
-
The second card
-
+
The second card
+
This is a card with some text on it, it's the second one in the
deck. It has a bit more text in it so that we can see how the
vertical spacing will work.
@@ -266,9 +266,9 @@ const Demo = () => (
-
The third card
-
...and the last :(
-
This card doesn't have much text...
+
The third card
+
...and the last :(
+
This card doesn't have much text...
@@ -365,7 +365,7 @@ const Demo = () => (
-
This content fades in and out
+
This content fades in and out
diff --git a/docs/components_page/__init__.py b/docs/components_page/__init__.py
index 64daf3579..36b94bae7 100644
--- a/docs/components_page/__init__.py
+++ b/docs/components_page/__init__.py
@@ -59,6 +59,7 @@ def _get_label(slug):
def register_apps():
component_bodies = {
+ "accordion": {"markdown_path": COMPONENTS / "accordion.md"},
"alert": {"markdown_path": COMPONENTS / "alert.md"},
"badge": {"markdown_path": COMPONENTS / "badge.md"},
"button": {"markdown_path": COMPONENTS / "button.md"},
diff --git a/docs/components_page/components/__tests__/test_accordion.py b/docs/components_page/components/__tests__/test_accordion.py
new file mode 100644
index 000000000..34055de79
--- /dev/null
+++ b/docs/components_page/components/__tests__/test_accordion.py
@@ -0,0 +1,68 @@
+"""
+Testing of callbacks in non-Python Accordion snippets.
+"""
+from pathlib import Path
+
+import dash.testing.wait as wait
+
+from .helpers import load_jl_app, load_r_app
+
+HERE = Path(__file__).parent
+
+
+def test_r_simple(dashr):
+ r_app = load_r_app((HERE.parent / "accordion" / "simple.R"), "accordion")
+ dashr.start_server(r_app)
+ check_simple_callbacks(dashr)
+
+
+def test_jl_simple(dashjl):
+ jl_app = load_jl_app(
+ (HERE.parent / "accordion" / "simple.jl"), "accordion"
+ )
+ dashjl.start_server(jl_app)
+ check_simple_callbacks(dashjl)
+
+
+def check_simple_callbacks(runner):
+ # Find the accordion object
+ accordion_comp = runner.find_element("#accordion")
+ accordion_text = runner.find_element("#accordion-contents")
+
+ # Check it has 3 page-items objects in it
+ pages = accordion_comp.find_elements(".accordion-item")
+ wait.until(
+ lambda: len(pages) == 3,
+ timeout=4,
+ )
+
+ # Click the third section
+ wait.until(
+ lambda: pages[2].find_elements(".accordion-collapse").text
+ == "This is the content of the third section",
+ timeout=4,
+ )
+ pages[2].find_elements(".accordion-button").click()
+
+ # Check the text in contents changes to "Item selected: item-2"
+ wait.until(
+ lambda: accordion_text.text == "Item selected: item-2",
+ timeout=4,
+ )
+
+ # Change the slider to value 1
+ runner.click_at_coord_fractions(
+ runner.find_element("#item-change"), 0.5, 0.25
+ )
+
+ # Check the text in contents changes to "Item selected: item-1"
+ wait.until(
+ lambda: accordion_text.text == "Item selected: item-1",
+ timeout=4,
+ )
+
+ # Check that the right section is showing
+ item = accordion_comp.find_element(".show")
+ wait.until(
+ lambda: item.text == "This is the content of the second section"
+ )
diff --git a/docs/components_page/components/accordion.md b/docs/components_page/components/accordion.md
new file mode 100644
index 000000000..d051b57d4
--- /dev/null
+++ b/docs/components_page/components/accordion.md
@@ -0,0 +1,22 @@
+---
+title: Accordion
+lead: Use the Accordion component to create collapsible lists.
+---
+
+You can create an accordion using the `Accordion` and `AccordionItem` components. Each item in the accordion can be assiged a specific `item_id` which is used in the `active_item` property to determine which section is open. If no `item_id` is specified, the sections are labelled as `item-0`, `item-1`, ... consecutively. Each section header is determined by the `title` prop of the `AccordionItem`.
+
+{{example:components/accordion/simple.py:accordion}}
+
+## Start Collapsed
+
+You can set which item is opened when it is first started using the `active_item` property. If this is not defined, the first item will be open by default. If you want no items to be open on start up, you can specify `start_collapsed=True`.
+
+{{example:components/accordion/collapsed.py:accordion}}
+
+## Flush
+
+Add flush to change some of the styling, including removing borders, and rounding some of the edges to fit in line with the parent container.
+
+{{example:components/accordion/flush.py:accordion}}
+
+{{apidoc:src/components/accordion/Accordion.js}}
diff --git a/docs/components_page/components/accordion/collapsed.R b/docs/components_page/components/accordion/collapsed.R
new file mode 100644
index 000000000..1779a11bb
--- /dev/null
+++ b/docs/components_page/components/accordion/collapsed.R
@@ -0,0 +1,22 @@
+library(dashBootstrapComponents)
+library(dashHtmlComponents)
+
+accordion <- htmlDiv(
+ dbcAccordion(
+ list(
+ dbcAccordionItem(
+ "This is the content of the first section",
+ title="Item 1",
+ ),
+ dbcAccordionItem(
+ "This is the content of the second section",
+ title="Item 2",
+ ),
+ dbcAccordionItem(
+ "This is the content of the third section",
+ title="Item 3",
+ ),
+ ),
+ start_collapsed=TRUE,
+ ),
+)
diff --git a/docs/components_page/components/accordion/collapsed.jl b/docs/components_page/components/accordion/collapsed.jl
new file mode 100644
index 000000000..faca13d56
--- /dev/null
+++ b/docs/components_page/components/accordion/collapsed.jl
@@ -0,0 +1,21 @@
+using DashBootstrapComponents, DashHtmlComponents
+
+accordion = html_div(
+ dbc_accordion(
+ [
+ dbc_accordionitem(
+ "This is the content of the first section",
+ title="Item 1",
+ ),
+ dbc_accordionitem(
+ "This is the content of the second section",
+ title="Item 2",
+ ),
+ dbc_accordionitem(
+ "This is the content of the third section",
+ title="Item 3",
+ ),
+ ],
+ start_collapsed=true,
+ ),
+)
diff --git a/docs/components_page/components/accordion/collapsed.py b/docs/components_page/components/accordion/collapsed.py
new file mode 100644
index 000000000..da0b0fd0f
--- /dev/null
+++ b/docs/components_page/components/accordion/collapsed.py
@@ -0,0 +1,22 @@
+import dash_bootstrap_components as dbc
+import dash_html_components as html
+
+accordion = html.Div(
+ dbc.Accordion(
+ [
+ dbc.AccordionItem(
+ "This is the content of the first section",
+ title="Item 1",
+ ),
+ dbc.AccordionItem(
+ "This is the content of the second section",
+ title="Item 2",
+ ),
+ dbc.AccordionItem(
+ "This is the content of the third section",
+ title="Item 3",
+ ),
+ ],
+ start_collapsed=True,
+ ),
+)
diff --git a/docs/components_page/components/accordion/flush.R b/docs/components_page/components/accordion/flush.R
new file mode 100644
index 000000000..ec3a6c724
--- /dev/null
+++ b/docs/components_page/components/accordion/flush.R
@@ -0,0 +1,22 @@
+library(dashBootstrapComponents)
+library(dashHtmlComponents)
+
+accordion <- htmlDiv(
+ dbcAccordion(
+ list(
+ dbcAccordionItem(
+ "This is the content of the first section",
+ title="Item 1",
+ ),
+ dbcAccordionItem(
+ "This is the content of the second section",
+ title="Item 2",
+ ),
+ dbcAccordionItem(
+ "This is the content of the third section",
+ title="Item 3",
+ ),
+ ),
+ flush=TRUE,
+ ),
+)
diff --git a/docs/components_page/components/accordion/flush.jl b/docs/components_page/components/accordion/flush.jl
new file mode 100644
index 000000000..3b32b9d5c
--- /dev/null
+++ b/docs/components_page/components/accordion/flush.jl
@@ -0,0 +1,21 @@
+using DashBootstrapComponents, DashHtmlComponents
+
+accordion = html_div(
+ dbc_accordion(
+ [
+ dbc_accordionitem(
+ "This is the content of the first section",
+ title="Item 1",
+ ),
+ dbc_accordionitem(
+ "This is the content of the second section",
+ title="Item 2",
+ ),
+ dbc_accordionitem(
+ "This is the content of the third section",
+ title="Item 3",
+ ),
+ ],
+ flush=true,
+ ),
+)
diff --git a/docs/components_page/components/accordion/flush.py b/docs/components_page/components/accordion/flush.py
new file mode 100644
index 000000000..15f80d311
--- /dev/null
+++ b/docs/components_page/components/accordion/flush.py
@@ -0,0 +1,22 @@
+import dash_bootstrap_components as dbc
+import dash_html_components as html
+
+accordion = html.Div(
+ dbc.Accordion(
+ [
+ dbc.AccordionItem(
+ "This is the content of the first section",
+ title="Item 1",
+ ),
+ dbc.AccordionItem(
+ "This is the content of the second section",
+ title="Item 2",
+ ),
+ dbc.AccordionItem(
+ "This is the content of the third section",
+ title="Item 3",
+ ),
+ ],
+ flush=True,
+ ),
+)
diff --git a/docs/components_page/components/accordion/simple.R b/docs/components_page/components/accordion/simple.R
new file mode 100644
index 000000000..e17c5b933
--- /dev/null
+++ b/docs/components_page/components/accordion/simple.R
@@ -0,0 +1,55 @@
+library(dashBootstrapComponents)
+library(dashCoreComponents)
+library(dashHtmlComponents)
+
+accordion <- htmlDiv(
+ list(
+ htmlDiv("Select an item", id="accordion-contents"),
+ dbcAccordion(
+ list(
+ dbcAccordionItem(
+ "This is the content of the first section",
+ title="Item 1",
+ ),
+ dbcAccordionItem(
+ "This is the content of the second section",
+ title="Item 2",
+ ),
+ dbcAccordionItem(
+ "This is the content of the third section",
+ title="Item 3",
+ ),
+ ),
+ id="accordion",
+ ),
+ htmlDiv(
+ "Or set the open item dynamically using the slider below",
+ class_name="py-2",
+ ),
+ dccSlider(
+ id="item-change",
+ min=0,
+ max=2,
+ step=1,
+ value=0,
+ marks=list(0="0", 1="1", 2="2")
+ ),
+ )
+)
+
+
+@app.callback(
+ Output("accordion-contents", "children"),
+ [Input("accordion", "active_item")],
+)
+def change_item(item):
+ if item:
+ return f"Item selected: {item}"
+ return "Select an item"
+
+
+@app.callback(
+ Output("accordion", "active_item"), [Input("item-change", "value")]
+)
+def change_active_item(value):
+ return f"item-{value}"
diff --git a/docs/components_page/components/accordion/simple.jl b/docs/components_page/components/accordion/simple.jl
new file mode 100644
index 000000000..15770cb11
--- /dev/null
+++ b/docs/components_page/components/accordion/simple.jl
@@ -0,0 +1,54 @@
+using DashBootstrapComponents, DashCoreComponents, DashHtmlComponents
+
+accordion = html_div(
+ [
+ html_div("Select an item", id="accordion-contents"),
+ dbc_accordion(
+ [
+ dbc_accordionitem(
+ "This is the content of the first section",
+ title="Item 1",
+ ),
+ dbc_accordionitem(
+ "This is the content of the second section",
+ title="Item 2",
+ ),
+ dbc_accordionitem(
+ "This is the content of the third section",
+ title="Item 3",
+ ),
+ ],
+ id="accordion",
+ ),
+ html_div(
+ "Or set the open item dynamically using the slider below",
+ class_name="py-2",
+ ),
+ dcc_slider(
+ id="item-change",
+ min=0,
+ max=2,
+ step=1,
+ value=0,
+ marks=Dict(0 => "0", 1 => "1", 2 => "2"),
+ ),
+ ]
+)
+
+
+callback(
+ app,
+ Output("accordion-contents", "children"),
+ Input("accordion", "active_item"),
+) do item
+ return item ? "Item selected: $item" : "Select an item"
+end;
+
+
+callback(
+ app,
+ Output("accordion", "active_item"),
+ Input("item-change", "value")
+) do value
+ return "item-$value"
+end;
diff --git a/docs/components_page/components/accordion/simple.py b/docs/components_page/components/accordion/simple.py
new file mode 100644
index 000000000..042fefccd
--- /dev/null
+++ b/docs/components_page/components/accordion/simple.py
@@ -0,0 +1,56 @@
+import dash_bootstrap_components as dbc
+import dash_core_components as dcc
+import dash_html_components as html
+from dash.dependencies import Input, Output
+
+accordion = html.Div(
+ [
+ html.Div("Select an item", id="accordion-contents"),
+ dbc.Accordion(
+ [
+ dbc.AccordionItem(
+ "This is the content of the first section",
+ title="Item 1",
+ ),
+ dbc.AccordionItem(
+ "This is the content of the second section",
+ title="Item 2",
+ ),
+ dbc.AccordionItem(
+ "This is the content of the third section",
+ title="Item 3",
+ ),
+ ],
+ id="accordion",
+ ),
+ html.Div(
+ "Or set the open item dynamically using the slider below",
+ class_name="py-2",
+ ),
+ dcc.Slider(
+ id="item-change",
+ min=0,
+ max=2,
+ step=1,
+ value=0,
+ marks={i: str(i) for i in range(3)},
+ ),
+ ]
+)
+
+
+@app.callback(
+ Output("accordion-contents", "children"),
+ [Input("accordion", "active_item")],
+)
+def change_item(item):
+ if item:
+ return f"Item selected: {item}"
+ return "Select an item"
+
+
+@app.callback(
+ Output("accordion", "active_item"), [Input("item-change", "value")]
+)
+def change_active_item(value):
+ return f"item-{value}"
diff --git a/setup.cfg b/setup.cfg
index 78566eb81..a6214b353 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -2,6 +2,9 @@
exclude =
node_modules,
dash_bootstrap_components/_components,
+ docs/components_page/components/accordion/collapsed.py,
+ docs/components_page/components/accordion/flush.py,
+ docs/components_page/components/accordion/simple.py,
docs/components_page/components/alert/auto_dismiss.py,
docs/components_page/components/alert/dismiss.py,
docs/components_page/components/button/usage.py,
diff --git a/src/components/accordion/Accordion.js b/src/components/accordion/Accordion.js
new file mode 100644
index 000000000..8371aa883
--- /dev/null
+++ b/src/components/accordion/Accordion.js
@@ -0,0 +1,206 @@
+import React, {useEffect} from 'react';
+import PropTypes from 'prop-types';
+import {omit} from 'ramda';
+import {default as RBAccordion} from 'react-bootstrap/Accordion';
+
+const resolveChildProps = child => {
+ // This may need to change in the future if https://github.com/plotly/dash-renderer/issues/84 is addressed
+ if (
+ child.props._dashprivate_layout &&
+ child.props._dashprivate_layout.props
+ ) {
+ // props are coming from Dash
+ return child.props._dashprivate_layout.props;
+ } else {
+ // else props are coming from React (e.g. Demo.js, or Tabs.test.js)
+ return child.props;
+ }
+};
+
+const Accordion = props => {
+ const {
+ children,
+ active_item,
+ start_collapsed,
+ loading_state,
+ key,
+ setProps,
+ ...otherProps
+ } = props;
+
+ // if active_item not set initially, choose first item
+ useEffect(() => {
+ if (setProps && active_item === undefined && !start_collapsed) {
+ setProps({
+ active_item:
+ children && (resolveChildProps(children[0]).item_id || 'item-0')
+ });
+ }
+ }, []);
+
+ const toggle = item => {
+ if (setProps) {
+ if (active_item !== item) {
+ setProps({active_item: item});
+ }
+ }
+ };
+
+ const items =
+ children &&
+ children.map((child, idx) => {
+ const childProps = resolveChildProps(child);
+ const {
+ children,
+ title,
+ item_id,
+ loading_state,
+ ...otherProps
+ } = childProps;
+ const itemID = item_id || 'item-' + idx;
+ return (
+
+ {
+ toggle(itemID);
+ }}
+ // .dbcd-main h2 has margins defined on it - we need to make
+ // sure to overwrite them
+ style={{marginTop: '0rem', marginBottom: '0rem'}}
+ >
+ {title}
+
+ {children}
+
+ );
+ });
+ return (
+
+ {items}
+
+ );
+};
+
+Accordion.defaultProps = {
+ persisted_props: ['active_item'],
+ persistence_type: 'local',
+ start_collapsed: false
+};
+
+Accordion.propTypes = {
+ /**
+ * The ID of this component, used to identify dash components
+ * in callbacks. The ID needs to be unique across all of the
+ * components in an app.
+ */
+ id: PropTypes.string,
+
+ /**
+ * The children of this component
+ */
+ children: PropTypes.node,
+
+ /**
+ * Defines CSS styles which will override styles previously set.
+ */
+ style: PropTypes.object,
+
+ /**
+ * Often used with CSS to style elements with common properties.
+ */
+ class_name: PropTypes.string,
+
+ /**
+ * A unique identifier for the component, used to improve
+ * performance by React.js while rendering components
+ * See https://reactjs.org/docs/lists-and-keys.html for more info
+ */
+ key: PropTypes.string,
+
+ /**
+ * Renders accordion edge-to-edge with its parent container
+ */
+ flush: PropTypes.bool,
+
+ /**
+ * The item_id of the currently active item. If item_id has not been specified
+ * for the active item, this will default to item-i, where i is the index
+ * (starting from 0) of the item.
+ */
+ active_item: PropTypes.string,
+
+ /**
+ *
+ */
+ start_collapsed: PropTypes.bool,
+
+ /**
+ * Object that holds the loading state object coming from dash-renderer
+ */
+ loading_state: PropTypes.shape({
+ /**
+ * Determines if the component is loading or not
+ */
+ is_loading: PropTypes.bool,
+ /**
+ * Holds which property is loading
+ */
+ prop_name: PropTypes.string,
+ /**
+ * Holds the name of the component that is loading
+ */
+ component_name: PropTypes.string
+ }),
+
+ /**
+ * Used to allow user interactions in this component to be persisted when
+ * the component - or the page - is refreshed. If `persisted` is truthy and
+ * hasn't changed from its previous value, a `value` that the user has
+ * changed while using the app will keep that change, as long as
+ * the new `value` also matches what was given originally.
+ * Used in conjunction with `persistence_type`.
+ */
+ persistence: PropTypes.oneOfType([
+ PropTypes.bool,
+ PropTypes.string,
+ PropTypes.number
+ ]),
+
+ /**
+ * Properties whose user interactions will persist after refreshing the
+ * component or the page. Since only `value` is allowed this prop can
+ * normally be ignored.
+ */
+ persisted_props: PropTypes.arrayOf(PropTypes.oneOf(['active_item'])),
+
+ /**
+ * Where persisted user changes will be stored:
+ * memory: only kept in memory, reset on page refresh.
+ * local: window.localStorage, data is kept after the browser quit.
+ * session: window.sessionStorage, data is cleared once the browser quit.
+ */
+ persistence_type: PropTypes.oneOf(['local', 'session', 'memory'])
+};
+
+export default Accordion;
diff --git a/src/components/accordion/AccordionItem.js b/src/components/accordion/AccordionItem.js
new file mode 100644
index 000000000..014cb43cb
--- /dev/null
+++ b/src/components/accordion/AccordionItem.js
@@ -0,0 +1,63 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+const AccordionItem = props => {
+ return <>>;
+};
+
+AccordionItem.propTypes = {
+ /**
+ * The ID of this component, used to identify dash components
+ * in callbacks. The ID needs to be unique across all of the
+ * components in an app.
+ */
+ id: PropTypes.string,
+
+ /**
+ * The children of this component
+ */
+ children: PropTypes.node,
+
+ /**
+ * Defines CSS styles which will override styles previously set.
+ */
+ style: PropTypes.object,
+
+ /**
+ * Often used with CSS to style elements with common properties.
+ */
+ class_name: PropTypes.string,
+
+ /**
+ * The title on display in the collapsed accordion item.
+ */
+ title: PropTypes.string,
+
+ /**
+ * Optional identifier for item used for determining which item is visible
+ * if not specified, and AccordionItem is being used inside Accordion component, the itemId
+ * will be set to "item-i" where i is (zero indexed) position of item in list
+ * items pased to Accordion component.
+ */
+ item_id: PropTypes.string,
+
+ /**
+ * Object that holds the loading state object coming from dash-renderer
+ */
+ loading_state: PropTypes.shape({
+ /**
+ * Determines if the component is loading or not
+ */
+ is_loading: PropTypes.bool,
+ /**
+ * Holds which property is loading
+ */
+ prop_name: PropTypes.string,
+ /**
+ * Holds the name of the component that is loading
+ */
+ component_name: PropTypes.string
+ })
+};
+
+export default AccordionItem;
diff --git a/src/components/accordion/__tests__/Accordion.test.js b/src/components/accordion/__tests__/Accordion.test.js
new file mode 100644
index 000000000..e087e93cc
--- /dev/null
+++ b/src/components/accordion/__tests__/Accordion.test.js
@@ -0,0 +1,128 @@
+import React from 'react';
+import {render} from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+import Accordion from '../Accordion';
+import AccordionItem from '../AccordionItem';
+
+jest.useFakeTimers();
+
+describe('Accordion', () => {
+ test('renders a div with accordion class', () => {
+ const {container} = render();
+ expect(container.querySelector('div.accordion')).not.toBe(null);
+ });
+
+ test('renders each item correctly, in order', () => {
+ const {container} = render(
+
+ item-content-1
+ item-content-2
+
+ );
+
+ const accordionItems = container.querySelector('div.accordion');
+
+ // Item class
+ expect(accordionItems.children[0]).toHaveClass('accordion-item');
+ expect(accordionItems.children[1]).toHaveClass('accordion-item');
+
+ // Headers
+ expect(
+ accordionItems.children[0].querySelector('h2.accordion-header')
+ ).toHaveTextContent('item-label-1');
+ expect(
+ accordionItems.children[1].querySelector('h2.accordion-header')
+ ).toHaveTextContent('item-label-2');
+
+ // Content
+ expect(
+ accordionItems.children[0].querySelector('div.accordion-collapse')
+ ).toHaveTextContent('item-content-1');
+ expect(
+ accordionItems.children[1].querySelector('div.accordion-collapse')
+ ).toHaveTextContent('item-content-2');
+ });
+
+ test('sets currently active item with "active_item" prop', () => {
+ const {container} = render(
+
+
+ item-content-1
+
+
+ item-content-2
+
+
+ );
+
+ const accordionItems = container.querySelector('div.accordion');
+
+ expect(
+ accordionItems.children[0].querySelector('div.accordion-collapse')
+ ).not.toHaveClass('show');
+ expect(
+ accordionItems.children[1].querySelector('div.accordion-collapse')
+ ).toHaveClass('show');
+ });
+
+ test('starts in a collapsed state with "start_collapsed" prop', () => {
+ const {container} = render(
+
+
+ item-content-1
+
+
+ item-content-2
+
+
+ );
+
+ const accordionItems = container.querySelector('div.accordion');
+
+ expect(
+ accordionItems.children[0].querySelector('div.accordion-collapse')
+ ).not.toHaveClass('show');
+ expect(
+ accordionItems.children[1].querySelector('div.accordion-collapse')
+ ).not.toHaveClass('show');
+ });
+
+ test('tracks most recently clicked item with "active_item" prop', () => {
+ const mockSetProps = jest.fn();
+ const {container, rerender} = render(
+
+ item-content-1
+ item-content-2
+
+ );
+
+ let accordionItems = container.querySelector('div.accordion');
+
+ expect(
+ accordionItems.children[0].querySelector('div.accordion-collapse')
+ ).toHaveClass('show');
+ expect(
+ accordionItems.children[1].querySelector('div.accordion-collapse')
+ ).not.toHaveClass('show');
+
+ userEvent.click(
+ accordionItems.children[1].querySelector('h2.accordion-header > button')
+ );
+ expect(mockSetProps.mock.calls).toHaveLength(1);
+
+ rerender(
+
+ item-content-1
+ item-content-2
+
+ );
+ jest.runAllTimers();
+
+ expect(
+ accordionItems.children[0].querySelector('div.accordion-collapse')
+ ).not.toHaveClass('show');
+ expect(
+ accordionItems.children[1].querySelector('div.accordion-collapse')
+ ).toHaveClass('show');
+ });
+});
diff --git a/src/index.js b/src/index.js
index 0e92b88e1..a84989f0a 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,3 +1,5 @@
+export {default as Accordion} from './components/accordion/Accordion';
+export {default as AccordionItem} from './components/accordion/AccordionItem';
export {default as Alert} from './components/Alert';
export {default as Badge} from './components/Badge';
export {default as Button} from './components/Button';