Init
This commit is contained in:
400
docs/design-examples/components/README.md
Normal file
400
docs/design-examples/components/README.md
Normal file
@@ -0,0 +1,400 @@
|
||||
# experimenta Vue Komponenten-Beispiele
|
||||
|
||||
Dieser Ordner enthält **Referenz-Implementierungen** der experimenta Design System Komponenten als Vue 3 Single File Components (SFC).
|
||||
|
||||
Diese Komponenten dienen als **Vorlagen und Beispiele** für die Entwicklung eigener Komponenten oder können direkt in das Projekt kopiert werden.
|
||||
|
||||
---
|
||||
|
||||
## Verfügbare Komponenten
|
||||
|
||||
### 1. ExperimentaButton.vue
|
||||
|
||||
Animierter Button mit Gradient-Hintergrund nach experimenta Design System.
|
||||
|
||||
**Features:**
|
||||
|
||||
- Primary & Secondary Variants
|
||||
- Responsive Größen (Small, Medium, Large)
|
||||
- Link-Verhalten (kann als `<a>` oder `<button>` gerendert werden)
|
||||
- Hover-Animation mit Gradient-Shift
|
||||
- Accessibility-Ready (Focus States, ARIA Labels)
|
||||
|
||||
**Verwendung:**
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
import ExperimentaButton from './ExperimentaButton.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- Primary Button (default) -->
|
||||
<ExperimentaButton @click="handleClick"> Zur Startseite </ExperimentaButton>
|
||||
|
||||
<!-- Secondary Button -->
|
||||
<ExperimentaButton variant="secondary"> Abbrechen </ExperimentaButton>
|
||||
|
||||
<!-- As Link -->
|
||||
<ExperimentaButton href="https://www.experimenta.science" target="_blank">
|
||||
Zur experimenta Website
|
||||
</ExperimentaButton>
|
||||
|
||||
<!-- Small Size -->
|
||||
<ExperimentaButton size="small"> Small Button </ExperimentaButton>
|
||||
|
||||
<!-- Disabled -->
|
||||
<ExperimentaButton disabled> Disabled Button </ExperimentaButton>
|
||||
</template>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. ExperimentaCard.vue
|
||||
|
||||
Glass-morphism Card-Komponente mit verschiedenen Variants.
|
||||
|
||||
**Features:**
|
||||
|
||||
- Glass-morphism Styling (Backdrop Blur)
|
||||
- Info, Contact, Progress Variants
|
||||
- Optional: Akzent-Border (links)
|
||||
- Slot-basiertes Design (flexibel)
|
||||
|
||||
**Verwendung:**
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
import ExperimentaCard from './ExperimentaCard.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- Glass Card (Main) -->
|
||||
<ExperimentaCard>
|
||||
<h1>Willkommen!</h1>
|
||||
<p>Dies ist eine Glass-morphism Card.</p>
|
||||
</ExperimentaCard>
|
||||
|
||||
<!-- Info Card mit Titel -->
|
||||
<ExperimentaCard variant="info" title="Ihre Vorteile">
|
||||
<p>Mit der Jahreskarte erhalten Sie...</p>
|
||||
</ExperimentaCard>
|
||||
|
||||
<!-- Card mit Custom Title Slot -->
|
||||
<ExperimentaCard variant="contact">
|
||||
<template #title>
|
||||
<span>Kontakt</span>
|
||||
</template>
|
||||
<p>E-Mail: info@experimenta.science</p>
|
||||
</ExperimentaCard>
|
||||
|
||||
<!-- Progress Card -->
|
||||
<ExperimentaCard variant="progress">
|
||||
<!-- Progress Bar Content -->
|
||||
</ExperimentaCard>
|
||||
</template>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. ExperimentaStatusMessage.vue
|
||||
|
||||
Status-Nachrichten mit animierten Icons (Success, Error, Warning, Info).
|
||||
|
||||
**Features:**
|
||||
|
||||
- 4 Status-Typen mit passenden Farben
|
||||
- Animiertes Icon (Pulse Animation)
|
||||
- Responsive Icon-Größe
|
||||
- Slot-basierte Inhalte
|
||||
|
||||
**Verwendung:**
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
import ExperimentaStatusMessage from './ExperimentaStatusMessage.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- Success Message -->
|
||||
<ExperimentaStatusMessage type="success" title="Verlängerung erfolgreich!">
|
||||
<p>Ihre Jahreskarte wurde erfolgreich verlängert.</p>
|
||||
</ExperimentaStatusMessage>
|
||||
|
||||
<!-- Error Message -->
|
||||
<ExperimentaStatusMessage type="error" title="Ein Fehler ist aufgetreten">
|
||||
<p>Bitte versuchen Sie es erneut.</p>
|
||||
</ExperimentaStatusMessage>
|
||||
|
||||
<!-- Custom Icon -->
|
||||
<ExperimentaStatusMessage type="warning" title="Achtung" icon="⚠">
|
||||
<p>Dies ist eine Warnung.</p>
|
||||
</ExperimentaStatusMessage>
|
||||
|
||||
<!-- Custom Title Slot -->
|
||||
<ExperimentaStatusMessage type="info">
|
||||
<template #title>
|
||||
<span>Information</span>
|
||||
</template>
|
||||
<p>Hier ist eine Info.</p>
|
||||
</ExperimentaStatusMessage>
|
||||
</template>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. ExperimentaLogo.vue
|
||||
|
||||
Offizielles experimenta X-Logo mit Farbverläufen.
|
||||
|
||||
**Features:**
|
||||
|
||||
- SVG-basiert (skalierbar, scharf)
|
||||
- 3 Größen (Small, Medium, Large)
|
||||
- Responsive (passt sich automatisch an)
|
||||
- Optional als Link verwendbar
|
||||
- Hover-Animation
|
||||
|
||||
**Verwendung:**
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
import ExperimentaLogo from './ExperimentaLogo.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- Logo (default: large) -->
|
||||
<ExperimentaLogo />
|
||||
|
||||
<!-- Logo als Link -->
|
||||
<ExperimentaLogo href="https://www.experimenta.science" target="_blank" />
|
||||
|
||||
<!-- Small Logo -->
|
||||
<ExperimentaLogo size="small" />
|
||||
|
||||
<!-- Medium Logo -->
|
||||
<ExperimentaLogo size="medium" />
|
||||
</template>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Integration in Nuxt 4
|
||||
|
||||
### Option 1: Komponenten in `components/` verschieben
|
||||
|
||||
Kopiere die gewünschten Komponenten nach `components/`:
|
||||
|
||||
```bash
|
||||
cp docs/design-examples/components/ExperimentaButton.vue components/
|
||||
```
|
||||
|
||||
Nuxt erkennt sie automatisch (Auto-Imports):
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div>
|
||||
<ExperimentaButton>Click me</ExperimentaButton>
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Option 2: Als Composable verwenden
|
||||
|
||||
Erstelle eine Composable-Funktion in `composables/useExperimenta.ts`:
|
||||
|
||||
```typescript
|
||||
export function useExperimenta() {
|
||||
return {
|
||||
// Export component references
|
||||
ExperimentaButton: () => import('@/docs/design-examples/components/ExperimentaButton.vue'),
|
||||
ExperimentaCard: () => import('@/docs/design-examples/components/ExperimentaCard.vue'),
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Anpassungen & Erweiterungen
|
||||
|
||||
### shadcn-nuxt Integration
|
||||
|
||||
Diese Komponenten können **shadcn-nuxt Komponenten ersetzen** oder ergänzen:
|
||||
|
||||
```vue
|
||||
<!-- Statt shadcn Button: -->
|
||||
<Button>Click me</Button>
|
||||
|
||||
<!-- Verwende experimenta Button: -->
|
||||
<ExperimentaButton>Click me</ExperimentaButton>
|
||||
```
|
||||
|
||||
### Tailwind Klassen verwenden
|
||||
|
||||
Alle Komponenten verwenden Tailwind CSS Utilities. Du kannst sie anpassen:
|
||||
|
||||
```vue
|
||||
<ExperimentaButton class="mt-8">
|
||||
Custom Margin
|
||||
</ExperimentaButton>
|
||||
```
|
||||
|
||||
### Custom Variants hinzufügen
|
||||
|
||||
Beispiel: Eine neue Button-Variant hinzufügen:
|
||||
|
||||
```vue
|
||||
<!-- In ExperimentaButton.vue -->
|
||||
<script setup lang="ts">
|
||||
interface Props {
|
||||
variant?: 'primary' | 'secondary' | 'tertiary' // Neu: tertiary
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* Neue Variant definieren */
|
||||
.btn-tertiary {
|
||||
@apply bg-info text-white;
|
||||
}
|
||||
|
||||
.btn-tertiary:hover {
|
||||
@apply bg-info-dark;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## TypeScript Support
|
||||
|
||||
Alle Komponenten sind **TypeScript-ready** mit vollständigen Prop-Definitionen.
|
||||
|
||||
Beispiel für Type-Safe Usage:
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import ExperimentaButton from './ExperimentaButton.vue'
|
||||
|
||||
function handleClick(event: MouseEvent) {
|
||||
console.log('Button clicked', event)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ExperimentaButton variant="primary" size="large" :disabled="false" @click="handleClick">
|
||||
Click me
|
||||
</ExperimentaButton>
|
||||
</template>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Accessibility (A11y)
|
||||
|
||||
Alle Komponenten folgen **WCAG 2.1 AA Standards**:
|
||||
|
||||
- ✅ **Keyboard Navigation** (Tab, Enter, Space)
|
||||
- ✅ **Focus Indicators** (sichtbarer Focus-Ring)
|
||||
- ✅ **ARIA Labels** (Screen Reader Support)
|
||||
- ✅ **Color Contrast** (mindestens 4.5:1 Ratio)
|
||||
|
||||
---
|
||||
|
||||
## Testing
|
||||
|
||||
Beispiel für Vitest Unit Tests:
|
||||
|
||||
```typescript
|
||||
// ExperimentaButton.spec.ts
|
||||
import { mount } from '@vue/test-utils'
|
||||
import ExperimentaButton from './ExperimentaButton.vue'
|
||||
|
||||
describe('ExperimentaButton', () => {
|
||||
it('renders primary button by default', () => {
|
||||
const wrapper = mount(ExperimentaButton, {
|
||||
slots: { default: 'Click me' },
|
||||
})
|
||||
|
||||
expect(wrapper.find('.btn-primary').exists()).toBe(true)
|
||||
expect(wrapper.text()).toBe('Click me')
|
||||
})
|
||||
|
||||
it('emits click event', async () => {
|
||||
const wrapper = mount(ExperimentaButton)
|
||||
await wrapper.trigger('click')
|
||||
|
||||
expect(wrapper.emitted('click')).toBeTruthy()
|
||||
})
|
||||
|
||||
it('renders as link when href is provided', () => {
|
||||
const wrapper = mount(ExperimentaButton, {
|
||||
props: { href: 'https://example.com' },
|
||||
})
|
||||
|
||||
expect(wrapper.element.tagName).toBe('A')
|
||||
expect(wrapper.attributes('href')).toBe('https://example.com')
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Storybook Integration (Optional)
|
||||
|
||||
Erstelle Stories für visuelle Dokumentation:
|
||||
|
||||
```typescript
|
||||
// ExperimentaButton.stories.ts
|
||||
import type { Meta, StoryObj } from '@storybook/vue3'
|
||||
import ExperimentaButton from './ExperimentaButton.vue'
|
||||
|
||||
const meta: Meta<typeof ExperimentaButton> = {
|
||||
title: 'Components/ExperimentaButton',
|
||||
component: ExperimentaButton,
|
||||
tags: ['autodocs'],
|
||||
}
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof ExperimentaButton>
|
||||
|
||||
export const Primary: Story = {
|
||||
args: {
|
||||
variant: 'primary',
|
||||
},
|
||||
render: (args) => ({
|
||||
components: { ExperimentaButton },
|
||||
setup() {
|
||||
return { args }
|
||||
},
|
||||
template: '<ExperimentaButton v-bind="args">Click me</ExperimentaButton>',
|
||||
}),
|
||||
}
|
||||
|
||||
export const Secondary: Story = {
|
||||
args: {
|
||||
variant: 'secondary',
|
||||
},
|
||||
render: (args) => ({
|
||||
components: { ExperimentaButton },
|
||||
setup() {
|
||||
return { args }
|
||||
},
|
||||
template: '<ExperimentaButton v-bind="args">Cancel</ExperimentaButton>',
|
||||
}),
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Weitere Ressourcen
|
||||
|
||||
- **Design System Dokumentation**: `docs/DESIGN_SYSTEM.md`
|
||||
- **Tailwind Config**: `tailwind.config.ts`
|
||||
- **CSS Custom Properties**: `assets/css/tailwind.css`
|
||||
- **Design-Vorlagen**: `design-examples/*.html`
|
||||
|
||||
---
|
||||
|
||||
**Fragen oder Feedback?** → docs@experimenta.science
|
||||
Reference in New Issue
Block a user