168 lines
3.9 KiB
Vue
168 lines
3.9 KiB
Vue
<template>
|
|
<div
|
|
data-cy="highlight-sidebar"
|
|
class="highlight-sidebar"
|
|
>
|
|
<div
|
|
class="highlight-sidebar__close-button"
|
|
@click="close"
|
|
>
|
|
<cross class="highlight-sidebar__close-icon" />
|
|
</div>
|
|
<div class="highlight-sidebar__section highlight-sidebar__highlight">
|
|
<h2 class="heading-4">Meine Markierung</h2>
|
|
<mark
|
|
class="paragraph highlight-sidebar__highlighted-text"
|
|
:class="[`highlight--${highlight.color}`]"
|
|
data-cy="highlight-in-sidebar"
|
|
ref="highlightMark"
|
|
>
|
|
{{ highlight.text }}
|
|
</mark>
|
|
</div>
|
|
<div class="highlight-sidebar__section highlight-sidebar__note">
|
|
<h2 class="heading-4">Meine Notiz</h2>
|
|
<div
|
|
class="form-with-border highlight-sidebar__note-form"
|
|
v-if="inEditMode"
|
|
>
|
|
<textarea
|
|
class="borderless-textarea"
|
|
placeholder="Notiz erfassen..."
|
|
data-cy="highlight-note-input"
|
|
v-model="note"
|
|
v-auto-grow
|
|
></textarea>
|
|
<a
|
|
class="button button--primary"
|
|
data-cy="highlight-note-save"
|
|
@click.stop="save"
|
|
>Speichern</a
|
|
>
|
|
</div>
|
|
<div v-else>
|
|
<!-- .stop to prevent the click handler to close the sidebar (as the element won't be a child of the
|
|
sidebar anymore once the event handler checks) -->
|
|
<p
|
|
data-cy="highlight-note-text"
|
|
class="highlight-sidebar__note"
|
|
>
|
|
{{ note }}
|
|
</p>
|
|
<a
|
|
class="inline-title highlight-sidebar__edit-note"
|
|
@click.stop="enableEditMode"
|
|
>Notiz bearbeiten</a
|
|
>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { HighlightNode } from '@/__generated__/graphql';
|
|
import { defineAsyncComponent, onMounted, ref } from 'vue';
|
|
export interface Props {
|
|
highlight: HighlightNode;
|
|
}
|
|
|
|
import vAutoGrow from '@/directives/auto-grow';
|
|
|
|
const emits = defineEmits(['close', 'update-text']);
|
|
const close = () => emits('close');
|
|
|
|
const note = ref('');
|
|
|
|
const props = defineProps<Props>();
|
|
|
|
const highlightMark = ref<HTMLElement | null>(null);
|
|
|
|
const Cross = defineAsyncComponent(() => import('@/components/icons/CrossIcon.vue'));
|
|
const inEditMode = ref(false);
|
|
|
|
onMounted(() => {
|
|
note.value = props.highlight.note?.text || '';
|
|
// enable edit mode if note does not yet exist from a previous save
|
|
inEditMode.value = note.value == '';
|
|
});
|
|
|
|
const enableEditMode = () => {
|
|
inEditMode.value = true;
|
|
};
|
|
|
|
const save = () => {
|
|
emits('update-text', note.value);
|
|
inEditMode.value = false;
|
|
};
|
|
</script>
|
|
|
|
<style scoped lang="postcss">
|
|
@import 'styles/css/mixins/desktop.css';
|
|
|
|
.highlight-sidebar {
|
|
position: fixed;
|
|
right: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
z-index: 15;
|
|
height: 100vh;
|
|
background-color: var(--color-white);
|
|
padding: var(--medium-spacing);
|
|
|
|
box-shadow: -2px 4px 11px 0px rgba(0, 0, 0, 0.12);
|
|
|
|
display: grid;
|
|
grid-template-columns: 1fr 50px;
|
|
grid-template-rows: 50px max-content;
|
|
|
|
grid-template-areas: '. x' 'h h' 'n n';
|
|
|
|
@mixin desktop {
|
|
width: 300px;
|
|
}
|
|
&__close-button {
|
|
grid-area: x;
|
|
}
|
|
&__highlight {
|
|
grid-area: h;
|
|
}
|
|
&__note {
|
|
grid-area: n;
|
|
}
|
|
|
|
&__section {
|
|
border-top: 1px solid var(--color-silver);
|
|
padding: var(--large-spacing) 0;
|
|
}
|
|
|
|
&__highlighted-text {
|
|
display: inline-block;
|
|
--num-lines: 3;
|
|
max-height: calc(var(--regular-font-size) * var(--paragraph-line-height) * var(--num-lines));
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
position: relative;
|
|
/* white-space: nowrap; */
|
|
&::after {
|
|
content: '...';
|
|
position: absolute;
|
|
right: 5px;
|
|
bottom: 0;
|
|
}
|
|
}
|
|
|
|
&__note-form {
|
|
min-height: 100px;
|
|
}
|
|
|
|
&__note {
|
|
white-space: pre-line; /* display newlines as linebreaks */
|
|
margin-bottom: var(--medium-spacing);
|
|
}
|
|
|
|
&__edit-note {
|
|
cursor: pointer;
|
|
}
|
|
}
|
|
</style>
|