3bfa54b4b3
- Nuxt 3 project with @nuxtjs/tailwindcss module - Tailwind CSS config with A0 Dark Theme design tokens (CSS custom properties) - AppHeader: sticky, logo, nav, phone, social icons, mobile burger menu - AppFooter: 4-column grid (Navigation, Kontakt, Rechtliches, Social) - HmsLogo: SVG with orange #EC6925 border - error.vue: 404 page with Seite nicht gefunden - robots.txt server route: Disallow: / - Meta: noindex, nofollow, noarchive, nosnippet - JSON-LD: LocalBusiness schema - OpenGraph tags - routeRules: SSR/CSR per route - Shared components: LoadingSkeleton, EmptyState, ErrorState, LegalContentPage, SpeakerIcon - 42 vitest tests passing - Build: 0 errors
91 lines
3.7 KiB
Vue
91 lines
3.7 KiB
Vue
<template>
|
|
<div
|
|
class="flex flex-col items-center gap-2 p-4 rounded-lg border border-border-default bg-panel hover:border-accent-border transition-colors duration-fast cursor-pointer group"
|
|
role="button"
|
|
:tabindex="0"
|
|
:aria-label="type"
|
|
@click="$emit('select', type)"
|
|
@keydown.enter="$emit('select', type)"
|
|
>
|
|
<svg
|
|
:width="size"
|
|
:height="size"
|
|
viewBox="0 0 48 48"
|
|
fill="none"
|
|
class="text-secondary group-hover:text-accent transition-colors duration-fast"
|
|
aria-hidden="true"
|
|
>
|
|
<!-- Line Array -->
|
|
<template v-if="type === 'line-array'">
|
|
<rect x="6" y="16" width="8" height="16" rx="1" fill="currentColor" />
|
|
<path d="M16 20 L24 14 M16 28 L24 34" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
|
|
<path d="M26 12 L30 10 M26 36 L30 38" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.6" />
|
|
<path d="M32 8 L36 6 M32 40 L36 42" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.3" />
|
|
</template>
|
|
|
|
<!-- Subwoofer -->
|
|
<template v-else-if="type === 'subwoofer'">
|
|
<rect x="8" y="8" width="32" height="32" rx="2" fill="none" stroke="currentColor" stroke-width="2" />
|
|
<circle cx="24" cy="24" r="8" fill="none" stroke="currentColor" stroke-width="2" />
|
|
<circle cx="24" cy="24" r="4" fill="none" stroke="currentColor" stroke-width="1.5" />
|
|
</template>
|
|
|
|
<!-- Point Source -->
|
|
<template v-else-if="type === 'point-source'">
|
|
<rect x="10" y="18" width="10" height="12" rx="1" fill="currentColor" />
|
|
<path d="M22 16 Q28 24 22 32" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
|
|
<path d="M26 12 Q34 24 26 36" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.6" />
|
|
</template>
|
|
|
|
<!-- Column Array -->
|
|
<template v-else-if="type === 'column-array'">
|
|
<rect x="16" y="6" width="16" height="36" rx="1" fill="none" stroke="currentColor" stroke-width="2" />
|
|
<circle cx="24" cy="14" r="3" fill="currentColor" />
|
|
<circle cx="24" cy="24" r="3" fill="currentColor" />
|
|
<circle cx="24" cy="34" r="3" fill="currentColor" />
|
|
</template>
|
|
|
|
<!-- Monitor -->
|
|
<template v-else-if="type === 'monitor'">
|
|
<path d="M6 30 L24 14 L42 30 L42 34 L6 34 Z" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round" />
|
|
<circle cx="24" cy="26" r="4" fill="none" stroke="currentColor" stroke-width="1.5" />
|
|
</template>
|
|
|
|
<!-- Moving Head -->
|
|
<template v-else>
|
|
<rect x="18" y="6" width="12" height="10" rx="1" fill="currentColor" />
|
|
<path d="M24 16 L24 24" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
|
|
<circle cx="24" cy="30" r="6" fill="none" stroke="currentColor" stroke-width="2" />
|
|
<path d="M18 30 L14 30 M30 30 L34 30" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" opacity="0.5" />
|
|
</template>
|
|
</svg>
|
|
<span class="text-xs text-text-muted group-hover:text-accent transition-colors duration-fast">{{ label }}</span>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
const props = withDefaults(defineProps<{
|
|
type: "line-array" | "subwoofer" | "point-source" | "column-array" | "monitor" | "moving-head";
|
|
label?: string;
|
|
size?: number;
|
|
}>(), {
|
|
label: "",
|
|
size: 48,
|
|
});
|
|
|
|
const labelMap: Record<string, string> = {
|
|
"line-array": "Line Array",
|
|
"subwoofer": "Subwoofer",
|
|
"point-source": "Point Source",
|
|
"column-array": "Column Array",
|
|
"monitor": "Monitor",
|
|
"moving-head": "Moving Head",
|
|
};
|
|
|
|
const label = computed(() => props.label || labelMap[props.type] || props.type);
|
|
|
|
defineEmits<{
|
|
select: [type: string];
|
|
}>();
|
|
</script>
|