Currently working on a site using vuetify, I have come across the following layout:
The issue arises when I apply absolute positioning to the copy-code icon. Upon scrolling horizontally through the code, I encounter this problem:
When attempting to switch from absolute to fixed positioning, for some reason, the icon no longer appears within the code snippet but instead in the top-right corner of the page:
Here is the code for the innermost component (the code snippet):
<template>
<div>
<v-fade-transition>
<v-sheet class="code d-flex grey--text text--lighten-3 pa-4" :color="background" @mouseenter="showCopy = true" @mouseleave="showCopy = false">
<v-fade-transition>
<v-btn v-if="showCopy" flat icon class="copy" color="success lighten-3" @click="copyCode">
<v-icon>content_copy</v-icon>
</v-btn>
</v-fade-transition>
<v-layout column>
<v-flex
v-for="(row, index) of rows"
:key="index"
:class="getClass(index)"
@mouseenter="rowEntered(index)"
@mouseleave="rowLeft(index)"
@click="rowClicked(index)"
>
<span class="orange--text text--lighten-3 mr-3 code-row">{{ getRowText(index + 1) }}</span>
<span>{{ row }}</span>
</v-flex>
</v-layout>
</v-sheet>
</v-fade-transition>
<v-snackbar v-model="showSnackbar" color="success">
<span>Text copied to clipboard!!!</span>
<v-btn dark flat @click="showSnackbar = false">Close</v-btn>
</v-snackbar>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import { Component, Prop } from 'vue-property-decorator';
import copyToClipboard from 'copy-to-clipboard';
@Component({
components: {}
})
export default class AppExamCardCode extends Vue {
@Prop({ type: String, required: true })
readonly code!: string;
readonly color = 'grey';
readonly darkenDefault = 'darken-3';
readonly darkenSelected = 'darken-2';
showCopy = false;
showSnackbar = false;
hovered = -1;
selected: number[] = [];
get background(): string {
return this.color + ' ' + this.darkenDefault;
}
get rows(): string[] {
return this.code.split('\n');
}
//rowClicked, rowLeft, rowEntered, getClass(returns only row background color, getRowText),
copyCode(): void {
copyToClipboard(this.code);
this.showSnackbar = true;
}
}
</script>
<style scoped>
.code {
border-radius: 12px;
overflow-x: auto;
letter-spacing: 0.5px;
word-spacing: 1px;
font-family: "Inconsolata", monospace;
white-space: pre;
font-weight: 300;
font-size: 15px;
}
.code-row {
letter-spacing: 0.8px;
}
.copy {
position: absolute;
top: 0;
right: 0;
margin: 5px;
}
</style>
Contained within: (AppExamCardCodeExercise)
<template>
<div class="code-exercise">
<app-exam-card-code :code="exercise.code" />
<app-exam-card-code-answer :solution="exercise.solution" :showAnswers="showAnswers"/>
</div>
</template>
Contained within AppExamCardExercise:
<template>
<div>
<app-exam-card-true-or-false-exercise v-if="isTrueOrFalse" :showAnswers="showAnswers"/>
<app-exam-card-code-exercise v-else :showAnswers="showAnswers"/>
</div>
</template>
Contained within AppExamCard:
<template>
<div>
<v-scale-transition>
<v-card v-if="show" class="exam-card" :class="cardClass" flat>
<!-- omitted -->
</v-toolbar>
<v-card-text>
<v-slide-y-transition mode="out-in">
<v-layout row pa-5 :key="current">
<v-flex xs12>
<app-exam-card-score v-if="isFinished && showScore" />
<app-exam-card-exercise v-else :showAnswers="showAnswers" />
</v-flex>
</v-layout>
</v-slide-y-transition>
</v-card-text>
<v-card-actions>
<!-- omitted -->
</v-card-actions>
</v-card>
</v-scale-transition>
</div>
</template>