ADD: richtext system
Added richtext system for better card content.
This commit is contained in:
parent
5fa3ba397b
commit
a325d52052
2 changed files with 165 additions and 24 deletions
|
@ -96,6 +96,14 @@ a {
|
||||||
color: var(--color-white);
|
color: var(--color-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.text {
|
||||||
|
color: var(--color-orange);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--color-orange-light);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.nowrap {
|
.nowrap {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
@ -107,16 +115,8 @@ a.mail {
|
||||||
color: var(--color-orange);
|
color: var(--color-orange);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|
||||||
& img {
|
|
||||||
filter: invert(50%) sepia(84%) saturate(868%) hue-rotate(1deg) brightness(103%) contrast(100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: var(--color-orange-light);
|
color: var(--color-orange-light);
|
||||||
|
|
||||||
& img {
|
|
||||||
filter: invert(72%) sepia(59%) saturate(390%) hue-rotate(343deg) brightness(102%) contrast(103%);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,6 +164,10 @@ span.chip {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
.margin-top {
|
.margin-top {
|
||||||
margin-top: 3rem;
|
margin-top: 3rem;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,21 @@
|
||||||
<div class="flex-col gap-default">
|
<div class="flex-col gap-default">
|
||||||
<h3>{{skill.title}}</h3>
|
<h3>{{skill.title}}</h3>
|
||||||
<main class="flex-col gap-sm">
|
<main class="flex-col gap-sm">
|
||||||
<p v-for="(t, i) in skill.text" :class="[i === skill.text.length - 1 && 'margin-top bold']">{{t}}</p>
|
<component v-for="({type, children, content, ...rest}, textIndex) in skill.text" :is="type" v-bind="rest">
|
||||||
|
{{ content}}
|
||||||
|
<template v-if="children">
|
||||||
|
<template v-for="({type, content, ...rest}, childIndex) in children" :key="childIndex">
|
||||||
|
<template v-if="type === 'text'">
|
||||||
|
{{ content }}
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<component :is="type" v-bind="rest">
|
||||||
|
{{ content}}
|
||||||
|
</component>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</component>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
@ -17,35 +31,158 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
type RichTextBase = {
|
||||||
|
type: 'text'
|
||||||
|
content: string
|
||||||
|
}
|
||||||
|
|
||||||
const skills = [
|
type RichTextSimple = {
|
||||||
|
type: 'p' | 'span'
|
||||||
|
content: string
|
||||||
|
class ?: string
|
||||||
|
children ?: RichText[]
|
||||||
|
}
|
||||||
|
|
||||||
|
type RichTextLink = {
|
||||||
|
type: 'a'
|
||||||
|
content: string
|
||||||
|
href: string
|
||||||
|
target ?: string
|
||||||
|
class ?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
type RichText = RichTextBase | RichTextSimple | RichTextLink
|
||||||
|
|
||||||
|
type Skill = {
|
||||||
|
img: string
|
||||||
|
title: string
|
||||||
|
text: RichText[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const skills : Skill[] = [
|
||||||
{
|
{
|
||||||
img: 'https://picsum.photos/550/350.webp?random=1',
|
img: 'https://picsum.photos/550/350.webp?random=1',
|
||||||
title: 'Das, was du sehen kannst',
|
title: 'Das, was du sehen kannst',
|
||||||
text: [
|
text: [
|
||||||
'Die meisten Anwendungen haben eine grafische Benutzeroberfläche - die so genannte GUI. Wenn etwas graphisch ist, ' +
|
{
|
||||||
'dann bedeutet das auch natürlich, dass es sinnvoll dargestellt werden muss. Dafür verwenden wir kleine Bausteine, die wir Komponenten nennen.',
|
type: 'p',
|
||||||
'Grundsätzlich lassen sich komplette Anwendungen und auch einfache Webseiten ziemlich cool über Komponenten aufbauen, sodass wir wiederkehrende Elemente ' +
|
content: 'Die meisten Anwendungen haben eine grafische Benutzeroberfläche - die so genannte GUI. Wenn etwas graphisch ist, ' +
|
||||||
'wie Buttons, Textabschnitte, Links oder Teaser immer wieder verwenden können - selbst wenn sich diese in ihren Details wie Farben oder Icons unterscheiden.',
|
'dann bedeutet das auch natürlich, dass es sinnvoll dargestellt werden muss. Dafür verwenden wir kleine Bausteine, die wir Komponenten nennen.',
|
||||||
'Diese Komponenten so zu entwickeln, dass sie wirklich flexibel sind und auch perfekt mit dem Design übereinstimmen ist gar nicht so einfach, denn oft sollten sie ' +
|
},
|
||||||
'auch mehr können als im Design kurzfristig ersichtlich ist.',
|
{
|
||||||
'Diese Voraussicht, für den Fall der Fälle vorzusorgen: Die gibt\'s bei mir dazu. Fussel-Ehrenwort.'
|
type: 'p',
|
||||||
|
content: 'Grundsätzlich lassen sich komplette Anwendungen und auch einfache Webseiten ziemlich cool über Komponenten aufbauen, sodass wir wiederkehrende Elemente ' +
|
||||||
|
'wie Buttons, Textabschnitte, Links oder Teaser immer wieder verwenden können - selbst wenn sich diese in ihren Details wie Farben oder Icons unterscheiden.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'p',
|
||||||
|
content: 'Diese Komponenten so zu entwickeln, dass sie wirklich flexibel sind und auch perfekt mit dem Design übereinstimmen ist gar nicht so einfach, denn oft sollten sie ' +
|
||||||
|
'auch mehr können als im Design kurzfristig ersichtlich ist.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'p',
|
||||||
|
class: 'margin-top bold',
|
||||||
|
content: 'Diese Voraussicht, für den Fall der Fälle vorzusorgen: Die gibt\'s bei mir dazu.',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'span',
|
||||||
|
class: 'highlight',
|
||||||
|
content: 'Fussel-Ehrenwort.'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}, {
|
}, {
|
||||||
img: 'https://picsum.photos/550/350.webp?random=2',
|
img: 'https://picsum.photos/550/350.webp?random=2',
|
||||||
title: 'Da, wo du eintragen kannst',
|
title: 'Da, wo du eintragen kannst',
|
||||||
text: [
|
text: [
|
||||||
'Du hast Daten in einer Datenbank liegen, aber keine Ahnung, wie du da gescheit rankommen sollst?',
|
{
|
||||||
'Liegen deine Daten eventuell sogar verstreut an mehreren Orten, über Datenbanken, Dateien und anderen Storagemöglichkeiten verteilt?',
|
type: 'p',
|
||||||
'Kein Ding. Ich bau dir eine Schnittstelle, die alles easy zusammenträgt.'
|
content: 'In vielen Fällen ist es natürlich praktisch, wenn du einfach Inhalte einer Seite auf das ändern kannst, was gerade aktuell ist, ohne auf andere angewiesen zu sein.'
|
||||||
|
+ 'Damit das reibungslos möglich ist, entwickle ich dir gerne eine Anwendung oder Homepage, deren Inhalte du komplett selbst auf dem neuesten Stand halten kannst - und zwar ' +
|
||||||
|
'mit einem sogenannten CMS - ein ',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'span',
|
||||||
|
class: 'highlight',
|
||||||
|
content: 'C'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
content: 'ontent '
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'span',
|
||||||
|
class: 'highlight',
|
||||||
|
content: 'M'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
content: 'anagement '
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'span',
|
||||||
|
class: 'highlight',
|
||||||
|
content: 'S'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
content: 'ystem.'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'p',
|
||||||
|
content: 'Für CMS setze ich in erster Linie auf die cloudbasierte Lösung ',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'a',
|
||||||
|
target: '_blank',
|
||||||
|
class: 'text',
|
||||||
|
href: 'https://www.storyblok.com',
|
||||||
|
content: 'Storyblok'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
content: '. Dies stellt für die Meisten eine kostenlose bis kostengünstige Lösung dar ohne viel technisches Wissen mitbringen zu müssen.',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'p',
|
||||||
|
content: 'Falls du aber nicht möchtest, dass deine Daten auf irgendeinem Fremden server liegen - was ich durchaus verstehen kann! - dann gibt es auch die Möglichkeit mit ',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'a',
|
||||||
|
target: '_blank',
|
||||||
|
class: 'text',
|
||||||
|
href: 'https://www.strapi.io',
|
||||||
|
content: 'Strapi'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
content: ' selbst das eigene CMS zu hosten. Das musst du dann aber allerdings selbst erledigen oder ich erledige das für dich für einen Aufpreis.',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'p',
|
||||||
|
class: 'margin-top bold',
|
||||||
|
content: 'Nie wieder jemand anderen Fragen zu müssen, um deine Website auf dem neuesten Stand zu halten.',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'span',
|
||||||
|
class: 'highlight',
|
||||||
|
content: 'Mit Fussel-Garantie.'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}, {
|
}, {
|
||||||
img: 'https://picsum.photos/550/350.webp?random=3',
|
img: 'https://picsum.photos/550/350.webp?random=3',
|
||||||
title: 'Headless CMS',
|
title: 'Was dabei am Ende rauskommt',
|
||||||
text: [
|
text: [
|
||||||
'Wenn man ein Headless CMS anbinden will, dann verknüpft das Komponenten und APIs.',
|
|
||||||
'Für eine saubere und dynamische Einbindung reicht die Library, die euch vom Hersteller zur Verfügung gestellt wird, oft nicht aus.',
|
|
||||||
'Übersichtliche Projektstruktur und saubere Auflösung der Daten - mit Fusselgarantie.'
|
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue