button with image

This commit is contained in:
2025-06-26 17:54:51 +02:00
parent 8bab93274b
commit 96dbc38c3a
8 changed files with 141 additions and 69 deletions

View File

@ -11,10 +11,12 @@
"@pinia/nuxt": "^0.11.0", "@pinia/nuxt": "^0.11.0",
"@tailwindcss/vite": "^4.1.8", "@tailwindcss/vite": "^4.1.8",
"@vueuse/core": "^13.3.0", "@vueuse/core": "^13.3.0",
"gsap": "^3.13.0",
"nuxt": "^3.17.4", "nuxt": "^3.17.4",
"tailwindcss": "^4.1.7", "tailwindcss": "^4.1.7",
"vue": "^3.5.14", "vue": "^3.5.14",
"vue-router": "^4.5.1", "vue-router": "^4.5.1",
"vue3-toastify": "^0.2.8",
}, },
"devDependencies": { "devDependencies": {
"@nuxtjs/tailwindcss": "^6.14.0", "@nuxtjs/tailwindcss": "^6.14.0",
@ -1290,6 +1292,8 @@
"graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="], "graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="],
"gsap": ["gsap@3.13.0", "", {}, "sha512-QL7MJ2WMjm1PHWsoFrAQH/J8wUeqZvMtHO58qdekHpCfhvhSL4gSiz6vJf5EeMP0LOn3ZCprL2ki/gjED8ghVw=="],
"gzip-size": ["gzip-size@7.0.0", "", { "dependencies": { "duplexer": "^0.1.2" } }, "sha512-O1Ld7Dr+nqPnmGpdhzLmMTQ4vAsD+rHwMm1NLUmoUFFymBOMKxCCrtDxqdBRYXdeEPEi3SyoR4TizJLQrnKBNA=="], "gzip-size": ["gzip-size@7.0.0", "", { "dependencies": { "duplexer": "^0.1.2" } }, "sha512-O1Ld7Dr+nqPnmGpdhzLmMTQ4vAsD+rHwMm1NLUmoUFFymBOMKxCCrtDxqdBRYXdeEPEi3SyoR4TizJLQrnKBNA=="],
"h3": ["h3@1.15.3", "", { "dependencies": { "cookie-es": "^1.2.2", "crossws": "^0.3.4", "defu": "^6.1.4", "destr": "^2.0.5", "iron-webcrypto": "^1.2.1", "node-mock-http": "^1.0.0", "radix3": "^1.1.2", "ufo": "^1.6.1", "uncrypto": "^0.1.3" } }, "sha512-z6GknHqyX0h9aQaTx22VZDf6QyZn+0Nh+Ym8O/u0SGSkyF5cuTJYKlc8MkzW3Nzf9LE1ivcpmYC3FUGpywhuUQ=="], "h3": ["h3@1.15.3", "", { "dependencies": { "cookie-es": "^1.2.2", "crossws": "^0.3.4", "defu": "^6.1.4", "destr": "^2.0.5", "iron-webcrypto": "^1.2.1", "node-mock-http": "^1.0.0", "radix3": "^1.1.2", "ufo": "^1.6.1", "uncrypto": "^0.1.3" } }, "sha512-z6GknHqyX0h9aQaTx22VZDf6QyZn+0Nh+Ym8O/u0SGSkyF5cuTJYKlc8MkzW3Nzf9LE1ivcpmYC3FUGpywhuUQ=="],
@ -2360,6 +2364,8 @@
"vue-router": ["vue-router@4.5.1", "", { "dependencies": { "@vue/devtools-api": "^6.6.4" }, "peerDependencies": { "vue": "^3.2.0" } }, "sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw=="], "vue-router": ["vue-router@4.5.1", "", { "dependencies": { "@vue/devtools-api": "^6.6.4" }, "peerDependencies": { "vue": "^3.2.0" } }, "sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw=="],
"vue3-toastify": ["vue3-toastify@0.2.8", "", { "peerDependencies": { "vue": ">=3.2.0" }, "optionalPeers": ["vue"] }, "sha512-8jDOqsJaBZEbGpCbhWDETJc11D1lZefvgFPq/IPdM+U7+qyXoVPDvK6uq/FIgyV7qV0NcNzvGBMEzjsLQqGROw=="],
"web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="], "web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="],
"webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],

View File

