Update
This commit is contained in:
136
resources/js/projects-renderer/components/ProjectHeadline.vue
Normal file
136
resources/js/projects-renderer/components/ProjectHeadline.vue
Normal 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>
|
||||
Reference in New Issue
Block a user