From 476d4acbda00b9c9ecda2385ee6e97593e1f35ef Mon Sep 17 00:00:00 2001 From: Joshua Pease Date: Tue, 24 Sep 2024 15:53:58 -0700 Subject: [PATCH] [#44] Adds Dialog Component --- config/tailwind/dialog.js | 45 +++++++++++ package-lock.json | 23 ++++++ package.json | 1 + src/js/app.js | 3 + tailwind.config.js | 3 +- templates/_components/dialog.twig | 78 +++++++++++++++++++ templates/parts-kit/dialog/default.twig | 24 ++++++ .../dialog/digalog-triggers-dialog.twig | 45 +++++++++++ 8 files changed, 221 insertions(+), 1 deletion(-) create mode 100644 config/tailwind/dialog.js create mode 100644 templates/_components/dialog.twig create mode 100644 templates/parts-kit/dialog/default.twig create mode 100644 templates/parts-kit/dialog/digalog-triggers-dialog.twig diff --git a/config/tailwind/dialog.js b/config/tailwind/dialog.js new file mode 100644 index 0000000..88c612e --- /dev/null +++ b/config/tailwind/dialog.js @@ -0,0 +1,45 @@ +import plugin from 'tailwindcss/plugin' + +export default plugin(({ addComponents }) => { + addComponents({ + '.dialog': { + '@apply invisible opacity-0 fixed inset-24 overflow-hidden z-50 open:visible m-auto bg-white p-24 text-black dark:border dark:border-gray-500 dark:bg-gray-900 dark:text-white rounded': + {}, + '&[open]': { + animation: + 'dialog-in var(--dialog-transition-duration, 300ms) cubic-bezier(0.2, 0, 0.13, 1) forwards', + }, + '&::backdrop': { + animation: + 'dialog-backdrop-in var(--dialog-transition-duration, 300ms) cubic-bezier(0.2, 0, 0.13, 1) forwards', + '@apply bg-black/80 backdrop-blur-sm': {}, + }, + '&[data-dialog-status="closing"]': { + animation: + 'dialog-out var(--dialog-transition-duration, 300ms) cubic-bezier(0.2, 0, 0.13, 1) forwards', + + '&::backdrop': { + animation: + 'dialog-backdrop-out var(--dialog-transition-duration, 300ms) cubic-bezier(0.2, 0, 0.13, 1) forwards', + }, + }, + // Animation Keyframes + '@keyframes dialog-in': { + '0%': { transform: 'translateY(2rem)', opacity: 0 }, + '100%': { transform: 'translateY(0px)', opacity: 1 }, + }, + '@keyframes dialog-out': { + '0%': { transform: 'scale(1)', opacity: 1 }, + '100%': { transform: 'scale(0.9)', opacity: 0 }, + }, + '@keyframes dialog-backdrop-in': { + '0%': { opacity: 0 }, + '100%': { opacity: 1 }, + }, + '@keyframes dialog-backdrop-out': { + '0%': { opacity: 1 }, + '100%': { opacity: 0 }, + }, + }, + }) +}) diff --git a/package-lock.json b/package-lock.json index 7e741b0..b00fa95 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "viget-craft-starter", "version": "1.0.0", "dependencies": { + "@alpinejs/focus": "^3.14.1", "alpinejs": "^3.14.1" }, "devDependencies": { @@ -38,6 +39,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@alpinejs/focus": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/@alpinejs/focus/-/focus-3.14.1.tgz", + "integrity": "sha512-z4xdpK6X1LB2VitsWbL61tmABoOORuEhE5v2tnUX/be6/nAygXyeDxZ1x9s1u+bOEYlIOXXLmjdmTlhchUVWxw==", + "dependencies": { + "focus-trap": "^6.9.4", + "tabbable": "^5.3.3" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", @@ -2095,6 +2105,14 @@ "dev": true, "peer": true }, + "node_modules/focus-trap": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-6.9.4.tgz", + "integrity": "sha512-v2NTsZe2FF59Y+sDykKY+XjqZ0cPfhq/hikWVL88BqLivnNiEffAsac6rP6H45ff9wG9LL5ToiDqrLEP9GX9mw==", + "dependencies": { + "tabbable": "^5.3.3" + } + }, "node_modules/foreground-child": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", @@ -4193,6 +4211,11 @@ "node": ">= 10" } }, + "node_modules/tabbable": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-5.3.3.tgz", + "integrity": "sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA==" + }, "node_modules/tailwindcss": { "version": "3.4.12", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.12.tgz", diff --git a/package.json b/package.json index 261c7bb..32fb032 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "vite-plugin-static-copy": "^1.0.6" }, "dependencies": { + "@alpinejs/focus": "^3.14.1", "alpinejs": "^3.14.1" } } diff --git a/src/js/app.js b/src/js/app.js index 688f959..4865b72 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -1,6 +1,9 @@ import '../css/app.css' import Alpine from 'alpinejs' +import focus from '@alpinejs/focus' + +Alpine.plugin(focus) // @ts-ignore window.Alpine = Alpine diff --git a/tailwind.config.js b/tailwind.config.js index b936bb2..f13283e 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,4 +1,5 @@ import buttons from './config/tailwind/buttons' +import dialog from './config/tailwind/dialog' /** Helper function to pair key and value together @@ -42,5 +43,5 @@ export default { }, extend: {}, }, - plugins: [buttons], + plugins: [buttons, dialog], } diff --git a/templates/_components/dialog.twig b/templates/_components/dialog.twig new file mode 100644 index 0000000..169c293 --- /dev/null +++ b/templates/_components/dialog.twig @@ -0,0 +1,78 @@ +{% from '_macros/icon.twig' import icon %} + +{# @var string id #} +{% set id = id ?? null %} + +{# @var boolean hideClose #} +{% set hideClose = hideClose ?? false %} + +{# @var array triggerProps #} +{% set triggerProps = triggerProps ?? {} %} + +{# @var string|null class #} +{% set class = class ?? null %} + +{# @var string|null content #} +{% set content = content ?? null %} + +
+ + {% if not hideClose %} + {{ include('_components/button.twig', { + icon: 'close', + iconOnly: true, + size: 'sm', + title: 'Close', + variant: 'subtle', + class: 'absolute right-4 top-4 size-24 !min-h-0 [&_svg]:size-12', + attrs: { + '@click': 'handleDialogClose()' + } + }) }} + {% endif %} + + {{ content }} + + +
diff --git a/templates/parts-kit/dialog/default.twig b/templates/parts-kit/dialog/default.twig new file mode 100644 index 0000000..0c8cb24 --- /dev/null +++ b/templates/parts-kit/dialog/default.twig @@ -0,0 +1,24 @@ +{% extends "viget-parts-kit/layout.twig" %} + +{% block main %} + +{% set content %} +

Hello World

+

Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos.

+ {% endset %} + + {# Dialogs are triggered by dispatching a custom event dialog:open with an id that matches the dialog's id #} + {{ include('_components/button.twig', { + text: 'Open Dialog', + attrs: { + 'x-data': '', + '@click': "$dispatch('dialog:open', { id: 'my-dialog'})" + }, + }) }} + + {{ include('_components/dialog.twig', { + content, + id: 'my-dialog', + hideClose: true, + }) }} +{% endblock %} diff --git a/templates/parts-kit/dialog/digalog-triggers-dialog.twig b/templates/parts-kit/dialog/digalog-triggers-dialog.twig new file mode 100644 index 0000000..1c4c9a3 --- /dev/null +++ b/templates/parts-kit/dialog/digalog-triggers-dialog.twig @@ -0,0 +1,45 @@ +{% extends "viget-parts-kit/layout.twig" %} + +{% block main %} + +{% set dialog1Content %} +

Dialog 1

+

Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos.

+ + {{ include('_components/button.twig', { + text: 'Open Dialog 2', + attrs: { + 'x-data': '', + '@click': "$dispatch('dialog:open', { id: 'my-dialog-2' })" + }, + }) }} + {% endset %} + + {% set dialog2Content %} +

Dialog 2

+

Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos.

+ + + {% endset %} + + {# Dialogs are triggered by dispatching a custom event dialog:open with an id that matches the dialog's id #} + {{ include('_components/button.twig', { + text: 'Open Dialog 1', + attrs: { + 'x-data': '', + '@click': "$dispatch('dialog:open', { id: 'my-dialog' })" + }, + }) }} + + {{ include('_components/dialog.twig', { + content: dialog1Content, + id: 'my-dialog', + }) }} + + {{ include('_components/dialog.twig', { + content: dialog2Content, + id: 'my-dialog-2', + }) }} + + +{% endblock %}