@ -17,22 +17,12 @@
<p>{{ item.description }}</p> <p>{{ item.description }}</p>
<h4 class="h4-uppercase-bold-inter">{{ item.sub_title }}</h4> <h4 class="h4-uppercase-bold-inter">{{ item.sub_title }}</h4>
</div> </div>
<UiImgWrapper :src="`/api/public/file/${component.img[index]}_l.webp`">
<div <template #button>
class="h-[235px] sm:h-[350px] w-full rounded-[20px] bg-cover bg-center transition-transform duration-300 group-hover:scale-105 xl:block relative"
:style="{
backgroundImage: `url('/api/public/file/${component.img[index]}_l.webp')`,
backgroundSize: 'cover',
backgroundPosition: 'center',
}">
<div
class="hidden sm:block absolute bottom-0 right-0 pt-2 pl-2 bg-bg-light dark:bg-bg-dark rounded-tl-2xl">
<UiButtonArrow :arrow="true">{{ item.title }}</UiButtonArrow> <UiButtonArrow :arrow="true">{{ item.title }}</UiButtonArrow>
</div> </template>
</div> </UiImgWrapper>
<UiButtonArrow :arrow="true" class="sm:hidden mx-auto">{{
item.title
}}</UiButtonArrow>
</div> </div>
<!-- Map block with same layout rules --> <!-- Map block with same layout rules -->

View File

@ -10,18 +10,15 @@
backgroundImage: `url('/api/public/file/${component.img[0]}_l.webp')`, backgroundImage: `url('/api/public/file/${component.img[0]}_l.webp')`,
backgroundSize: 'cover', backgroundSize: 'cover',
backgroundPosition: 'center', backgroundPosition: 'center',
}" }" />
/> <div class="flex flex-col items-center space-y-[30px] sm:flex-row sm:items-start md:space-y-0 xl:items-center">
<div
class="flex flex-col items-center space-y-[30px] sm:flex-row sm:items-start md:space-y-0 xl:items-center"
>
<h3 class="h4-uppercase-bold-inter sm:min-w-[45%]"> <h3 class="h4-uppercase-bold-inter sm:min-w-[45%]">
{{ component.front_section_lang[0].data.title_second }} {{ component.front_section_lang[0].data.title_second }}
</h3> </h3>
<div class="flex w-full items-start justify-center sm:justify-end"> <div class="flex w-full items-start justify-center sm:justify-end">
<UiButtonArrow :arrow="true" type="fill">{{ <UiButtonArrow :arrow="true" type="fill">{{
component.front_section_lang[0].data.button component.front_section_lang[0].data.button
}}</UiButtonArrow> }}</UiButtonArrow>
</div> </div>
</div> </div>
</div> </div>
@ -29,22 +26,25 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
defineProps<{ component: { defineProps<{
id: number component: {
name: string id: number
img: string[] name: string
component_name: string img: string[]
is_no_lang: boolean component_name: string
page_name: string is_no_lang: boolean
front_section_lang: { page_name: string
data: { front_section_lang: {
title: string data: {
button: string title: string
title_second: string button: string
} title_second: string
id_front_section: number }
id_lang: number id_front_section: number
}[] id_lang: number
} }>(); }[]
}
}>();
</script> </script>

View File

@ -1,41 +1,26 @@
<template> <template>
<div <div class="group flex cursor-pointer items-center justify-start gap-2 whitespace-nowrap">
class="group flex cursor-pointer items-center justify-start gap-2 whitespace-nowrap" <button :class="[
> 'h-[40px] cursor-pointer min-w-40 rounded-[10px] px-[22px] transition-all sm:h-[50px] md:h-[65px] md:rounded-[15px] md:px-[42px]',
<button type === 'fill'
:class="[ ? 'bg-button text-text-dark group-hover:bg-button-hover'
'h-[40px] cursor-pointer rounded-[10px] px-[22px] transition-all sm:h-[50px] md:h-[65px] md:rounded-[15px] md:px-[42px]', : type === 'border'
type === 'fill'
? 'bg-button text-text-dark group-hover:bg-button-hover'
: type === 'border'
? 'border-button text-button group-hover:border-button-hover group-hover:text-button-hover border' ? 'border-button text-button group-hover:border-button-hover group-hover:text-button-hover border'
: 'border-button text-button dark:border-block dark:text-block group-hover:border-button-hover group-hover:text-button-hover border', : 'border-button text-button dark:border-block dark:text-block group-hover:border-button-hover group-hover:text-button-hover border',
full && 'w-full' full && 'w-full'
]" ]">
>
<slot /> <slot />
</button> </button>
<div <div v-if="arrow" :class="[
v-if="arrow" 'flex h-[40px] w-[40px] items-center justify-center rounded-[10px] p-2.5 transition-all sm:h-[50px] sm:w-[50px] md:h-[65px] md:w-[65px] md:rounded-[15px]',
:class="[ type === 'fill'
'flex h-[40px] w-[40px] items-center justify-center rounded-[10px] p-2.5 transition-all sm:h-[50px] sm:w-[50px] md:h-[65px] md:w-[65px] md:rounded-[15px]', ? 'bg-button text-text-dark group-hover:bg-button-hover'
type === 'fill' : 'border-button text-button dark:border-block dark:text-block group-hover:border-button-hover group-hover:text-button-hover border',
? 'bg-button text-text-dark group-hover:bg-button-hover' ]">
: 'border-button text-button dark:border-block dark:text-block group-hover:border-button-hover group-hover:text-button-hover border', <svg class="" width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg">
]"
>
<svg
class=""
width="26"
height="26"
viewBox="0 0 26 26"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path <path
d="M25.1274 1.87258C25.1274 1.3203 24.6797 0.872582 24.1274 0.872584L15.1274 0.872583C14.5751 0.872583 14.1274 1.3203 14.1274 1.87258C14.1274 2.42487 14.5751 2.87258 15.1274 2.87258L23.1274 2.87258L23.1274 10.8726C23.1274 11.4249 23.5751 11.8726 24.1274 11.8726C24.6797 11.8726 25.1274 11.4249 25.1274 10.8726L25.1274 1.87258ZM1.5 24.5L2.20711 25.2071L24.8345 2.57969L24.1274 1.87258L23.4203 1.16548L0.792893 23.7929L1.5 24.5Z" d="M25.1274 1.87258C25.1274 1.3203 24.6797 0.872582 24.1274 0.872584L15.1274 0.872583C14.5751 0.872583 14.1274 1.3203 14.1274 1.87258C14.1274 2.42487 14.5751 2.87258 15.1274 2.87258L23.1274 2.87258L23.1274 10.8726C23.1274 11.4249 23.5751 11.8726 24.1274 11.8726C24.6797 11.8726 25.1274 11.4249 25.1274 10.8726L25.1274 1.87258ZM1.5 24.5L2.20711 25.2071L24.8345 2.57969L24.1274 1.87258L23.4203 1.16548L0.792893 23.7929L1.5 24.5Z"
fill="currentColor" fill="currentColor" />
/>
</svg> </svg>
</div> </div>
</div> </div>

