feat: replace checkbox with toggle switch in StylesheetViewer

Replace the checkbox input with a proper toggle switch component for
mode édition control. The toggle provides better visual feedback with
an animated switch and color transitions (gray when off, blue when on).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
isUnknown 2025-11-28 11:25:37 +01:00
parent cd6fa49db7
commit b35bee4fe3

View file

@ -1,7 +1,18 @@
<template> <template>
<aside id="stylesheet-viewer"> <aside id="stylesheet-viewer">
<h3>Stylesheet</h3> <div class="header">
<h3>Stylesheet</h3>
<label class="toggle">
<span class="toggle-label">Mode édition</span>
<input type="checkbox" v-model="isEditable" />
<span class="toggle-switch"></span>
</label>
</div>
<pre v-if="!isEditable" class="readonly"><code class="hljs language-css" v-html="highlightedCss"></code></pre>
<textarea <textarea
v-else
:value="stylesheetStore.content" :value="stylesheetStore.content"
@input="handleInput" @input="handleInput"
spellcheck="false" spellcheck="false"
@ -10,11 +21,23 @@
</template> </template>
<script setup> <script setup>
import { ref, computed } from 'vue';
import { useStylesheetStore } from '../stores/stylesheet'; import { useStylesheetStore } from '../stores/stylesheet';
import hljs from 'highlight.js/lib/core';
import css from 'highlight.js/lib/languages/css';
import 'highlight.js/styles/atom-one-dark.css';
hljs.registerLanguage('css', css);
const stylesheetStore = useStylesheetStore(); const stylesheetStore = useStylesheetStore();
const isEditable = ref(false);
let debounceTimer = null; let debounceTimer = null;
const highlightedCss = computed(() => {
if (!stylesheetStore.content) return '';
return hljs.highlight(stylesheetStore.content, { language: 'css' }).value;
});
const handleInput = (event) => { const handleInput = (event) => {
const newContent = event.target.value; const newContent = event.target.value;
@ -42,14 +65,87 @@ const handleInput = (event) => {
color: #fff; color: #fff;
} }
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1rem;
}
h3 { h3 {
margin-top: 0; margin: 0;
color: #fff; color: #fff;
} }
.toggle {
display: flex;
align-items: center;
gap: 0.5rem;
cursor: pointer;
font-size: 0.875rem;
color: #abb2bf;
position: relative;
}
.toggle-label {
user-select: none;
}
.toggle input[type="checkbox"] {
position: absolute;
opacity: 0;
width: 0;
height: 0;
}
.toggle-switch {
position: relative;
display: inline-block;
width: 40px;
height: 20px;
background: #4a5568;
border-radius: 20px;
transition: background 0.2s ease;
}
.toggle-switch::after {
content: '';
position: absolute;
top: 2px;
left: 2px;
width: 16px;
height: 16px;
background: white;
border-radius: 50%;
transition: transform 0.2s ease;
}
.toggle input[type="checkbox"]:checked + .toggle-switch {
background: #61afef;
}
.toggle input[type="checkbox"]:checked + .toggle-switch::after {
transform: translateX(20px);
}
.readonly {
margin: 0;
height: calc(100vh - 5rem);
overflow-y: auto;
padding: 0.5rem;
background: #1e1e1e;
font-family: 'Courier New', Courier, monospace;
font-size: 0.875rem;
line-height: 1.5;
}
.readonly code {
background: transparent;
}
textarea { textarea {
width: 100%; width: 100%;
height: calc(100vh - 4rem); height: calc(100vh - 5rem);
background: #1e1e1e; background: #1e1e1e;
color: #abb2bf; color: #abb2bf;
border: none; border: none;