"packages": {
"": {
"devDependencies": {
+ "@alpinejs/intersect": "^3.4.2",
"alpinejs": "^3.4.2",
"autoprefixer": "^10.3.7",
"axios": "^0.21",
"tailwindcss": "^2.2.17"
}
},
+ "node_modules/@alpinejs/intersect": {
+ "version": "3.4.2",
+ "resolved": "https://registry.npmjs.org/@alpinejs/intersect/-/intersect-3.4.2.tgz",
+ "integrity": "sha512-n9B9JcqRiQ8b+ozWdU+x8e0AWXfaIljmrRlnkvPnUXsM3dGdeB5PCelaLEr98YyXGUW2YeugKEtPMsezwAMRUA==",
+ "dev": true
+ },
"node_modules/@babel/code-frame": {
"version": "7.15.8",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz",
}
},
"dependencies": {
+ "@alpinejs/intersect": {
+ "version": "3.4.2",
+ "resolved": "https://registry.npmjs.org/@alpinejs/intersect/-/intersect-3.4.2.tgz",
+ "integrity": "sha512-n9B9JcqRiQ8b+ozWdU+x8e0AWXfaIljmrRlnkvPnUXsM3dGdeB5PCelaLEr98YyXGUW2YeugKEtPMsezwAMRUA==",
+ "dev": true
+ },
"@babel/code-frame": {
"version": "7.15.8",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz",
"production": "mix --production"
},
"devDependencies": {
+ "@alpinejs/intersect": "^3.4.2",
"alpinejs": "^3.4.2",
"autoprefixer": "^10.3.7",
"axios": "^0.21",
-.menu-open .menu-overlay {
- @apply opacity-100 pointer-events-auto;
+body.menu-open {
+ /* Prevent scrollbars and scrolling when menu is open */
+ max-height: 100vh;
+ overflow: hidden;
}
-.menu-open .header-logo, .menu-open .site-header {
+.menu-open .site-header {
+ /* Header becomes fixed so that all elements are positioned at top, regardless of scroll position */
+ @apply text-white;
+ position: fixed;
+ width: calc(100% - 4rem); /* Full width minus 2rem padding on each side */
+}
+
+.menu-open .header-logo {
@apply text-white;
}
// Add AlpineJS - https://alpinejs.dev/
import Alpine from 'alpinejs';
window.Alpine = Alpine;
+
+import intersect from '@alpinejs/intersect';
+Alpine.plugin(intersect)
+
Alpine.start();
$logo = 'https://odl.paris.cubedesigners.com/storage/102/groupe-84.svg';
$subtitle = "Découvrez le coeur de l'offre sous forme de feuilleteur interactif";
$button = "Découvrir l'offre";
- $illustration = 'https://odl.paris.cubedesigners.com/storage/103/magazine-mockup-presentation-vol9-at-2x.png';
+ $illustration = 'https://odl.paris.cubedesigners.com/storage/137/home-magazine.jpg';
$shortcuts = [
[
'title' => 'Ressources',
<div class="flex flex-col flex-1 -mx-22 -mt-22">
{{-- Main home content --}}
- <div class="flex flex-1 justify-center -mb-16">{{-- negative margin so image shadow sits under shortcuts --}}
+ <div x-data="{ shown: false }" x-intersect="shown = true"
+ class="flex flex-1 justify-center -mb-16">{{-- negative margin so image shadow sits under shortcuts --}}
{{-- Left Column: logo + text + CTA --}}
<div class="home-left flex flex-1 flex-col justify-center items-center p-6 max-w-[360px]">
- @if($logo)<img class="mb-10" src="{{ $logo }}" alt="Logo">@endif
- @if($subtitle)<p class="text-center mb-5 max-w-[280px]">{{ $subtitle }}</p>@endif
- @if($button)<a class="bg-blue text-white py-4 px-10 rounded-full" href="#">{{ $button }}</a>@endif
+ @if($logo)
+ <img class="mb-10" src="{{ $logo }}" alt="Logo"
+ x-show="shown" x-transition.opacity.scale.80.origin.bottom.duration.800ms.delay.200ms>
+ @endif
+ @if($subtitle)
+ <p class="text-center mb-5 max-w-[280px]"
+ x-show="shown" x-transition.opacity.scale.80.origin.bottom.duration.500ms.delay.300ms>
+ {{ $subtitle }}
+ </p>
+ @endif
+ @if($button)
+ <a class="bg-blue text-white py-4 px-10 rounded-full transition transform hover:scale-105"
+ href="#"
+ x-show="shown" x-transition.opacity.scale.80.origin.bottom.duration.500ms.delay.300ms>
+ {{ $button }}
+ </a>
+ @endif
</div>
{{-- Right Column: Illustration image --}}
- <div class="home-right flex-1 bg-contain bg-center bg-no-repeat max-w-[550px]" style="@if($illustration)background-image:url({{ $illustration }})@endif"></div>
+ <div class="home-right flex-1 max-w-[550px]">
+ <div class="w-full h-full
+ bg-contain bg-center bg-no-repeat
+ transform transition duration-300"
+ x-show="shown"
+ x-transition.opacity.scale.50.duration.1000ms.delay.300ms
+ style="@if($illustration)background-image:url({{ $illustration }})@endif">
+ </div>
+ </div>
</div>
{{-- Link blocks --}}
- <div class="grid grid-cols-3 gap-6">
+ <div class="grid grid-cols-3 gap-6" x-data="{ shown: false }" x-intersect="shown = true">
@foreach($shortcuts as $shortcut)
- <div class="bg-blue flex items-center text-white p-6 rounded-lg">
+ <div class="relative bg-blue flex items-center text-white p-6 rounded-lg overflow-hidden">
<img class="flex-shrink mr-8 w-[40%]" src="{{ $shortcut['image'] }}" alt="">
<div class="flex-1 flex-shrink-0 space-y-2">
<h3 class="font-semibold uppercase">{{ $shortcut['title'] }}</h3>
<p>{{ $shortcut['content'] }}</p>
- <x-link :href="$shortcut['link']" class="circle-arrow"></x-link>
+ <x-link :href="$shortcut['link']" class="circle-arrow transition transform hover:scale-110"></x-link>
+ </div>
+ {{-- Initial Mask --}}
+ <div class="absolute top-0 left-0 w-full h-full bg-white z-1 transition-transform transform origin-top ease-out duration-500"
+ :class="{ 'scale-y-0': shown }"
+ style="transition-delay: {{ 300 + $loop->index * 100 }}ms"
+ >
</div>
</div>
@endforeach
<title>{{ config('app.name') }}</title>
</head>
<body class="font-primary p-8" :class="menuOpen && 'menu-open'" x-data="{ menuOpen: false }">
- <header class="site-header relative flex justify-between z-10">
- {{-- Burger Menu Icon --}}
+ <header class="site-header relative flex justify-between z-20 transition-colors duration-500">
+ {{-- Menu Toggle --}}
<a href="#" @click.prevent="menuOpen = !menuOpen">
- <svg class="stroke-current fixed" xmlns="http://www.w3.org/2000/svg" width="33" height="26" viewBox="0 0 33.494 26.495">
+
+ {{-- Burger Menu Icon --}}
+ <svg x-show="!menuOpen" class="stroke-current fixed" xmlns="http://www.w3.org/2000/svg" width="33" height="26" viewBox="0 0 33.494 26.495">
<g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<path d="M1 1h31.494"/>
<path d="M1 13.248h31.494"/>
<path d="M1 25.495h31.494"/>
</g>
</svg>
+
+ {{-- Close Icon --}}
+ {{-- This icon is given the same width and height as the burger icon so it aligns properly (paths will be centred in the canvas) --}}
+ <svg x-cloak x-show="menuOpen" class="stroke-current fixed" xmlns="http://www.w3.org/2000/svg" width="33" height="26" viewBox="0 0 25.098 25.098">
+ <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
+ <path d="m1.414 23.683 22.27-22.27"/>
+ <path d="m1.414 1.414 22.27 22.27"/>
+ </g>
+ </svg>
+
<span class="ml-14">Menu</span>
</a>
</a>
</header>
+ {{-- Header spacer: same height as the header in the normal flow --}}
+ {{-- This is needed because the header switches to position:fixed when menu is open and therefore no longer --}}
+ {{-- takes any space in the document flow. This spacer is the replacement and prevents content from shifting. --}}
+ <div class="h-8" x-show="menuOpen"></div>
+
<div class="min-h-content flex flex-col mx-22 pt-22">
@yield('content')
</div>
fixed top-0 left-0 w-screen h-screen
flex items-center
bg-blue text-white
- transition-opacity duration-500
- px-30"
- :class="menuOpen ? '' : 'opacity-0 pointer-events-none'"
+ px-30
+ z-10"
+ x-show="menuOpen"
+ x-transition.opacity.duration.500ms
x-cloak>
- <ul class="font-medium text-6xl space-y-10">
+ <ul class="w-full font-medium text-6xl space-y-8">
@php
$menu_links = [
'/' => 'Accueil',
@foreach ($menu_links as $link => $text)
<li x-show="menuOpen"
- style="transition-delay: {{ 700 + (50 * $loop->iteration) }}ms"
+ style="transition-delay: {{ 300 + (200 * $loop->iteration) }}ms"
x-transition:enter="transition transform ease-out duration-1000"
x-transition:enter-start="opacity-0 translate-x-[-100px]"
x-transition:enter-end="opacity-100 translate-x-0">
- <x-link class="text-current transition-opacity duration-200 hover:opacity-60" href="{{ $link }}">{{ $text }}</x-link>
+ <x-link class="inline-block text-current transition-transform transform duration-200 hover:scale-105"
+ href="{{ $link }}">
+ {{ $text }}
+ </x-link>
+ </li>
+ <li class="bg-blue-dark h-px"
+ x-show="menuOpen"
+ style="transition-delay: {{ 600 + (200 * $loop->iteration) }}ms; transition-duration: 1700ms;"
+ x-transition:enter="transition transform origin-left ease-in-out"
+ x-transition:enter-start="opacity-0 scale-x-0"
+ x-transition:enter-end="opacity-100 scale-x-100">
</li>
@endforeach
</ul>