diff --git a/package.json b/package.json
index 4d319413..d3562b7f 100644
--- a/package.json
+++ b/package.json
@@ -56,6 +56,7 @@
"tailwindcss": "yarn:@tailwindcss/postcss7-compat@^2.1.2"
},
"dependencies": {
+ "@headlessui/react": "^1.4.0",
"clsx": "^1.1.1",
"goober": "^2.0.39",
"prop-types": "^15.7.2"
diff --git a/src/base-components/headlessui-dialog-base.js b/src/base-components/headlessui-dialog-base.js
new file mode 100644
index 00000000..86842001
--- /dev/null
+++ b/src/base-components/headlessui-dialog-base.js
@@ -0,0 +1,86 @@
+import React, { useRef } from 'react'
+import PropTypes from 'prop-types'
+import clsx from 'clsx'
+
+import { Dialog } from '@headlessui/react'
+
+import { useComponentIsActive } from '../hooks'
+
+
+const baseClasses = Object.freeze({
+ modal: 'fixed z-20 max-h-full max-w-full top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2',
+ overlay: 'absolute z-10 inset-0 w-full h-full bg-black bg-opacity-50 transition-opacity duration-200',
+})
+
+const ChildWithProps = ({ children, ...props }) => (React.Children.map(children, (child) => {
+ if (React.isValidElement(child)) {
+ return React.cloneElement(child, { ...props })
+ }
+ return child
+}))
+ChildWithProps.propTypes = { children: PropTypes.node.isRequired }
+
+const HeadlessUIDialog = ({ children, classes, modal, button, open, onClick, onClose }) => {
+ const ref = useRef(null)
+ const { ref: activeRef, componentIsActive, setComponentIsActive } = useComponentIsActive()
+ const controlledOpen = open || open === false || open === ''
+ let _open = componentIsActive
+
+ if (controlledOpen) {
+ _open = open
+ }
+
+ const handleButtonClick = () => {
+ if (!controlledOpen) {
+ setComponentIsActive((state) => !state)
+ }
+ onClick()
+ }
+
+ const handleClose = () => {
+ if (!controlledOpen) {
+ return
+ }
+ onClose()
+ }
+
+ const unControlledProps = controlledOpen ? {} : { onClick: handleButtonClick }
+
+ return (
+ <>
+
+ {button &&
+ {onClick && {button}}
+ {!onClick && button}
+ }
+
+
+
+ {_open && modal && }
+ >
+ )
+}
+
+HeadlessUIDialog.propTypes = {
+ children: PropTypes.node.isRequired,
+ classes: PropTypes.object,
+ modal: PropTypes.bool,
+ button: PropTypes.node,
+ open: PropTypes.bool,
+ onClick: PropTypes.func,
+ onClose: PropTypes.func,
+}
+HeadlessUIDialog.defaultProps = {
+ classes: { root: '', button: '', modal: '', dialog: '', overlay: '' },
+ modal: false,
+ button: null,
+ open: undefined,
+ onClick: () => {},
+ onClose: () => {},
+}
+
+export default HeadlessUIDialog
diff --git a/stories/dialog.stories.js b/stories/dialog.stories.js
index f82f0d7e..97f3860e 100644
--- a/stories/dialog.stories.js
+++ b/stories/dialog.stories.js
@@ -1,6 +1,7 @@
import React from 'react'
import { DialogBase } from '../src/base-components'
+import HeadlessUIDialog from '../src/base-components/headlessui-dialog-base'
export default {
@@ -25,39 +26,76 @@ export default {
export const Base = () => {
const button = ()
return (
-
-
- I am just a simple dialog.
- More improvements needed to make my usage more flexible.
-
-
+ <>
+
+
+ I am just a simple dialog.
+ More improvements needed to make my usage more flexible.
+
+
+
+
+
Headless Dialog example:
+
+
+ I am just a simple dialog.
+ More improvements needed to make my usage more flexible.
+
+
+
+ >
)
}
export const BaseModal = () => {
const button = ()
return (
-
-
- I am just a simple modal.
- More improvements needed to make my usage more flexible.
-
-
+ <>
+
+
+ I am just a simple modal.
+ More improvements needed to make my usage more flexible.
+
+
+
+
+
Headless Dialog example:
+
+
+ I am just a simple dialog.
+ More improvements needed to make my usage more flexible.
+
+
+
+ >
)
}
export const CustomDialog = () => {
- const button = ()
+ const button = ()
const customClasses = {
- button: 'w-32 p-4 rounded-md cursor-pointer bg-blue-50 hover:bg-blue-100',
dialog: 'w-96 p-4 shadow-md mt-1 bg-blue-200',
}
return (
-
-
- I am just a simple dialog.
- More improvements needed to make my usage more flexible.
-
-
+ <>
+
+
+ I am just a simple dialog.
+ More improvements needed to make my usage more flexible.
+
+
+
+
+
Headless Dialog example:
+
+
+ I am just a simple dialog.
+ More improvements needed to make my usage more flexible.
+
+
+
+ >
)
}
diff --git a/tailwind.config.js b/tailwind.config.js
index b61c36c3..021691db 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -1033,12 +1033,12 @@ module.exports = {
plugins: [
function({ addUtilities, theme }) {
- let newUtilities = {};
- const boxShadowPrefix = '0 0 0 1px';
- const colors = theme('colors');
+ let newUtilities = {}
+ const boxShadowPrefix = '0 0 0 1px'
+ const colors = theme('colors')
Object.keys(colors).forEach(color => {
- const colorData = colors[color];
+ const colorData = colors[color]
if (typeof colorData === 'string') {
newUtilities[`.shadow-${color}`] = {
boxShadow: `${boxShadowPrefix} ${colorData}`,
@@ -1049,12 +1049,12 @@ module.exports = {
newUtilities[`.shadow-${color}-${colorVariation}`] = {
boxShadow: `${boxShadowPrefix} ${colorData[colorVariation]}`,
}
- });
+ })
}
- });
+ })
addUtilities(newUtilities, {
- variants: ['focus', 'hover', 'active']
- });
- }
+ variants: ['focus', 'hover', 'active'],
+ })
+ },
],
}
diff --git a/yarn.lock b/yarn.lock
index d5ce61df..eb97effb 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1249,6 +1249,11 @@
dependencies:
purgecss "^3.1.3"
+"@headlessui/react@^1.4.0":
+ version "1.4.0"
+ resolved "https://registry.npmjs.org/@headlessui/react/-/react-1.4.0.tgz#c6d424d8ab10ac925e4423d7f3cbab02c30d736a"
+ integrity sha512-C+FmBVF6YGvqcEI5fa2dfVbEaXr2RGR6Kw1E5HXIISIZEfsrH/yuCgsjWw5nlRF9vbCxmQ/EKs64GAdKeb8gCw==
+
"@istanbuljs/load-nyc-config@^1.0.0":
version "1.1.0"
resolved "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced"