diff --git a/components/Molecules/Button/Button.stories.js b/components/Molecules/Button/Button.stories.js index b2b47e7..b9c728d 100644 --- a/components/Molecules/Button/Button.stories.js +++ b/components/Molecules/Button/Button.stories.js @@ -13,7 +13,8 @@ export const classic = { customText: 'Button', variant: 'primary', icon_left: 'none', - icon_right: 'none' + icon_right: 'none', + data: {} }, argTypes: { variant: { @@ -30,6 +31,9 @@ export const classic = { }, href: { control: { type: 'text' } + }, + data: { + control: { type: 'object' } } } }; diff --git a/components/Molecules/Button/Button.twig b/components/Molecules/Button/Button.twig index 01f168d..b92be85 100644 --- a/components/Molecules/Button/Button.twig +++ b/components/Molecules/Button/Button.twig @@ -1,16 +1,21 @@ {% set classes = classes|default('') %} -{% if variant %}{% set classes = classes ~ ' Button--' ~ variant %}{% endif %} -{% set tag = 'button' %} -{% if href %}{% set tag = 'a' %}{% endif %} +{% if variant %} + {% set classes = classes ~ ' Button--' ~ variant %} +{% endif %} +{% set tag = href ? 'a' : 'button' %} +{% set typeAttr = href ? '' : 'type=' ~ (type|default('button')) %} -<{{ tag }} class='Button {{ classes }}' {% if disabled %}disabled{% endif %} {% if href %}href='{{ href }}'{% else %}type='{{ type|default('button') }}'{% endif %}> - {% if icon_left %} - {{ source("/icons/"~ icon_left ~".svg") }} - {% endif %} - {% if text %} - {{ text }} - {% endif %} - {% if icon_right %} - {{ source("/icons/"~ icon_right ~".svg") }} - {% endif %} - +<{{tag}} class="Button {{ classes }}" {% if disabled %} disabled {% endif %} {% if href %} href="{{ href }}" {% endif %} {{ typeAttr }} {% if data is defined and data.key is defined and data.value is defined %} data-{{ data.key }}="{{ data.value }}" {% endif %}> + {% if icon %} + {{ source('/icons/' ~ icon ~ '.svg') }} + {% endif %} + {% if icon_left %} + {{ source('/icons/' ~ icon_left ~ '.svg') }} + {% endif %} + {% if text %} + {{ text }} + {% endif %} + {% if icon_right %} + {{ source('/icons/' ~ icon_right ~ '.svg') }} + {% endif %} + diff --git a/components/Organisms/Popin/Popin.stories.js b/components/Organisms/Popin/Popin.stories.js new file mode 100644 index 0000000..3a29f5a --- /dev/null +++ b/components/Organisms/Popin/Popin.stories.js @@ -0,0 +1,48 @@ +import Popin from './Popin.twig'; +import PopinWithTrigger from './PopinWithTrigger.twig'; +import { popin } from './popin'; + +export default { + title: 'Design System/Organisms/Popin' +}; + +export const base = { + render: (args) => Popin(args), + play: () => popin(), + args: { + title: 'Ici un titre', + text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.', + img: '/illustrations/sécurité.png', + checkbox: { + label: "Ici une optin que l'utilisateur peut checker", + name: 'popin-checkbox' + }, + link: { + label: 'Ici un lien', + href: '#' + }, + action: 'Bouton', + secondaryAction: 'Bouton', + open: true, + id: 'popin-base' + }, + argTypes: { + checkbox: { + control: { type: 'object' } + }, + action: { + control: { type: 'text' } + }, + secondaryAction: { + control: { type: 'text' } + }, + link: { + control: { type: 'object' } + } + } +}; + +export const withTrigger = { + render: (args) => PopinWithTrigger(args), + play: () => popin() +}; diff --git a/components/Organisms/Popin/Popin.twig b/components/Organisms/Popin/Popin.twig new file mode 100644 index 0000000..13fccd7 --- /dev/null +++ b/components/Organisms/Popin/Popin.twig @@ -0,0 +1,49 @@ +
+ + +
+ + {% if img %} +
+ {{ alt }} +
+ {% endif %} + +
+ {% if title %} +

+ {{ title }} +

+ {% endif %} + + {% if text %} +
+ {{ text }} +
+ {% endif %} + + {% if checkbox.label %} +
+ {% include '../../Molecules/Form/Checkbox.twig' with { label: checkbox.label, name: checkbox.name } %} +
+ {% endif %} +
+ + {% if action or secondaryAction or link %} +
+ {% if secondaryAction %} + {% include '../../Molecules/Button/Button.twig' with { text: secondaryAction, variant: 'secondary', classes: "Button--large" } %} + {% endif %} + {% if link %} + {% include '../../Molecules/Links/Link.twig' with { label: link.label, classes: '', href: link.href, target: '', iconLeft: link.iconLeft, iconRight: link.iconRight, iconSize: 'h-5 w-5' } %} + {% endif %} + {% if action %} + {% include '../../Molecules/Button/Button.twig' with { text: action, variant: 'primary', classes: "Button--large" } %} + {% endif %} +
+ {% endif %} + +
+
diff --git a/components/Organisms/Popin/PopinWithTrigger.twig b/components/Organisms/Popin/PopinWithTrigger.twig new file mode 100644 index 0000000..96de5e8 --- /dev/null +++ b/components/Organisms/Popin/PopinWithTrigger.twig @@ -0,0 +1,10 @@ +{% include '../../Molecules/Button/Button.twig' with { text: "open popin", variant: 'primary', classes: "Button--large popin-trigger", data: { 'key': "popin-id", 'value': "popin-with-trigger" } } %} + +{% include '../../Organisms/Popin/Popin.twig' with { + title: "Popin title", + text: "Popin text", + action: "Primary action", + secondaryAction: "Secondary action", + img: '/illustrations/sécurité.png', + id: "popin-with-trigger", +} %} diff --git a/components/Organisms/Popin/popin.css b/components/Organisms/Popin/popin.css new file mode 100644 index 0000000..6ba9dac --- /dev/null +++ b/components/Organisms/Popin/popin.css @@ -0,0 +1,103 @@ +.Popin { + position: fixed; + height: max-content; + display: none; + justify-content: center; + align-items: center; + flex-direction: column; + background-color: var(--white); + width: 500px; + border-radius: 16px; + box-shadow: 0px 4px 16px 0px rgba(0, 0, 0, 0.2); + padding: 32px; + z-index: 1000; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + transition: + transform 0.3s ease-in-out, + opacity 0.3s ease-in-out; + + &--open { + display: flex; + + + .Popin-overlay { + display: block; + } + } + + &-overlay { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + } + + &-dragbar { + display: none; + width: 83px; + height: 3px; + background-color: var(--black); + border-radius: 3px; + margin-bottom: 43px; + cursor: move; + } + + &-actions { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + } + + &-img { + width: 228px; + height: auto; + margin-bottom: 48px; + } + + &-title { + margin-bottom: 8px; + } + + &-text { + margin-bottom: 24px; + } + + &-checkbox { + margin-bottom: 24px; + } + + &-close { + align-self: flex-end; + width: 24px; + height: 24px; + } + + @media (max-width: 768px) { + width: 100%; + border-radius: 16px 16px 0 0; + top: auto; + bottom: 0; + left: 0; + transform: none; + + &-dragbar { + display: block; + } + + &-close { + display: none; + } + } +} + +@media (max-width: 768px) { + .dragging { + user-select: none; + opacity: 0.8; + } +} diff --git a/components/Organisms/Popin/popin.js b/components/Organisms/Popin/popin.js new file mode 100644 index 0000000..5f15b1f --- /dev/null +++ b/components/Organisms/Popin/popin.js @@ -0,0 +1,76 @@ +export const popin = () => { + const popins = document.querySelectorAll('.Popin'); + const popinOverlay = document.querySelector('.Popin-overlay'); + + let startY = 0; + let currentY = 0; + let dragging = false; + + popinOverlay.addEventListener('click', () => { + popins.forEach((popin) => { + popin.classList.remove('Popin--open'); + }); + }); + + document.querySelectorAll('.popin-trigger').forEach((trigger) => { + trigger.addEventListener('click', () => { + const popin = document.querySelector(`#${trigger.dataset.popinId}`); + + popin.classList.add('Popin--open'); + }); + }); + + popins.forEach((popin) => { + popin.querySelector('.Popin-close').addEventListener('click', () => { + popin.classList.remove('Popin--open'); + }); + + popin.addEventListener('touchstart', function (event) { + startY = event.touches[0].clientY; + dragging = true; + popin.classList.add('dragging'); + }); + + popin.addEventListener('touchmove', function (event) { + if (dragging && window.innerWidth <= 768) { + currentY = event.touches[0].clientY; + if (currentY - startY > 100) { + // Threshold for closing + popin.classList.remove('Popin--open'); + } + } + }); + + popin.addEventListener('touchend', function () { + dragging = false; + popin.classList.remove('dragging'); + }); + + // Mouse events for desktop devices + popin.addEventListener('mousedown', function (event) { + startY = event.clientY; + dragging = true; + popin.classList.add('dragging'); + }); + + popin.addEventListener('mousemove', function (event) { + if (dragging && window.innerWidth <= 768) { + currentY = event.clientY; + if (currentY - startY > 100) { + // Threshold for closing + popin.classList.remove('Popin--open'); + } + } + }); + + popin.addEventListener('mouseup', function () { + dragging = false; + popin.classList.remove('dragging'); + }); + + popin.addEventListener('mouseleave', function () { + dragging = false; + popin.classList.remove('dragging'); + }); + }); +};