This commit is contained in:
2026-05-13 17:11:09 +02:00
commit ea63897455
2785 changed files with 359868 additions and 0 deletions

View File

@@ -0,0 +1,136 @@
<script setup>
import { computed, inject } from 'vue';
defineProps({
headline: {
type: String,
default: '',
},
subline: {
type: String,
default: '',
},
mobilePreview: {
type: Boolean,
default: false,
},
});
const updateHeader = inject('editorUpdateHeader', null);
const isEditable = computed(() => !!updateHeader);
function onHeadlineBlur(e) {
updateHeader?.('headline', e.target.innerText.trim());
}
function onSublineBlur(e) {
updateHeader?.('subline', e.target.innerText.trim());
}
</script>
<template>
<section class="project-headline" :class="{ 'project-headline--mobile': mobilePreview }">
<span class="project-headline__eyebrow">Project headline</span>
<h1
v-if="isEditable"
contenteditable="true"
class="project-headline__editable"
data-placeholder="Untitled project"
:class="{ 'project-headline__editable--empty': !headline }"
@blur="onHeadlineBlur"
v-text="headline || ''"
></h1>
<h1 v-else>{{ headline || 'Untitled project' }}</h1>
<p
v-if="isEditable"
contenteditable="true"
class="project-headline__subline project-headline__editable project-headline__subline--edit"
data-placeholder="Add a subline"
@blur="onSublineBlur"
v-text="subline || ''"
></p>
<p v-else-if="subline" class="project-headline__subline">{{ subline }}</p>
</section>
</template>
<style scoped>
.project-headline {
container-type: inline-size;
display: grid;
gap: 0.85rem;
}
.project-headline__eyebrow {
color: var(--project-muted, #6b7280);
font-size: 0.8rem;
font-weight: 600;
letter-spacing: 0.18em;
text-transform: uppercase;
}
h1 {
color: var(--project-ink, #111827);
font-size: clamp(2.3rem, 5vw, 4.75rem);
font-weight: 700;
letter-spacing: -0.04em;
line-height: 0.94;
margin: 0;
max-width: 20ch;
}
.project-headline__subline {
color: var(--project-muted, #6b7280);
font-size: clamp(1rem, 1.5vw, 1.35rem);
font-weight: 400;
line-height: 1.5;
margin: 0;
max-width: 42ch;
}
/* ---- Inline edit ---- */
.project-headline__editable {
outline: none;
border-bottom: 1px solid transparent;
transition: border-color 0.15s;
}
.project-headline__editable:hover {
border-bottom-color: rgba(15, 23, 42, 0.18);
}
.project-headline__editable:focus {
border-bottom-color: rgba(14, 116, 144, 0.5);
}
.project-headline__editable:empty::before {
color: var(--project-muted, #6b7280);
content: attr(data-placeholder);
pointer-events: none;
}
.project-headline__subline--edit {
min-height: 1.5em;
}
.project-headline--mobile h1 {
font-size: clamp(1.75rem, 7vw, 2.5rem);
max-width: 100%;
}
.project-headline--mobile .project-headline__subline {
font-size: 1rem;
max-width: 100%;
}
@container (max-width: 480px) {
h1 {
font-size: clamp(1.75rem, 9cqi, 2.5rem);
max-width: 100%;
}
.project-headline__subline {
font-size: 1rem;
max-width: 100%;
}
}
</style>