View File

@ -0,0 +1,29 @@
<template>
<div class="hidden md:block">
<svg width="100%" height="100%" viewBox="0 0 870 350" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<clipPath id="customClip">
<path
d="M20 0.5H847.666C858.366 0.5 867.067 9.12193 867.165 19.8213L869.315 254.821C869.415 265.66 860.656 274.5 849.816 274.5H653C641.678 274.5 632.5 283.678 632.5 295V330C632.5 340.77 623.77 349.5 613 349.5H20C9.23045 349.5 0.5 340.77 0.5 330V20C0.5 9.23045 9.23045 0.5 20 0.5Z" />
</clipPath>
</defs>
<image :href="src" clip-path="url(#customClip)" preserveAspectRatio="xMidYMid slice" width="100%"
height="100%" />
<foreignObject x="640" y="280" width="calc(100% - 640px - 1px)" height="calc(100% - 280px)">
<slot name="button"></slot>
</foreignObject>
</svg>
</div>
<div class="block md:hidden">
<img :src="src" width="100%" height="100%" class="object-contain rounded-2xl my-4" />
<div class="flex justify-center">
<slot name="button"></slot>
</div>
</div>
</template>
<script lang="ts" setup>
defineProps<{ src: string }>()
</script>

View File

@ -53,6 +53,7 @@ export default defineNuxtConfig({
ignored: ["**/backend/pb_data/**"], ignored: ["**/backend/pb_data/**"],
}, },
hmr: { hmr: {
host: "127.0.0.1",
clientPort: 3000, // useful if proxying clientPort: 3000, // useful if proxying
}, },
}, },

View File

@ -17,6 +17,7 @@
"@pinia/nuxt": "^0.11.0", "@pinia/nuxt": "^0.11.0",
"@tailwindcss/vite": "^4.1.8", "@tailwindcss/vite": "^4.1.8",
"@vueuse/core": "^13.3.0", "@vueuse/core": "^13.3.0",
"gsap": "^3.13.0",
"nuxt": "^3.17.4", "nuxt": "^3.17.4",
"tailwindcss": "^4.1.7", "tailwindcss": "^4.1.7",
"vue": "^3.5.14", "vue": "^3.5.14",

View File

@ -6,6 +6,66 @@
</template> </template>
<script setup> <script setup>
import { gsap } from 'gsap'
import ScrollTrigger from 'gsap/ScrollTrigger'
gsap.registerPlugin(ScrollTrigger)
watch(useColorMode(), (color) => {
console.log(color);
})
onMounted(() => {
const anim = gsap.fromTo(
'h1',
{
opacity: 0,
zoom: 0.95
},
{
opacity: 1,
duration: 1,
zoom: 1,
ease: 'power2.out',
}
)
ScrollTrigger.create({
trigger: 'h1',
start: 'top 80%',
onEnter: () => anim.restart(), // play when scrolling down
onEnterBack: () => anim.restart(), // play again when scrolling up
})
const animh2 = gsap.fromTo(
'h2',
{
opacity: 0,
color: 'var(--color-accent-green-light)',
},
{
opacity: 1,
duration: 1,
ease: 'power2.out',
}
)
ScrollTrigger.create({
trigger: 'h2',
start: 'top 80%',
onEnter: () => animh2.restart(), // play when scrolling down
onEnterBack: () => animh2.restart(), // play again when scrolling up
})
})
const route = useRoute(); const route = useRoute();
const store = useStore(); const store = useStore();
const menuStore = useMenuStore(); const menuStore = useMenuStore();