diff --git a/package-lock.json b/package-lock.json
index a64b142e..c2d0c774 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -77,8 +77,6 @@
"integrity": "sha512-cL9tllhqvsQ6r1+d9Invf7nNXg/3BlfL1vvvL/AdH9fZ2l5j0CeBcoq6UjsqHpvyN1v5nXSZgqJZoGeK+ZOAbw==",
"dev": true,
"dependencies": {
- "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents",
- "chokidar": "^3.4.0",
"commander": "^4.0.1",
"convert-source-map": "^1.1.0",
"fs-readdir-recursive": "^1.1.0",
@@ -7293,7 +7291,6 @@
"dependencies": {
"anymatch": "~3.1.1",
"braces": "~3.0.2",
- "fsevents": "~2.3.1",
"glob-parent": "~5.1.0",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
@@ -7513,7 +7510,6 @@
"integrity": "sha512-gnB85c3MGC7Nm9I/FkiasNBOKjOiO1RNuXXarQms37q4QMpWdlbBgD/VnOStA2faG1dpXMv31RFApjX1/QdgWQ==",
"dev": true,
"dependencies": {
- "colors": "^1.1.2",
"object-assign": "^4.1.0",
"string-width": "^4.2.0"
},
@@ -9740,8 +9736,7 @@
"esprima": "^4.0.1",
"estraverse": "^5.2.0",
"esutils": "^2.0.2",
- "optionator": "^0.8.1",
- "source-map": "~0.6.1"
+ "optionator": "^0.8.1"
},
"bin": {
"escodegen": "bin/escodegen.js",
@@ -10395,9 +10390,6 @@
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
"integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
"dev": true,
- "dependencies": {
- "graceful-fs": "^4.1.6"
- },
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
@@ -11302,7 +11294,6 @@
"minimist": "^1.2.5",
"neo-async": "^2.6.0",
"source-map": "^0.6.1",
- "uglify-js": "^3.1.4",
"wordwrap": "^1.0.0"
},
"bin": {
@@ -12870,7 +12861,6 @@
"@types/node": "*",
"anymatch": "^3.0.3",
"fb-watchman": "^2.0.0",
- "fsevents": "^2.1.2",
"graceful-fs": "^4.2.4",
"jest-regex-util": "^26.0.0",
"jest-serializer": "^26.6.2",
@@ -13104,7 +13094,6 @@
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"dev": true,
"dependencies": {
- "graceful-fs": "^4.1.6",
"universalify": "^2.0.0"
},
"optionalDependencies": {
@@ -13134,9 +13123,6 @@
"resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz",
"integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=",
"dev": true,
- "dependencies": {
- "graceful-fs": "^4.1.9"
- },
"optionalDependencies": {
"graceful-fs": "^4.1.9"
}
@@ -16976,9 +16962,6 @@
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.23.0.tgz",
"integrity": "sha512-c29LVsqOaLbBHuIbsTxaKENh1N2EQBOHaWv7gkHN4dgRbxSREqDnDbtFJYdpPauS4YCplMSNCABQ6Eeor69bAA==",
"dev": true,
- "dependencies": {
- "clipboard": "^2.0.0"
- },
"optionalDependencies": {
"clipboard": "^2.0.0"
}
@@ -19039,9 +19022,6 @@
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.45.2.tgz",
"integrity": "sha512-kRRU7wXzFHUzBIv0GfoFFIN3m9oteY4uAsKllIpQDId5cfnkWF2J130l+27dzDju0E6MScKiV0ZM5Bw8m4blYQ==",
"dev": true,
- "dependencies": {
- "fsevents": "~2.3.1"
- },
"bin": {
"rollup": "dist/bin/rollup"
},
@@ -19332,9 +19312,6 @@
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
"dev": true,
- "dependencies": {
- "graceful-fs": "^4.1.6"
- },
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
@@ -22145,10 +22122,8 @@
"integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==",
"dev": true,
"dependencies": {
- "chokidar": "^3.4.1",
"graceful-fs": "^4.1.2",
- "neo-async": "^2.5.0",
- "watchpack-chokidar2": "^2.0.1"
+ "neo-async": "^2.5.0"
},
"optionalDependencies": {
"chokidar": "^3.4.1",
@@ -22176,7 +22151,6 @@
"anymatch": "^2.0.0",
"async-each": "^1.0.1",
"braces": "^2.3.2",
- "fsevents": "^1.2.7",
"glob-parent": "^3.1.0",
"inherits": "^2.0.3",
"is-binary-path": "^1.0.0",
@@ -24256,8 +24230,7 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.1.0.tgz",
"integrity": "sha512-cauadRPiC3lDxudbgLkHThAhfqLIzp7159z2tNjODxrpOnckOk809rfAj63YdXWreRbLETNOupq1pC4i1NX9xA==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"@istanbuljs/load-nyc-config": {
"version": "1.1.0",
@@ -24520,8 +24493,7 @@
"version": "1.6.22",
"resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz",
"integrity": "sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"@mdx-js/util": {
"version": "1.6.22",
@@ -26487,8 +26459,7 @@
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.3.1.tgz",
"integrity": "sha512-HyZ+3Eay8SGaPq7kcFoANZLr4EjeXQ19yjjb9fp6B0PHHpvZoe00jdsnpnooMEbx9J5rQ93nxPUG3MQmXVxGMQ==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"@testing-library/dom": {
"version": "7.30.4",
@@ -27215,8 +27186,7 @@
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz",
"integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"acorn-node": {
"version": "1.8.2",
@@ -27292,15 +27262,13 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz",
"integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"ajv-keywords": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"alphanum-sort": {
"version": "1.0.2",
@@ -27980,8 +27948,7 @@
"version": "0.3.7",
"resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.7.tgz",
"integrity": "sha512-squySRkf+6JGnvjoUtDEjSREJEBirnXi9NqP6rjSYsylxQxqBTz+pkmf395i9E2zsvmYUaI40BHo6SqZUdydlw==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"babel-plugin-polyfill-corejs2": {
"version": "0.2.0",
@@ -32391,8 +32358,7 @@
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
"integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"ieee754": {
"version": "1.2.1",
@@ -33581,8 +33547,7 @@
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.1.2.tgz",
"integrity": "sha512-O8DMCl32V34RrD+ZHxcAPc2+kYytuDIoQYjY36RVdsLK7uHjgNVvFec4yv0X6LgB4YEZgSvK5QtFi5YVqEpoMA==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"marked": {
"version": "1.2.9",
@@ -35844,8 +35809,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz",
"integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"postcss-modules-local-by-default": {
"version": "4.0.0",
@@ -36696,8 +36660,7 @@
"version": "5.1.4",
"resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.1.4.tgz",
"integrity": "sha512-WOEpRNz8Oo2SEU4eYQ279jEKFSjpFPa9Vi2U/K0DGwP9wOQ8wYkJcNSd5Qbv1L8OFvyKDCbWekjftXaU5mbmtg==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"react-dev-utils": {
"version": "11.0.4",
@@ -36955,8 +36918,7 @@
"version": "1.22.0",
"resolved": "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-1.22.0.tgz",
"integrity": "sha512-MPLbF8vzRwAG3GcjdL+OHQlhgtWsLTXs+7uJiHfEeT3Ur7IsZaNYqRTLQ9sj2nB6M6jylcPCeCmH7qbszJmecg==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"react-docgen-typescript-plugin": {
"version": "0.6.3",
@@ -38047,8 +38009,7 @@
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/rollup-plugin-peer-deps-external/-/rollup-plugin-peer-deps-external-2.2.4.tgz",
"integrity": "sha512-AWdukIM1+k5JDdAqV/Cxd+nejvno2FVLVeZ74NKggm3Q5s9cbbcOgUPGdbxPi4BXu7xGaZ8HG12F+thImYu/0g==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"rollup-plugin-postcss": {
"version": "3.1.8",
@@ -40236,8 +40197,7 @@
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.2.5.tgz",
"integrity": "sha512-gN3vgMISAgacF7sqsLPByqoePooY3n2emTH59Ur5d/M8eg4WTWu1xp8i8DHjohftIyEx0S08RiYxbffr4j8Peg==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"use-composed-ref": {
"version": "1.1.0",
@@ -40252,8 +40212,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz",
"integrity": "sha512-L7Evj8FGcwo/wpbv/qvSfrkHFtOpCzvM5yl2KVyDJoylVuSvzphiiasmjgQPttIGBAy2WKiBNR98q8w7PiNgKQ==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"use-latest": {
"version": "1.2.0",
@@ -40749,8 +40708,7 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/webpack-filter-warnings-plugin/-/webpack-filter-warnings-plugin-1.2.1.tgz",
"integrity": "sha512-Ez6ytc9IseDMLPo0qCuNNYzgtUl8NovOqjIq4uAU8LTD4uoa1w1KpZyyzFtLTEMZpkkOkLfL9eN+KGYdk1Qtwg==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"webpack-hot-middleware": {
"version": "2.25.0",
diff --git a/rollup.config.js b/rollup.config.js
index 62b0d055..770d915c 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -28,6 +28,7 @@ export default {
card: 'src/components/Card/index.tsx',
badge: 'src/components/Badge/index.tsx',
alert: 'src/components/Alert/index.tsx',
+ accordian: 'src/components/Accordian/index.tsx',
tabs: 'src/components/Tabs/index.tsx',
menu: 'src/components/Menu/index.tsx',
modal: 'src/components/Modal/index.tsx',
diff --git a/src/components/Accordion/Accordion.module.css b/src/components/Accordion/Accordion.module.css
new file mode 100644
index 00000000..dce8da93
--- /dev/null
+++ b/src/components/Accordion/Accordion.module.css
@@ -0,0 +1,72 @@
+.sbui-accordion-container {
+ @apply flex flex-col rounded-md;
+}
+
+.sbui-accordion-container--bordered {
+ @apply border border-solid;
+ @apply bg-white border-gray-200;
+ @apply dark:bg-dark-700 dark:border-darkmode;
+}
+
+.sbui-accordion-item {
+ @apply w-full;
+}
+
+.sbui-accordion-item__button {
+ @apply flex justify-between w-full text-left cursor-pointer px-6 py-4 border-0 border-solid font-medium text-base rounded-t-md bg-transparent;
+
+ @apply border-gray-200 text-gray-500 hover:text-gray-600;
+ @apply dark:border-darkmode dark:text-dark-200 dark:hover:text-white;
+
+ font-family: inherit;
+ font-weight: inherit;
+}
+
+.sbui-accordion-item__button .sbui-typography-text {
+ @apply w-full max-w-none;
+}
+
+.sbui-accordion-item__button .sbui-typography-text:last-child {
+ @apply pl-2;
+}
+
+.sbui-accordion-item__button .sbui-icon {
+ @apply mt-px;
+}
+
+.sbui-accordion-item__button--open .sbui-icon {
+ @apply transform rotate-180;
+}
+
+.sbui-accordion-container--bordered
+ .sbui-accordion-item__button:not(:first-child) {
+ @apply rounded-none border-t border-gray-200 dark:border-darkmode;
+}
+
+.sbui-accordion-item__panel {
+ @apply px-6 py-4;
+}
+
+.sbui-accordion-item__panel--enter {
+ @apply transition-max-height ease-in-out duration-700 overflow-hidden;
+}
+
+.sbui-accordion-item__panel--enterFrom {
+ @apply max-h-0;
+}
+
+.sbui-accordion-item__panel--enterTo {
+ @apply max-h-screen;
+}
+
+.sbui-accordion-item__panel--leave {
+ @apply transition-max-height ease-in-out duration-300 overflow-hidden;
+}
+
+.sbui-accordion-item__panel--leaveFrom {
+ @apply max-h-screen;
+}
+
+.sbui-accordion-item__panel--leaveTo {
+ @apply max-h-0;
+}
diff --git a/src/components/Accordion/Accordion.stories.tsx b/src/components/Accordion/Accordion.stories.tsx
new file mode 100644
index 00000000..70e7aa35
--- /dev/null
+++ b/src/components/Accordion/Accordion.stories.tsx
@@ -0,0 +1,63 @@
+import React from 'react'
+
+import { Accordion } from '.'
+import { Typography } from '../Typography'
+import { IconArrowUp } from '../Icon/icons/IconArrowUp'
+
+export default {
+ title: 'Displays/Accordion',
+ component: Accordion,
+}
+
+export const Default = (args: any) => (
+
+
+
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur
+ amet labore.
+
+
+
+)
+
+Default.args = {}
+
+const Multiple = (args: any) => (
+
+
+
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur
+ amet labore.
+
+
+
+
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur
+ amet labore.
+
+
+
+)
+
+export const withMultiple = Multiple.bind({})
+withMultiple.args = {}
+
+export const withBorder = Multiple.bind({})
+withBorder.args = {
+ bordered: true,
+}
+
+export const withDefaultActive = Multiple.bind({})
+withDefaultActive.args = {
+ defaultActiveId: [1],
+}
+
+export const withIconLeft = Multiple.bind({})
+withIconLeft.args = {
+ iconPosition: 'left',
+}
+
+export const withCustomIcon = Multiple.bind({})
+withCustomIcon.args = {
+ icon: ,
+}
diff --git a/src/components/Accordion/Accordion.tsx b/src/components/Accordion/Accordion.tsx
new file mode 100644
index 00000000..f79d7af0
--- /dev/null
+++ b/src/components/Accordion/Accordion.tsx
@@ -0,0 +1,131 @@
+import React, { createContext, useCallback, useContext, useEffect } from 'react'
+import { Disclosure, Transition } from '@headlessui/react'
+// @ts-ignore
+import AccordionStyles from './Accordion.module.css'
+import { IconChevronUp } from '../Icon/icons/IconChevronUp'
+import Typography from '../Typography'
+
+type ContextValue = Required<
+ Pick
+>
+
+const AccordionContext = createContext({
+ defaultActiveId: [],
+ icon: ,
+ iconPosition: 'right',
+ onChange: undefined,
+})
+
+interface AccordionProps {
+ children?: React.ReactNode
+ className?: string
+ defaultActiveId?: (string | number)[]
+ icon?: React.ReactNode
+ iconPosition?: 'left' | 'right'
+ bordered?: boolean
+ onChange?: (item: {
+ label: string
+ id?: string | number
+ open: boolean
+ }) => void
+}
+
+function Accordion({
+ children,
+ className,
+ defaultActiveId = [],
+ icon = ,
+ iconPosition = 'right',
+ bordered,
+ onChange,
+}: AccordionProps) {
+ let containerClasses = [AccordionStyles['sbui-accordion-container']]
+ if (bordered) {
+ containerClasses.push(AccordionStyles['sbui-accordion-container--bordered'])
+ }
+ if (className) {
+ containerClasses.push(className)
+ }
+
+ const contextValue = {
+ defaultActiveId,
+ icon,
+ iconPosition,
+ onChange,
+ }
+
+ return (
+
+ {children}
+
+ )
+}
+
+interface ItemProps {
+ children?: React.ReactNode
+ className?: string
+ label: string
+ id?: string | number
+}
+
+export function Item({ children, className, label, id }: ItemProps) {
+ const { defaultActiveId, icon, iconPosition, onChange } = useContext(
+ AccordionContext
+ )
+
+ let panelClasses = [AccordionStyles['sbui-accordion-item__panel']]
+
+ let buttonClasses = [AccordionStyles['sbui-accordion-item__button']]
+ if (className) {
+ buttonClasses.push(className)
+ }
+
+ const isDefaultActive = defaultActiveId.includes(id)
+
+ const handleOnChange = useCallback(
+ (open: boolean) => () => {
+ if (onChange) {
+ onChange({ id, label, open })
+ }
+ },
+ [onChange, id, label]
+ )
+
+ return (
+
+ {({ open }) => (
+ <>
+
+ {iconPosition === 'left' && icon}
+ {label}
+ {iconPosition === 'right' && icon}
+
+
+
+ {children}
+
+
+ >
+ )}
+
+ )
+}
+
+Accordion.Item = Item
+export default Accordion
diff --git a/src/components/Accordion/index.tsx b/src/components/Accordion/index.tsx
new file mode 100644
index 00000000..971fd8af
--- /dev/null
+++ b/src/components/Accordion/index.tsx
@@ -0,0 +1 @@
+export { default as Accordion } from './Accordion'
diff --git a/src/components/Icon/Icon.tsx b/src/components/Icon/Icon.tsx
index 6d43b308..89600729 100644
--- a/src/components/Icon/Icon.tsx
+++ b/src/components/Icon/Icon.tsx
@@ -50,7 +50,7 @@ function Icon({
}: Props) {
return (
- {({ contextSize }) => {
+ {({ contextSize, className: contextClassName }) => {
const defaultSizes: StringMap = {
tiny: 14,
small: 18,
@@ -88,6 +88,11 @@ function Icon({
// default these icons to use 'currentColor' ie, the text color
const noColor = !color && !fill && !stroke
+ let classes = ['sbui-icon', className]
+ if (contextClassName) {
+ classes.push(contextClassName)
+ }
+
const Icon = (
// custom SVG file