121 lines
7.1 KiB
Vue
121 lines
7.1 KiB
Vue
<template>
|
|
<div class="min-h-screen flex flex-col p-4 sm:p-8 bg-slate-50 dark:bg-gray-950 transition-colors duration-300" :class="{ 'lg:h-screen': layers.some(l => l.sprites.length) && $route.name === 'home' }">
|
|
<!-- Decorative gradient blur in top-right corner -->
|
|
<div class="fixed top-0 right-0 w-[600px] h-[600px] bg-gradient-to-bl from-blue-400/40 via-purple-400/30 to-transparent dark:from-blue-400/30 dark:via-purple-400/20 blur-3xl pointer-events-none -translate-y-32 translate-x-32"></div>
|
|
<div class="flex flex-col flex-1" :class="{ 'lg:overflow-hidden': layers.some(l => l.sprites.length) && $route.name === 'home' }">
|
|
<header class="mb-6 sm:mb-5">
|
|
<div class="flex flex-col sm:flex-row justify-between items-center gap-6 mb-8">
|
|
<div class="text-center sm:text-left">
|
|
<router-link to="/" class="block group" title="Spritesheet Generator - Create professional spritesheets" aria-label="Go to homepage">
|
|
<span class="text-3xl sm:text-5xl font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-gray-900 to-gray-700 dark:from-white dark:to-gray-300 tracking-tight mb-3 group-hover:opacity-80 transition-opacity">Spritesheet generator</span>
|
|
</router-link>
|
|
<p class="text-sm sm:text-base text-gray-600 dark:text-gray-400 font-medium">Create professional spritesheets for your game development projects</p>
|
|
</div>
|
|
<div class="flex flex-col items-center sm:items-end gap-3">
|
|
<nav class="flex flex-wrap items-center justify-center gap-3">
|
|
<a href="https://gitea.adhd.sh/root/spritesheet-generator" target="_blank" rel="noopener noreferrer" class="btn btn-secondary hover:shadow-md" data-rybbit-event="source-link" title="View source code on Gitea" aria-label="View source code repository">
|
|
<i class="fab fa-github"></i>
|
|
<span class="font-medium">Source</span>
|
|
</a>
|
|
<a href="https://discord.gg/JTev3nzeDa" target="_blank" rel="noopener noreferrer" class="btn btn-secondary hover:shadow-md" data-rybbit-event="discord-link" title="Join our Discord community" aria-label="Join Discord server">
|
|
<i class="fab fa-discord"></i>
|
|
<span class="font-medium">Discord</span>
|
|
</a>
|
|
<a href="#" @click.prevent="openHelpModal" class="btn btn-secondary hover:shadow-md" data-rybbit-event="help-link" title="Get help and documentation" aria-label="Open help modal">
|
|
<i class="fas fa-question-circle"></i>
|
|
<span class="font-medium">Help</span>
|
|
</a>
|
|
<a href="#" @click.prevent="openFeedbackModal" class="btn btn-secondary hover:shadow-md" data-rybbit-event="feedback-link" title="Share your feedback with us" aria-label="Open feedback modal">
|
|
<i class="fas fa-comment-dots"></i>
|
|
<span class="font-medium">Feedback</span>
|
|
</a>
|
|
<dark-mode-toggle />
|
|
</nav>
|
|
<div class="flex gap-4 text-sm font-medium text-gray-600 dark:text-gray-400">
|
|
<router-link to="/" class="hover:text-gray-900 dark:hover:text-white transition-colors" title="Spritesheet Generator Home" aria-label="Navigate to home page">Home</router-link>
|
|
<router-link to="/blog" class="hover:text-gray-900 dark:hover:text-white transition-colors" title="Read our blog posts" aria-label="Navigate to blog">Blog</router-link>
|
|
<router-link to="/about" class="hover:text-gray-900 dark:hover:text-white transition-colors" title="Learn more about us" aria-label="Navigate to about page">About Us</router-link>
|
|
<router-link to="/contact" class="hover:text-gray-900 dark:hover:text-white transition-colors" title="Get in touch with us" aria-label="Navigate to contact page">Contact</router-link>
|
|
<router-link to="/faq" class="hover:text-gray-900 dark:hover:text-white transition-colors" title="Frequently Asked Questions" aria-label="Navigate to FAQ page">FAQ</router-link>
|
|
<router-link to="/privacy-policy" class="hover:text-gray-900 dark:hover:text-white transition-colors" title="Read our privacy policy" aria-label="Navigate to privacy policy">Privacy Policy</router-link>
|
|
<a href="/sitemap.xml" target="_blank" rel="noopener noreferrer" class="hover:text-gray-900 dark:hover:text-white transition-colors" title="View XML sitemap" aria-label="View sitemap">Sitemap</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<Breadcrumbs />
|
|
|
|
<router-view />
|
|
</div>
|
|
|
|
<HelpModal :is-open="isHelpModalOpen" @close="closeHelpModal" />
|
|
<FeedbackModal :is-open="isFeedbackModalOpen" @close="closeFeedbackModal" />
|
|
|
|
<!-- One-time feedback popup -->
|
|
<div v-if="showFeedbackPopup" class="fixed inset-0 z-50 flex items-center justify-center backdrop-blur-sm">
|
|
<div class="max-w-md p-6 mx-4 bg-white dark:bg-gray-800 border border-gray-600 rounded-xl shadow-xl">
|
|
<div class="text-center">
|
|
<div class="mb-4 text-4xl">💬</div>
|
|
<h3 class="mb-3 text-lg font-semibold text-gray-900 dark:text-white">Help us improve!</h3>
|
|
<p class="mb-6 text-gray-600 dark:text-gray-300">We'd love to hear your thoughts about the Spritesheet generator. Would you like to share your feedback?</p>
|
|
<div class="flex justify-center gap-3">
|
|
<button @click="handleFeedbackPopupResponse(false)" class="px-4 py-2 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 transition-colors cursor-pointer">Maybe later</button>
|
|
<button @click="handleFeedbackPopupResponse(true)" class="px-6 py-2 font-medium text-white bg-gray-700 hover:bg-gray-800 rounded-lg transition-colors cursor-pointer">Share feedback</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, onMounted } from 'vue';
|
|
import { RouterView, RouterLink } from 'vue-router';
|
|
import HelpModal from './components/HelpModal.vue';
|
|
import FeedbackModal from './components/FeedbackModal.vue';
|
|
import DarkModeToggle from './components/utilities/DarkModeToggle.vue';
|
|
import Breadcrumbs from './components/Breadcrumbs.vue';
|
|
import { useLayers } from './composables/useLayers';
|
|
|
|
const { layers } = useLayers();
|
|
|
|
const isHelpModalOpen = ref(false);
|
|
const isFeedbackModalOpen = ref(false);
|
|
const showFeedbackPopup = ref(false);
|
|
|
|
const openHelpModal = () => {
|
|
isHelpModalOpen.value = true;
|
|
};
|
|
|
|
const closeHelpModal = () => {
|
|
isHelpModalOpen.value = false;
|
|
};
|
|
|
|
const openFeedbackModal = () => {
|
|
isFeedbackModalOpen.value = true;
|
|
};
|
|
|
|
const closeFeedbackModal = () => {
|
|
isFeedbackModalOpen.value = false;
|
|
};
|
|
|
|
onMounted(() => {
|
|
const hasShownFeedbackPopup = localStorage.getItem('hasShownFeedbackPopup');
|
|
if (!hasShownFeedbackPopup) {
|
|
setTimeout(() => {
|
|
showFeedbackPopup.value = true;
|
|
}, 3000);
|
|
}
|
|
});
|
|
|
|
const handleFeedbackPopupResponse = (showModal: boolean) => {
|
|
showFeedbackPopup.value = false;
|
|
localStorage.setItem('hasShownFeedbackPopup', 'true');
|
|
|
|
if (showModal) {
|
|
openFeedbackModal();
|
|
}
|
|
};
|
|
</script>
|