@myelmut/design-system 0.1.47 → 0.1.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -2
- package/src/assets/fonts/PPMori-Regular.woff2 +0 -0
- package/src/assets/fonts/PPMori-RegularItalic.woff2 +0 -0
- package/src/assets/fonts/PPMori-SemiBold.woff2 +0 -0
- package/src/assets/fonts/PPPangaia-Medium.woff2 +0 -0
- package/src/assets/fonts/PPPangaia-MediumItalic.woff2 +0 -0
- package/src/assets/fonts/PPPangaia-Ultralight.woff2 +0 -0
- package/src/assets/illustrations/balls-light.webp +0 -0
- package/src/assets/illustrations/balls.webp +0 -0
- package/src/assets/illustrations/basket-light.webp +0 -0
- package/src/assets/illustrations/basket.webp +0 -0
- package/src/assets/illustrations/bowl-2-light.webp +0 -0
- package/src/assets/illustrations/bowl-2.webp +0 -0
- package/src/assets/illustrations/bowl-light.webp +0 -0
- package/src/assets/illustrations/bowl.webp +0 -0
- package/src/assets/illustrations/box-2-light.webp +0 -0
- package/src/assets/illustrations/box-2.webp +0 -0
- package/src/assets/illustrations/box-light.webp +0 -0
- package/src/assets/illustrations/box.webp +0 -0
- package/src/assets/illustrations/calendar-light.webp +0 -0
- package/src/assets/illustrations/calendar.webp +0 -0
- package/src/assets/illustrations/can-light.webp +0 -0
- package/src/assets/illustrations/can.webp +0 -0
- package/src/assets/illustrations/carrot-light.webp +0 -0
- package/src/assets/illustrations/carrot.webp +0 -0
- package/src/assets/illustrations/cat-light.webp +0 -0
- package/src/assets/illustrations/cat.webp +0 -0
- package/src/assets/illustrations/check-rounded.webp +0 -0
- package/src/assets/illustrations/chicken-light.webp +0 -0
- package/src/assets/illustrations/chicken.webp +0 -0
- package/src/assets/illustrations/cross-rounded.webp +0 -0
- package/src/assets/illustrations/crown-light.webp +0 -0
- package/src/assets/illustrations/crown.webp +0 -0
- package/src/assets/illustrations/dog-light.webp +0 -0
- package/src/assets/illustrations/dog.webp +0 -0
- package/src/assets/illustrations/face-light.webp +0 -0
- package/src/assets/illustrations/face.webp +0 -0
- package/src/assets/illustrations/food-bag-light.webp +0 -0
- package/src/assets/illustrations/food-bag.webp +0 -0
- package/src/assets/illustrations/france-light.webp +0 -0
- package/src/assets/illustrations/france.webp +0 -0
- package/src/assets/illustrations/fridge-light.webp +0 -0
- package/src/assets/illustrations/fridge.webp +0 -0
- package/src/assets/illustrations/glasses-light.webp +0 -0
- package/src/assets/illustrations/glasses.webp +0 -0
- package/src/assets/illustrations/half-label-light.webp +0 -0
- package/src/assets/illustrations/half-label.webp +0 -0
- package/src/assets/illustrations/kitten-light.webp +0 -0
- package/src/assets/illustrations/kitten.webp +0 -0
- package/src/assets/illustrations/label-light.webp +0 -0
- package/src/assets/illustrations/label.webp +0 -0
- package/src/assets/illustrations/leaf-light.webp +0 -0
- package/src/assets/illustrations/leaf.webp +0 -0
- package/src/assets/illustrations/liquid-light.webp +0 -0
- package/src/assets/illustrations/liquid.webp +0 -0
- package/src/assets/illustrations/magnifying-glass-light.webp +0 -0
- package/src/assets/illustrations/magnifying-glass.webp +0 -0
- package/src/assets/illustrations/meat-light.webp +0 -0
- package/src/assets/illustrations/meat.webp +0 -0
- package/src/assets/illustrations/molecule-light.webp +0 -0
- package/src/assets/illustrations/molecule.webp +0 -0
- package/src/assets/illustrations/paws-light.webp +0 -0
- package/src/assets/illustrations/paws.webp +0 -0
- package/src/assets/illustrations/plate-light.webp +0 -0
- package/src/assets/illustrations/plate.webp +0 -0
- package/src/assets/illustrations/pot-big-2-light.webp +0 -0
- package/src/assets/illustrations/pot-big-2.webp +0 -0
- package/src/assets/illustrations/pot-big-light.webp +0 -0
- package/src/assets/illustrations/pot-big.webp +0 -0
- package/src/assets/illustrations/pot-light.webp +0 -0
- package/src/assets/illustrations/pot.webp +0 -0
- package/src/assets/illustrations/puppy-light.webp +0 -0
- package/src/assets/illustrations/puppy.webp +0 -0
- package/src/assets/illustrations/quantity-light.webp +0 -0
- package/src/assets/illustrations/quantity.webp +0 -0
- package/src/assets/illustrations/sausage-light.webp +0 -0
- package/src/assets/illustrations/sausage.webp +0 -0
- package/src/assets/illustrations/sausages-light.webp +0 -0
- package/src/assets/illustrations/sausages.webp +0 -0
- package/src/assets/illustrations/skeleton-light.webp +0 -0
- package/src/assets/illustrations/skeleton.webp +0 -0
- package/src/assets/illustrations/sofa-light.webp +0 -0
- package/src/assets/illustrations/sofa.webp +0 -0
- package/src/assets/illustrations/sport-light.webp +0 -0
- package/src/assets/illustrations/sport.webp +0 -0
- package/src/assets/illustrations/steak-light.webp +0 -0
- package/src/assets/illustrations/steak.webp +0 -0
- package/src/assets/illustrations/truck-light.webp +0 -0
- package/src/assets/illustrations/truck.webp +0 -0
- package/src/assets/illustrations/warning-light.webp +0 -0
- package/src/assets/illustrations/warning.webp +0 -0
- package/src/assets/images/cat.webp +0 -0
- package/src/assets/images/dog.webp +0 -0
- package/src/assets/images/frequency/food-in-fridge.webp +0 -0
- package/src/assets/images/ingredients/beef.webp +0 -0
- package/src/assets/images/ingredients/beer-yeast.webp +0 -0
- package/src/assets/images/ingredients/calcium.webp +0 -0
- package/src/assets/images/ingredients/carrot.webp +0 -0
- package/src/assets/images/ingredients/chicken.webp +0 -0
- package/src/assets/images/ingredients/courgette.webp +0 -0
- package/src/assets/images/ingredients/dry-apple.webp +0 -0
- package/src/assets/images/ingredients/dry-carrot.webp +0 -0
- package/src/assets/images/ingredients/duck.webp +0 -0
- package/src/assets/images/ingredients/fish.webp +0 -0
- package/src/assets/images/ingredients/liquid.webp +0 -0
- package/src/assets/images/ingredients/oil.webp +0 -0
- package/src/assets/images/ingredients/pork.webp +0 -0
- package/src/assets/images/ingredients/potato.webp +0 -0
- package/src/assets/images/ingredients/quinoa.webp +0 -0
- package/src/assets/images/ingredients/rice.webp +0 -0
- package/src/assets/images/ingredients/seaweed.webp +0 -0
- package/src/assets/images/ingredients/turkey.webp +0 -0
- package/src/assets/images/ingredients/vitamins.webp +0 -0
- package/src/assets/images/tips/claudine-head.webp +0 -0
- package/src/assets/images/tips/claudine-tips-head-mobile.webp +0 -0
- package/src/assets/images/tips/claudine-tips-head-mobile@2x.webp +0 -0
- package/src/assets/images/tips/claudine-tips-head.webp +0 -0
- package/src/assets/images/tips/claudine-tips-head@2x.webp +0 -0
- package/src/assets/images/tips/claudine-tips-mobile.webp +0 -0
- package/src/assets/images/tips/claudine-tips-mobile@2x.webp +0 -0
- package/src/assets/images/tips/claudine-tips.webp +0 -0
- package/src/assets/images/tips/claudine-tips@2x.webp +0 -0
- package/src/assets/images/tips/payment-mobile.webp +0 -0
- package/src/assets/images/tips/payment-mobile@2x.webp +0 -0
- package/src/assets/images/tips/payment.webp +0 -0
- package/src/assets/images/tips/payment@2x.webp +0 -0
- package/src/assets/images/trash/dog-product-mobile.webp +0 -0
- package/src/assets/images/trash/dog-product.webp +0 -0
- package/src/assets/images/trash/full-cat.png +0 -0
- package/src/assets/images/trash/testimonial-1-mobile.webp +0 -0
- package/src/assets/images/trash/testimonial-1-mobile@2x.webp +0 -0
- package/src/assets/images/trash/testimonial-1.webp +0 -0
- package/src/assets/images/trash/testimonial-1@2x.webp +0 -0
- package/src/components/Accordions/FAQ/FaqItem.stories.tsx +61 -0
- package/src/components/Accordions/FAQ/FaqItem.tsx +55 -0
- package/src/components/Accordions/Ingredient/Ingredient.stories.tsx +38 -0
- package/src/components/Accordions/Ingredient/Ingredient.tsx +93 -0
- package/src/components/Accordions/index.tsx +4 -0
- package/src/components/Base/Banner/Banner.stories.tsx +33 -0
- package/src/components/Base/Banner/Banner.tsx +23 -0
- package/src/components/Base/Emblem/Emblem.stories.tsx +40 -0
- package/src/components/Base/Emblem/Emblem.tsx +22 -0
- package/src/components/Base/Logo/Logo.stories.tsx +46 -0
- package/src/components/Base/Logo/Logo.tsx +34 -0
- package/src/components/Base/ResponsiveImage/ResponsiveImage.stories.tsx +78 -0
- package/src/components/Base/ResponsiveImage/ResponsiveImage.tsx +56 -0
- package/src/components/Base/Text/Text.stories.tsx +115 -0
- package/src/components/Base/Text/Text.tsx +60 -0
- package/src/components/Base/Title/Title.stories.tsx +145 -0
- package/src/components/Base/Title/Title.tsx +77 -0
- package/src/components/Base/VideoPlayer/VideoPlayer.stories.tsx +60 -0
- package/src/components/Base/VideoPlayer/VideoPlayer.tsx +78 -0
- package/src/components/Base/index.tsx +9 -0
- package/src/components/Buttons/Button/Button.stories.tsx +158 -0
- package/src/components/Buttons/Button/Button.tsx +68 -0
- package/src/components/Buttons/CardButton/CardButton.stories.tsx +47 -0
- package/src/components/Buttons/CardButton/CardButton.tsx +25 -0
- package/src/components/Buttons/ClearButton/ClearButton.stories.tsx +26 -0
- package/src/components/Buttons/ClearButton/ClearButton.tsx +18 -0
- package/src/components/Buttons/FAQButton/FAQButton.stories.tsx +33 -0
- package/src/components/Buttons/FAQButton/FAQButton.tsx +27 -0
- package/src/components/Buttons/IllustratedCardButton/IllustratedCardButton.stories.tsx +71 -0
- package/src/components/Buttons/IllustratedCardButton/IllustratedCardButton.tsx +45 -0
- package/src/components/Buttons/SimpleIllustratedCardButton/SimpleIllustratedCardButton.stories.tsx +74 -0
- package/src/components/Buttons/SimpleIllustratedCardButton/SimpleIllustratedCardButton.tsx +43 -0
- package/src/components/Buttons/SocialButton/SocialButton.stories.tsx +56 -0
- package/src/components/Buttons/SocialButton/SocialButton.tsx +28 -0
- package/src/components/Buttons/Toggle/Toggle.tsx +64 -0
- package/src/components/Buttons/Toggle/Toogle.stories.tsx +66 -0
- package/src/components/Buttons/index.ts +10 -0
- package/src/components/Cards/CTACard/CTACard.stories.tsx +83 -0
- package/src/components/Cards/CTACard/CTACard.tsx +47 -0
- package/src/components/Cards/FeatureCard/FeatureCard.stories.tsx +96 -0
- package/src/components/Cards/FeatureCard/FeatureCard.tsx +50 -0
- package/src/components/Cards/FeatureIllustration/FeatureIllustration.stories.tsx +96 -0
- package/src/components/Cards/FeatureIllustration/FeatureIllustration.tsx +56 -0
- package/src/components/Cards/FeatureIllustration/index.ts +2 -0
- package/src/components/Cards/FoodCard/FoodCard.stories.tsx +43 -0
- package/src/components/Cards/FoodCard/FoodCard.tsx +37 -0
- package/src/components/Cards/FrequencySelectorCard/FrequencySelectorCard.stories.tsx +140 -0
- package/src/components/Cards/FrequencySelectorCard/FrequencySelectorCard.tsx +90 -0
- package/src/components/Cards/FrequencySelectorCard/index.ts +2 -0
- package/src/components/Cards/IllustratedCard/IllustratedCard.stories.tsx +54 -0
- package/src/components/Cards/IllustratedCard/IllustratedCard.tsx +44 -0
- package/src/components/Cards/PaymentCard/PaymentCard.stories.tsx +35 -0
- package/src/components/Cards/PaymentCard/PaymentCard.tsx +31 -0
- package/src/components/Cards/PlanCard/PlanCard.stories.tsx +140 -0
- package/src/components/Cards/PlanCard/PlanCard.tsx +119 -0
- package/src/components/Cards/Polaroid/Polaroid.stories.tsx +118 -0
- package/src/components/Cards/Polaroid/Polaroid.tsx +66 -0
- package/src/components/Cards/RecetteCard/RecetteCard.stories.tsx +86 -0
- package/src/components/Cards/RecetteCard/RecetteCard.tsx +47 -0
- package/src/components/Cards/StatCard/StatCard.stories.tsx +69 -0
- package/src/components/Cards/StatCard/StatCard.tsx +45 -0
- package/src/components/Cards/Testimonial/Testimonial.stories.tsx +65 -0
- package/src/components/Cards/Testimonial/Testimonial.tsx +62 -0
- package/src/components/Cards/TestimonialSlider/TestimonialSlider.stories.ts +53 -0
- package/src/components/Cards/TestimonialSlider/TestimonialSlider.tsx +50 -0
- package/src/components/Cards/Tips/Tips.stories.tsx +32 -0
- package/src/components/Cards/Tips/Tips.tsx +40 -0
- package/src/components/Cards/TransitionCard/TransitionCard.stories.tsx +50 -0
- package/src/components/Cards/TransitionCard/TransitionCard.tsx +66 -0
- package/src/components/Cards/UpCard/UpCard.stories.tsx +94 -0
- package/src/components/Cards/UpCard/UpCard.tsx +50 -0
- package/src/components/Cards/WizardTips/WizardTips.stories.tsx +48 -0
- package/src/components/Cards/WizardTips/WizardTips.tsx +33 -0
- package/src/components/Cards/index.ts +19 -0
- package/src/components/Inputs/ButtonSelect/ButtonSelect.stories.tsx +51 -0
- package/src/components/Inputs/ButtonSelect/ButtonSelect.tsx +34 -0
- package/src/components/Inputs/Checkbox/Checkbox.stories.tsx +47 -0
- package/src/components/Inputs/Checkbox/Checkbox.tsx +35 -0
- package/src/components/Inputs/Dropdown/Dropdown.stories.tsx +61 -0
- package/src/components/Inputs/Dropdown/Dropdown.tsx +108 -0
- package/src/components/Inputs/DropdownMenu/DropdownMenu.stories.tsx +75 -0
- package/src/components/Inputs/DropdownMenu/DropdownMenu.tsx +109 -0
- package/src/components/Inputs/ErrorMessage/ErrorMessage.stories.tsx +33 -0
- package/src/components/Inputs/ErrorMessage/ErrorMessage.tsx +18 -0
- package/src/components/Inputs/Filters/Filters.stories.tsx +54 -0
- package/src/components/Inputs/Filters/Filters.tsx +75 -0
- package/src/components/Inputs/Label/Label.stories.tsx +34 -0
- package/src/components/Inputs/Label/Label.tsx +16 -0
- package/src/components/Inputs/Newsletter/Newsletter.stories.tsx +67 -0
- package/src/components/Inputs/Newsletter/Newsletter.tsx +70 -0
- package/src/components/Inputs/QuantityInput/QuantityInput.stories.tsx +54 -0
- package/src/components/Inputs/QuantityInput/QuantityInput.tsx +46 -0
- package/src/components/Inputs/Tag/Tag.stories.tsx +33 -0
- package/src/components/Inputs/Tag/Tag.tsx +19 -0
- package/src/components/Inputs/TagSelect/TagSelect.stories.tsx +50 -0
- package/src/components/Inputs/TagSelect/TagSelect.tsx +48 -0
- package/src/components/Inputs/TextInput/TextInput.stories.tsx +40 -0
- package/src/components/Inputs/TextInput/TextInput.tsx +38 -0
- package/src/components/Inputs/WizardDropdown/WizardDropdown.stories.tsx +59 -0
- package/src/components/Inputs/WizardDropdown/WizardDropdown.tsx +93 -0
- package/src/components/Inputs/WizardTextInput/WizardTextInput.stories.tsx +40 -0
- package/src/components/Inputs/WizardTextInput/WizardTextInput.tsx +31 -0
- package/src/components/Inputs/index.ts +16 -0
- package/src/components/Navigation/Footer/Footer.stories.tsx +28 -0
- package/src/components/Navigation/Footer/Footer.tsx +130 -0
- package/src/components/Navigation/FooterTips/FooterTips.stories.tsx +22 -0
- package/src/components/Navigation/FooterTips/FooterTips.tsx +24 -0
- package/src/components/Navigation/MobileMenu/MobileMenu.stories.tsx +56 -0
- package/src/components/Navigation/MobileMenu/MobileMenu.tsx +45 -0
- package/src/components/Navigation/Navbar/Navbar.stories.tsx +128 -0
- package/src/components/Navigation/Navbar/Navbar.tsx +66 -0
- package/src/components/Navigation/NavbarDesktop/NavbarDesktop.stories.tsx +57 -0
- package/src/components/Navigation/NavbarDesktop/NavbarDesktop.tsx +48 -0
- package/src/components/Navigation/NavbarMobile/NavbarMobile.stories.tsx +59 -0
- package/src/components/Navigation/NavbarMobile/NavbarMobile.tsx +75 -0
- package/src/components/Navigation/Stepper/Stepper.stories.tsx +41 -0
- package/src/components/Navigation/Stepper/Stepper.tsx +19 -0
- package/src/components/Navigation/Tabs/Tabs.stories.tsx +120 -0
- package/src/components/Navigation/Tabs/Tabs.tsx +92 -0
- package/src/components/Navigation/WizardNavbar/WizardNavbar.stories.tsx +59 -0
- package/src/components/Navigation/WizardNavbar/WizardNavbar.tsx +83 -0
- package/src/components/Navigation/index.ts +11 -0
- package/src/components/SVG/Facebook.svg +3 -0
- package/src/components/SVG/Instagram.svg +5 -0
- package/src/components/SVG/Linkedin.svg +5 -0
- package/src/components/SVG/Tiktok.svg +7 -0
- package/src/components/SVG/arrow-plain.svg +3 -0
- package/src/components/SVG/arrow.svg +3 -0
- package/src/components/SVG/calendar.svg +4 -0
- package/src/components/SVG/check-circle.svg +5 -0
- package/src/components/SVG/check-rounded.svg +4 -0
- package/src/components/SVG/check.svg +3 -0
- package/src/components/SVG/cross-rounded.svg +3 -0
- package/src/components/SVG/cross.svg +4 -0
- package/src/components/SVG/dollar-rounded.svg +6 -0
- package/src/components/SVG/double-arrow.svg +3 -0
- package/src/components/SVG/filters.svg +8 -0
- package/src/components/SVG/hat-cook.svg +4 -0
- package/src/components/SVG/home-hero-shape-mobile.svg +3 -0
- package/src/components/SVG/home-hero-shape-small.svg +3 -0
- package/src/components/SVG/home-hero-shape.svg +3 -0
- package/src/components/SVG/index.ts +75 -0
- package/src/components/SVG/info.svg +3 -0
- package/src/components/SVG/magic-wand.svg +9 -0
- package/src/components/SVG/menu.svg +5 -0
- package/src/components/SVG/minus.svg +3 -0
- package/src/components/SVG/mute.svg +4 -0
- package/src/components/SVG/pause.svg +3 -0
- package/src/components/SVG/play.svg +3 -0
- package/src/components/SVG/plus.svg +4 -0
- package/src/components/SVG/polaroid-thread.svg +17 -0
- package/src/components/SVG/profil.svg +4 -0
- package/src/components/SVG/quote.svg +3 -0
- package/src/components/SVG/recipe-bg-shape.svg +3 -0
- package/src/components/SVG/star.svg +3 -0
- package/src/components/SVG/subtract.svg +3 -0
- package/src/components/SVG/trustpilot.svg +14 -0
- package/src/components/SVG/unmute.svg +5 -0
- package/src/components/index.ts +20 -0
- package/src/components/styles/Color/Color.stories.tsx +89 -0
- package/src/components/styles/Color/Color.tsx +47 -0
- package/src/components/styles/Icon/Icon.stories.tsx +103 -0
- package/src/components/styles/Icon/Icon.tsx +6 -0
- package/src/components/styles/Illustration/Illustration.stories.tsx +253 -0
- package/src/components/styles/Illustration/Illustration.tsx +45 -0
- package/src/components/styles/Typography/Typography.stories.tsx +37 -0
- package/src/components/styles/Typography/Typography.tsx +19 -0
- package/src/helpers/accordions.ts +39 -0
- package/src/helpers/clickoutside.ts +31 -0
- package/src/helpers/debounce.ts +10 -0
- package/src/helpers/index.ts +9 -0
- package/src/helpers/intersectionObserver.ts +101 -0
- package/src/helpers/keyboardControl.ts +58 -0
- package/src/helpers/responsive.ts +29 -0
- package/src/helpers/scroll.ts +16 -0
- package/src/index.ts +8 -0
- package/src/lib/i18n.ts +20 -0
- package/src/lib/locales/fr/design.json +42 -0
- package/src/styles/globals.css +205 -0
- package/src/types/svg.d.ts +8 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
|
|
3
|
+
import { MobileMenu } from './MobileMenu';
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'Components/Navigation/MobileMenu',
|
|
7
|
+
component: MobileMenu,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
argTypes: {
|
|
10
|
+
variant: {
|
|
11
|
+
control: 'select',
|
|
12
|
+
options: ['dark', 'light'],
|
|
13
|
+
},
|
|
14
|
+
className: {
|
|
15
|
+
control: 'text',
|
|
16
|
+
description: 'Additional CSS classes',
|
|
17
|
+
},
|
|
18
|
+
activeNavLink: {
|
|
19
|
+
control: 'text',
|
|
20
|
+
description: 'Current active link',
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
args: {
|
|
24
|
+
variant: 'light',
|
|
25
|
+
className: '!top-0 !translate-y-0',
|
|
26
|
+
activeNavLink: '/recettes',
|
|
27
|
+
},
|
|
28
|
+
globals: {
|
|
29
|
+
viewport: {
|
|
30
|
+
value: 'mobile',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
} satisfies Meta<typeof MobileMenu>;
|
|
34
|
+
|
|
35
|
+
export default meta;
|
|
36
|
+
|
|
37
|
+
type Story = StoryObj<typeof meta>;
|
|
38
|
+
|
|
39
|
+
export const Light: Story = {
|
|
40
|
+
globals: {
|
|
41
|
+
backgrounds: {
|
|
42
|
+
value: 'dark',
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const Dark: Story = {
|
|
48
|
+
args: {
|
|
49
|
+
variant: 'dark',
|
|
50
|
+
},
|
|
51
|
+
globals: {
|
|
52
|
+
backgrounds: {
|
|
53
|
+
value: 'light',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import clsx from 'clsx';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
5
|
+
|
|
6
|
+
import { ProfilIcon } from '../../../components';
|
|
7
|
+
import { menuNavLinks } from '../Navbar/Navbar';
|
|
8
|
+
|
|
9
|
+
type MobileMenuProps = {
|
|
10
|
+
variant: 'dark' | 'light';
|
|
11
|
+
className?: string;
|
|
12
|
+
activeNavLink: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const variantStyles = {
|
|
16
|
+
light: 'text-claret-violet-dark bg-beige-light',
|
|
17
|
+
dark: 'text-beige-light bg-claret-violet-dark',
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const MobileMenu = ({ variant, className, activeNavLink }: MobileMenuProps) => {
|
|
21
|
+
const { t } = useTranslation();
|
|
22
|
+
|
|
23
|
+
//prettier-ignore
|
|
24
|
+
const linkStyles = clsx(
|
|
25
|
+
'w-full border-t px-6 py-4.5',
|
|
26
|
+
variant === 'light' ? 'border-claret-violet-light/30' : 'border-beige-light/30',
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<ul className={clsx('absolute top-0 right-0 left-0 z-1 w-full -translate-y-full transition-transform duration-300 ease-in-out group-data-[open=false]:duration-150 group-data-[open=true]:translate-y-0', variantStyles[variant], className)}>
|
|
31
|
+
{menuNavLinks.map((item) => (
|
|
32
|
+
<li key={item.label} className={clsx(linkStyles, activeNavLink === item.href && 'font-semibold')}>
|
|
33
|
+
<a href={item.href} aria-current={activeNavLink === item.href ? 'page' : undefined}>
|
|
34
|
+
{t(`navigation.${item.label}`)}
|
|
35
|
+
</a>
|
|
36
|
+
</li>
|
|
37
|
+
))}
|
|
38
|
+
<li>
|
|
39
|
+
<a href="/auth/sign-in" className={clsx('flex items-center gap-2.5 font-semibold', linkStyles, variant === 'light' ? 'bg-beige-dark' : 'bg-claret-violet-light')}>
|
|
40
|
+
<ProfilIcon className="w-2.5" /> {t('navigation.signIn')}
|
|
41
|
+
</a>
|
|
42
|
+
</li>
|
|
43
|
+
</ul>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { Meta, StoryObj } from '@storybook/react-vite';
|
|
4
|
+
|
|
5
|
+
import { Navbar } from './Navbar';
|
|
6
|
+
|
|
7
|
+
const meta = {
|
|
8
|
+
title: 'Components/Navigation/NavbarDesktop',
|
|
9
|
+
component: Navbar,
|
|
10
|
+
tags: ['autodocs'],
|
|
11
|
+
parameters: {
|
|
12
|
+
layout: 'fullscreen',
|
|
13
|
+
responsive: true,
|
|
14
|
+
},
|
|
15
|
+
argTypes: {
|
|
16
|
+
variant: {
|
|
17
|
+
control: 'select',
|
|
18
|
+
options: ['light', 'dark'],
|
|
19
|
+
},
|
|
20
|
+
connected: {
|
|
21
|
+
control: 'boolean',
|
|
22
|
+
description: 'Whether the user is connected.',
|
|
23
|
+
},
|
|
24
|
+
className: {
|
|
25
|
+
control: 'text',
|
|
26
|
+
description: 'Additional CSS classes.',
|
|
27
|
+
},
|
|
28
|
+
activeNavLink: {
|
|
29
|
+
control: 'text',
|
|
30
|
+
description: 'The active navigation link.',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
args: {
|
|
34
|
+
activeNavLink: '/recettes',
|
|
35
|
+
},
|
|
36
|
+
} satisfies Meta<typeof Navbar>;
|
|
37
|
+
|
|
38
|
+
export default meta;
|
|
39
|
+
|
|
40
|
+
type Story = StoryObj<typeof meta>;
|
|
41
|
+
|
|
42
|
+
export const Dark: Story = {
|
|
43
|
+
args: {
|
|
44
|
+
activeNavLink: '/recettes',
|
|
45
|
+
variant: 'dark',
|
|
46
|
+
},
|
|
47
|
+
globals: {
|
|
48
|
+
backgrounds: {
|
|
49
|
+
value: 'light',
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
render: (args) => (
|
|
53
|
+
<div className="h-screen w-screen">
|
|
54
|
+
<Navbar {...args} />
|
|
55
|
+
<div className="text-claret-violet-dark container mx-auto px-3">
|
|
56
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
57
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
58
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
59
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
60
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
61
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
62
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
63
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
64
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
65
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
66
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
67
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
68
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
69
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
70
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
71
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
72
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
73
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
74
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
75
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
76
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
77
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
78
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
79
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
80
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
),
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export const Light: Story = {
|
|
87
|
+
args: {
|
|
88
|
+
activeNavLink: '/recettes',
|
|
89
|
+
variant: 'light',
|
|
90
|
+
},
|
|
91
|
+
globals: {
|
|
92
|
+
backgrounds: {
|
|
93
|
+
value: 'dark',
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
render: (args) => (
|
|
97
|
+
<div className="h-screen w-screen">
|
|
98
|
+
<Navbar {...args} />
|
|
99
|
+
<div className="text-beige-light container mx-auto px-3">
|
|
100
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
101
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
102
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
103
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
104
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
105
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
106
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
107
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
108
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
109
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
110
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
111
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
112
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
113
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
114
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
115
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
116
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
117
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
118
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
119
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
120
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
121
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
122
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
123
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
124
|
+
<p>lore ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos. </p>
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
),
|
|
128
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useEffect, useRef, useState } from 'react';
|
|
4
|
+
|
|
5
|
+
import clsx from 'clsx';
|
|
6
|
+
|
|
7
|
+
import { NavbarDesktop, NavbarMobile } from '../../../components';
|
|
8
|
+
import { debounce } from '../../../helpers';
|
|
9
|
+
|
|
10
|
+
export type NavbarProps = {
|
|
11
|
+
variant: 'light' | 'dark';
|
|
12
|
+
activeNavLink: string;
|
|
13
|
+
voucher?: string;
|
|
14
|
+
connected?: boolean;
|
|
15
|
+
className?: string;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const menuNavLinks = [
|
|
19
|
+
{
|
|
20
|
+
label: 'recipes',
|
|
21
|
+
href: '/recettes',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
label: 'history',
|
|
25
|
+
href: '/notre-histoire',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
label: 'blog',
|
|
29
|
+
href: '/blog',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
label: 'sponsorship',
|
|
33
|
+
href: '/parrainage',
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
//todo update nav links
|
|
38
|
+
//todo connected style when design ready
|
|
39
|
+
//todo dog/Cat menu when design ready
|
|
40
|
+
//todo manage analytics events on buttons
|
|
41
|
+
|
|
42
|
+
export const Navbar = (props: NavbarProps) => {
|
|
43
|
+
const [variant, setVariant] = useState<'light' | 'dark'>(props.variant);
|
|
44
|
+
const navRef = useRef<HTMLDivElement | null>(null);
|
|
45
|
+
|
|
46
|
+
// GSAP system to manage navbar variant changes
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
const handleNavbarChange = debounce((event: CustomEvent) => {
|
|
49
|
+
const newVariant = event.detail as 'light' | 'dark';
|
|
50
|
+
setVariant(newVariant);
|
|
51
|
+
}, 10);
|
|
52
|
+
|
|
53
|
+
window.addEventListener('navbar-change', handleNavbarChange as EventListener);
|
|
54
|
+
|
|
55
|
+
return () => {
|
|
56
|
+
window.removeEventListener('navbar-change', handleNavbarChange as EventListener);
|
|
57
|
+
};
|
|
58
|
+
}, []);
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<div id="navbar" ref={navRef} className={clsx('w-full', variant === 'light' ? 'bg-claret-violet-dark' : 'bg-beige-light', props.voucher ? 'h-36 lg:h-36.5' : 'h-21 lg:h-27.5')}>
|
|
62
|
+
<NavbarDesktop {...props} variant={variant} />
|
|
63
|
+
<NavbarMobile {...props} variant={variant} />
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
|
|
3
|
+
import { NavbarDesktop } from './NavbarDesktop';
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'Components/Navigation/Navbar',
|
|
7
|
+
component: NavbarDesktop,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
parameters: {
|
|
10
|
+
layout: 'fullscreen',
|
|
11
|
+
},
|
|
12
|
+
argTypes: {
|
|
13
|
+
variant: {
|
|
14
|
+
control: 'select',
|
|
15
|
+
options: ['light', 'dark'],
|
|
16
|
+
},
|
|
17
|
+
connected: {
|
|
18
|
+
control: 'boolean',
|
|
19
|
+
description: 'Whether the user is connected.',
|
|
20
|
+
},
|
|
21
|
+
className: {
|
|
22
|
+
control: 'text',
|
|
23
|
+
description: 'Additional CSS classes.',
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
} satisfies Meta<typeof NavbarDesktop>;
|
|
27
|
+
|
|
28
|
+
export default meta;
|
|
29
|
+
|
|
30
|
+
type Story = StoryObj<typeof meta>;
|
|
31
|
+
|
|
32
|
+
export const Dark: Story = {
|
|
33
|
+
args: {
|
|
34
|
+
variant: 'dark',
|
|
35
|
+
activeNavLink: '/',
|
|
36
|
+
},
|
|
37
|
+
globals: {
|
|
38
|
+
backgrounds: {
|
|
39
|
+
value: 'light',
|
|
40
|
+
},
|
|
41
|
+
viewport: {
|
|
42
|
+
value: 'desktop',
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const Light: Story = {
|
|
48
|
+
args: {
|
|
49
|
+
variant: 'light',
|
|
50
|
+
activeNavLink: '/',
|
|
51
|
+
},
|
|
52
|
+
globals: {
|
|
53
|
+
backgrounds: {
|
|
54
|
+
value: 'dark',
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import clsx from 'clsx';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
5
|
+
|
|
6
|
+
import { Banner, Button, Logo } from '../../../components';
|
|
7
|
+
import { menuNavLinks, NavbarProps } from '../Navbar/Navbar';
|
|
8
|
+
|
|
9
|
+
const variantStyles = {
|
|
10
|
+
light: 'text-claret-violet-dark from-claret-violet-dark to-claret-violet-dark/0',
|
|
11
|
+
dark: 'text-beige-light from-beige-light to-beige-light/0 ',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const NavbarDesktop = ({ variant = 'dark', className, voucher, activeNavLink }: NavbarProps) => {
|
|
15
|
+
const { t } = useTranslation('design');
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<nav className={clsx('group fixed top-0 right-0 left-0 z-100 bg-linear-to-b from-60% px-0 py-7.5 transition-colors duration-300 max-lg:hidden', voucher ? 'pt-16.5' : 'pt-7.5', variantStyles[variant], className)}>
|
|
19
|
+
{!!voucher && <Banner content={voucher} className={clsx('top-0 z-100')} />}
|
|
20
|
+
|
|
21
|
+
<div className={clsx('relative z-20 container mx-auto flex flex-1 items-center justify-between')}>
|
|
22
|
+
<div className="flex items-center md:gap-10 xl:gap-20">
|
|
23
|
+
<a href="/" className="me-auto">
|
|
24
|
+
<Logo className="w-18 xl:w-36" variant={variant === 'dark' ? 'primary' : 'secondary'} />
|
|
25
|
+
</a>
|
|
26
|
+
<ul className="flex items-center justify-between md:gap-2.5 xl:gap-5">
|
|
27
|
+
{menuNavLinks.map((link) => (
|
|
28
|
+
<li key={link.label}>
|
|
29
|
+
<Button variant="terciary" as="a" href={link.href} color={variant} active={activeNavLink === link.href}>
|
|
30
|
+
{t(`navigation.${link.label}`)}
|
|
31
|
+
</Button>
|
|
32
|
+
</li>
|
|
33
|
+
))}
|
|
34
|
+
</ul>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<div className="flex items-center gap-6">
|
|
38
|
+
<Button variant="secondary" color={variant} as="a" href="/auth/sign-in" size="md">
|
|
39
|
+
{t('navigation.signIn')}
|
|
40
|
+
</Button>
|
|
41
|
+
<Button variant="primary" color={variant} as="a" href="/wizard/type" size="md">
|
|
42
|
+
{t('navigation.tryTwoWeeks')}
|
|
43
|
+
</Button>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</nav>
|
|
47
|
+
);
|
|
48
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
|
|
3
|
+
import { NavbarMobile } from './NavbarMobile';
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'Components/Navigation/NavbarMobile',
|
|
7
|
+
component: NavbarMobile,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
parameters: {
|
|
10
|
+
layout: 'fullscreen',
|
|
11
|
+
},
|
|
12
|
+
argTypes: {
|
|
13
|
+
variant: {
|
|
14
|
+
control: 'select',
|
|
15
|
+
options: ['light', 'dark'],
|
|
16
|
+
},
|
|
17
|
+
connected: {
|
|
18
|
+
control: 'boolean',
|
|
19
|
+
description: 'Whether the user is connected.',
|
|
20
|
+
},
|
|
21
|
+
className: {
|
|
22
|
+
control: 'text',
|
|
23
|
+
description: 'Additional CSS classes.',
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
globals: {
|
|
27
|
+
viewport: {
|
|
28
|
+
value: 'mobile',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
} satisfies Meta<typeof NavbarMobile>;
|
|
32
|
+
|
|
33
|
+
export default meta;
|
|
34
|
+
|
|
35
|
+
type Story = StoryObj<typeof meta>;
|
|
36
|
+
|
|
37
|
+
export const Dark: Story = {
|
|
38
|
+
args: {
|
|
39
|
+
variant: 'dark',
|
|
40
|
+
activeNavLink: '/',
|
|
41
|
+
},
|
|
42
|
+
globals: {
|
|
43
|
+
backgrounds: {
|
|
44
|
+
value: 'light',
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const Light: Story = {
|
|
50
|
+
args: {
|
|
51
|
+
variant: 'light',
|
|
52
|
+
activeNavLink: '/',
|
|
53
|
+
},
|
|
54
|
+
globals: {
|
|
55
|
+
backgrounds: {
|
|
56
|
+
value: 'dark',
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
4
|
+
|
|
5
|
+
import clsx from 'clsx';
|
|
6
|
+
|
|
7
|
+
import { Banner, CrossIcon, Logo, MenuIcon, MobileMenu } from '../../../components';
|
|
8
|
+
import { disableScroll, enableScroll } from '../../../helpers';
|
|
9
|
+
import { NavbarProps } from '../Navbar/Navbar';
|
|
10
|
+
|
|
11
|
+
const variantStyles = {
|
|
12
|
+
light: 'text-claret-violet-dark from-claret-violet-dark to-claret-violet-dark/0 group-data-[open=true]:from-claret-violet-dark/0 group-data-[open=true]:text-claret-violet-dark',
|
|
13
|
+
dark: 'text-beige-light from-beige-light to-beige-light/0 group-data-[open=true]:from-beige-light/0 group-data-[open=true]:text-beige-light',
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const overlayStyles = {
|
|
17
|
+
dark: 'bg-claret-violet-dark/30',
|
|
18
|
+
light: 'bg-beige-light/30',
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const NavbarMobile = ({ variant = 'dark', className, voucher, activeNavLink }: NavbarProps) => {
|
|
22
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
23
|
+
const [isClosing, setIsClosing] = useState(false);
|
|
24
|
+
const closingTimerRef = useRef<number | null>(null);
|
|
25
|
+
|
|
26
|
+
const handleClickMenu = useCallback(() => {
|
|
27
|
+
if (isOpen) {
|
|
28
|
+
enableScroll();
|
|
29
|
+
setIsClosing(true);
|
|
30
|
+
setIsOpen(false);
|
|
31
|
+
closingTimerRef.current = window.setTimeout(() => {
|
|
32
|
+
setIsClosing(false);
|
|
33
|
+
}, 300);
|
|
34
|
+
} else {
|
|
35
|
+
disableScroll();
|
|
36
|
+
setIsOpen(true);
|
|
37
|
+
}
|
|
38
|
+
}, [isOpen]);
|
|
39
|
+
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
return () => {
|
|
42
|
+
if (closingTimerRef.current !== null) {
|
|
43
|
+
clearTimeout(closingTimerRef.current);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}, []);
|
|
47
|
+
|
|
48
|
+
const logoVariant: 'primary' | 'secondary' = useMemo(() => {
|
|
49
|
+
return (variant === 'dark' && !isOpen) || (variant === 'light' && isOpen) ? 'primary' : 'secondary';
|
|
50
|
+
}, [variant, isOpen]);
|
|
51
|
+
|
|
52
|
+
const mobileMenuStyles = useMemo(() => {
|
|
53
|
+
return clsx({
|
|
54
|
+
'text-claret-violet-dark': (variant === 'dark' && !isOpen) || (variant === 'light' && isOpen),
|
|
55
|
+
'text-beige-light': (variant === 'dark' && isOpen) || (variant === 'light' && !isOpen),
|
|
56
|
+
});
|
|
57
|
+
}, [variant, isOpen]);
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<nav data-open={isOpen} className={clsx('group fixed top-0 right-0 left-0 z-20 block lg:hidden', className)}>
|
|
61
|
+
{!!voucher && <Banner content={voucher} className={clsx('z-100', isOpen ? 'top-0' : 'top-7')} />}
|
|
62
|
+
<div className={clsx('relative z-10 flex items-center justify-between bg-linear-to-b from-60% p-6 pe-3 transition-colors duration-150', voucher ? (isOpen ? 'h-29.5 pt-13.5' : 'h-36 pt-20.5') : 'h-21.5 pt-6', variantStyles[variant])}>
|
|
63
|
+
<a href="/" className="me-auto">
|
|
64
|
+
<Logo className="w-18 md:w-36" variant={logoVariant} />
|
|
65
|
+
</a>
|
|
66
|
+
|
|
67
|
+
<button onClick={handleClickMenu} className={clsx('p-3', mobileMenuStyles)}>
|
|
68
|
+
{isOpen ? <CrossIcon className="w-4" /> : <MenuIcon className="w-4" />}
|
|
69
|
+
</button>
|
|
70
|
+
</div>
|
|
71
|
+
<MobileMenu variant={variant} className={voucher ? 'pt-29.5' : 'pt-21.5'} activeNavLink={activeNavLink} />
|
|
72
|
+
{(isOpen || isClosing) && <div onClick={handleClickMenu} className={clsx('fixed inset-0 z-0', overlayStyles[variant], isClosing ? 'animate-fade-out' : 'animate-fade-in')}></div>}
|
|
73
|
+
</nav>
|
|
74
|
+
);
|
|
75
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
|
|
3
|
+
import { Stepper } from './Stepper';
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof Stepper> = {
|
|
6
|
+
title: 'Components/Navigation/Stepper',
|
|
7
|
+
component: Stepper,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
parameters: {
|
|
10
|
+
layout: 'centered',
|
|
11
|
+
},
|
|
12
|
+
argTypes: {
|
|
13
|
+
totalSteps: {
|
|
14
|
+
control: 'number',
|
|
15
|
+
description: 'Total number of steps.',
|
|
16
|
+
},
|
|
17
|
+
currentStep: {
|
|
18
|
+
control: 'number',
|
|
19
|
+
description: 'Current step.',
|
|
20
|
+
},
|
|
21
|
+
className: {
|
|
22
|
+
control: 'text',
|
|
23
|
+
description: 'Additional CSS classes.',
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
args: {
|
|
27
|
+
totalSteps: 8,
|
|
28
|
+
currentStep: 1,
|
|
29
|
+
className: 'w-screen',
|
|
30
|
+
},
|
|
31
|
+
globals: {
|
|
32
|
+
backgrounds: {
|
|
33
|
+
value: 'light',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export default meta;
|
|
39
|
+
type Story = StoryObj<typeof meta>;
|
|
40
|
+
|
|
41
|
+
export const Default: Story = {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import clsx from 'clsx';
|
|
2
|
+
|
|
3
|
+
export type StepperProps = {
|
|
4
|
+
totalSteps: number;
|
|
5
|
+
currentStep: number;
|
|
6
|
+
className?: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const Stepper = ({ totalSteps, currentStep, className }: StepperProps) => {
|
|
10
|
+
return (
|
|
11
|
+
<div className={clsx('relative flex items-center justify-between gap-2', className)}>
|
|
12
|
+
{Array.from({ length: totalSteps }).map((_, index) => (
|
|
13
|
+
<div key={index} className={clsx('bg-beige-light border-claret-violet-dark/40 z-2 h-1.5 w-1.5 rounded-full border transition-colors duration-200 md:h-2.5 md:w-2.5', index <= currentStep - 1 && 'bg-claret-violet-dark delay-150')}></div>
|
|
14
|
+
))}
|
|
15
|
+
<div className="bg-claret-violet-dark/30 absolute right-0 left-0 z-0 h-0.25 md:h-0.5"></div>
|
|
16
|
+
<div style={{ width: `${((currentStep - 1) / (totalSteps - 1)) * 100}%` }} className={clsx('bg-claret-violet-dark transition-width absolute left-0 z-1 block h-0.25 w-0 max-w-full shrink-0 duration-300 md:h-0.5')}></div>
|
|
17
|
+
</div>
|
|
18
|
+
);
|
|
19
|
+
};
|