Compare commits

...

2 commits

Author SHA1 Message Date
isUnknown
83455b7098 fix: improve Coloris color picker visibility and button clickability
All checks were successful
Deploy / Build and Deploy to Production (push) Successful in 16s
- Fix grid layout: add second column for input (grid-template-columns: var(--input-h) 1fr)
- Ensure color picker button is clickable with cursor pointer and pointer-events auto
- Set color picker z-index to 10000 to display above all UI elements
- Add global styles to ensure Coloris button is always clickable

Fixes issues where:
- Color picker appeared behind ElementPopup
- Button was not consistently clickable
- Grid layout was missing second column definition

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-09 16:54:10 +01:00
isUnknown
9127520ff7 feat: add keyboard shortcut Cmd/Ctrl+S to SaveButton
- Add Cmd+S (Mac) or Ctrl+S (Windows/Linux) keyboard shortcut to save CSS
- Detect platform to display correct shortcut symbol (⌘ or Ctrl)
- Prevent default browser save behavior
- Translate tooltips to French
- Show shortcut in button tooltip

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-09 16:46:48 +01:00
5 changed files with 90 additions and 68 deletions

View file

@ -11,25 +11,19 @@ input[type="number"] {
// min-width: var(--input-w); // min-width: var(--input-w);
// width: 100%; // width: 100%;
// padding: 0 1ch; // padding: 0 1ch;
} }
.field { .field {
display: flex; display: flex;
label { label {
font-weight: 600; font-weight: 600;
color: var(--color-800); color: var(--color-800);
} }
.input-with-unit { .input-with-unit {
display: flex; display: flex;
gap: 0.3rem; gap: 0.3rem;
} }
.unit-toggle { .unit-toggle {
@ -44,43 +38,42 @@ input[type="number"] {
.clr-field { .clr-field {
width: 100%; width: 100%;
display: grid; display: grid;
grid-template-columns: var(--input-h); grid-template-columns: var(--input-h) 1fr;
grid-gap: 1ch; grid-gap: 1ch;
button{ button {
grid-column: 1; grid-column: 1;
position: relative; position: relative;
border-radius: var(--border-radius); border-radius: var(--border-radius);
cursor: pointer;
pointer-events: auto;
} }
input{ input {
grid-column: 2; grid-column: 2;
} }
} }
} }
} }
.field {
.field{
display: grid; display: grid;
grid-template-columns: var(--label-w) 1fr; grid-template-columns: var(--label-w) 1fr;
label{ label {
align-self: center; align-self: center;
} }
} }
.field-font{ .field-font {
display: grid; display: grid;
grid-template-columns: var(--label-w) 1fr; grid-template-columns: var(--label-w) 1fr;
grid-template-rows: var(--input-h) var(--input-h); grid-template-rows: var(--input-h) var(--input-h);
select{ select {
width: 100%; width: 100%;
} }
.field-checkbox{ .field-checkbox {
grid-column: 2; grid-column: 2;
padding-top: var(--space-xs); padding-top: var(--space-xs);
label{ label {
font-weight: 400; font-weight: 400;
margin-left: 0.75ch; margin-left: 0.75ch;
color: var(--color-txt); color: var(--color-txt);
@ -88,45 +81,41 @@ input[type="number"] {
} }
} }
.field-text-size{ .field-text-size {
input[type="number"]{ input[type="number"] {
width: var(--input-w-small); width: var(--input-w-small);
padding-left: 0.75ch; padding-left: 0.75ch;
} }
input[type="range"]{ input[type="range"] {
flex-grow: 2; flex-grow: 2;
flex-shrink: 2; flex-shrink: 2;
} }
} }
.field-margin, .field-size{ .field-margin,
.field-size {
display: inline-grid; display: inline-grid;
width: calc(50% - 1ch); width: calc(50% - 1ch);
grid-template-columns: 6.5ch var(--input-w-small) 1fr; grid-template-columns: 6.5ch var(--input-w-small) 1fr;
margin-bottom: var(--space-xs); margin-bottom: var(--space-xs);
input{ input {
width: var(--input-w-small); width: var(--input-w-small);
padding-left: 0.75ch; padding-left: 0.75ch;
} }
&:nth-of-type(odd){ &:nth-of-type(odd) {
margin-right: 2ch; margin-right: 2ch;
} }
} }
.checkbox-field{ .checkbox-field {
margin: calc(var(--space-xs)*2) 0; margin: calc(var(--space-xs) * 2) 0;
grid-template-columns: 3ch 1fr; grid-template-columns: 3ch 1fr;
input{ input {
justify-self: left; justify-self: left;
margin: 0; margin: 0;
} }
} }
.field--view-only { .field--view-only {
opacity: 0.3; opacity: 0.3;
} }
@ -165,12 +154,6 @@ input[type="number"] {
} }
} }
// INPUTNUMBER =============================================== // INPUTNUMBER ===============================================
// Masquer les spinners natifs partout // Masquer les spinners natifs partout
@ -185,51 +168,46 @@ input[type="number"] {
-moz-appearance: textfield; -moz-appearance: textfield;
} }
.number-input {
.number-input{
position: relative; position: relative;
// padding: 0 1ch!important; // padding: 0 1ch!important;
input{ input {
padding-top: 0; padding-top: 0;
padding-bottom: 0; padding-bottom: 0;
} }
.spinner-buttons{ .spinner-buttons {
height: var(--input-h); height: var(--input-h);
width: var(--input-h); width: var(--input-h);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
position: absolute; position: absolute;
right: 0; right: 0;
top: 0; top: 0;
button{ button {
height: calc(var(--input-h)*0.5); height: calc(var(--input-h) * 0.5);
cursor: pointer; cursor: pointer;
padding: 0; padding: 0;
svg{ svg {
width: 10px; width: 10px;
height: auto; height: auto;
} }
svg path{ svg path {
fill: var(--color-interface-600); fill: var(--color-interface-600);
} }
&:hover{ &:hover {
svg path{ svg path {
fill: var(--color-interface-900); fill: var(--color-interface-900);
} }
} }
} }
.spinner-down{ .spinner-down {
svg{ svg {
// position: relative; // position: relative;
// top: -2px; // top: -2px;
} }
} }
} }
} }
// Composant NumberInput avec boutons personnalisés // Composant NumberInput avec boutons personnalisés
// .number-input { // .number-input {

View file

@ -304,13 +304,15 @@ input[type=number] {
.field .input-with-color .clr-field { .field .input-with-color .clr-field {
width: 100%; width: 100%;
display: grid; display: grid;
grid-template-columns: var(--input-h); grid-template-columns: var(--input-h) 1fr;
grid-gap: 1ch; grid-gap: 1ch;
} }
.field .input-with-color .clr-field button { .field .input-with-color .clr-field button {
grid-column: 1; grid-column: 1;
position: relative; position: relative;
border-radius: var(--border-radius); border-radius: var(--border-radius);
cursor: pointer;
pointer-events: auto;
} }
.field .input-with-color .clr-field input { .field .input-with-color .clr-field input {
grid-column: 2; grid-column: 2;
@ -351,17 +353,20 @@ input[type=number] {
flex-shrink: 2; flex-shrink: 2;
} }
.field-margin, .field-size { .field-margin,
.field-size {
display: inline-grid; display: inline-grid;
width: calc(50% - 1ch); width: calc(50% - 1ch);
grid-template-columns: 6.5ch var(--input-w-small) 1fr; grid-template-columns: 6.5ch var(--input-w-small) 1fr;
margin-bottom: var(--space-xs); margin-bottom: var(--space-xs);
} }
.field-margin input, .field-size input { .field-margin input,
.field-size input {
width: var(--input-w-small); width: var(--input-w-small);
padding-left: 0.75ch; padding-left: 0.75ch;
} }
.field-margin:nth-of-type(odd), .field-size:nth-of-type(odd) { .field-margin:nth-of-type(odd),
.field-size:nth-of-type(odd) {
margin-right: 2ch; margin-right: 2ch;
} }

File diff suppressed because one or more lines are too long

View file

@ -675,6 +675,19 @@ onMounted(async () => {
height: 1.5rem; height: 1.5rem;
} }
/* Coloris color picker - ensure it's always on top */
:deep(.clr-picker) {
z-index: 10000 !important;
}
/* Coloris button - ensure it's clickable and visible */
:deep(.clr-field button) {
pointer-events: auto !important;
cursor: pointer !important;
position: relative;
z-index: 1;
}
/* Hide UI elements when printing */ /* Hide UI elements when printing */
@media print { @media print {
#editor-panel, #editor-panel,

View file

@ -39,7 +39,7 @@
</template> </template>
<script setup> <script setup>
import { ref, computed } from 'vue'; import { ref, computed, onMounted, onUnmounted } from 'vue';
import { useStylesheetStore } from '../stores/stylesheet'; import { useStylesheetStore } from '../stores/stylesheet';
const stylesheetStore = useStylesheetStore(); const stylesheetStore = useStylesheetStore();
@ -51,6 +51,10 @@ const lastSavedFormatted = computed(() => stylesheetStore.lastSavedFormatted);
const hasError = computed(() => !!saveError.value); const hasError = computed(() => !!saveError.value);
const showSuccess = ref(false); const showSuccess = ref(false);
// Detect platform for keyboard shortcut display
const isMac = typeof navigator !== 'undefined' && navigator.platform.toUpperCase().indexOf('MAC') >= 0;
const shortcutKey = isMac ? '⌘' : 'Ctrl';
const handleSave = async () => { const handleSave = async () => {
const result = await stylesheetStore.saveCustomCss(); const result = await stylesheetStore.saveCustomCss();
@ -64,12 +68,34 @@ const handleSave = async () => {
// Errors are handled in the store and reflected in hasError // Errors are handled in the store and reflected in hasError
}; };
const getTooltip = () => { const handleKeyDown = (event) => {
if (!isDirty.value) return 'No changes to save'; // Check for Cmd+S (Mac) or Ctrl+S (Windows/Linux)
if (isSaving.value) return 'Saving...'; if ((event.metaKey || event.ctrlKey) && event.key === 's') {
if (hasError.value) return saveError.value; event.preventDefault();
return 'Save custom CSS';
// Only save if there are changes and not currently saving
if (isDirty.value && !isSaving.value) {
handleSave();
}
}
}; };
const getTooltip = () => {
if (!isDirty.value) return 'Aucune modification à enregistrer';
if (isSaving.value) return 'Enregistrement...';
if (hasError.value) return saveError.value;
return `Enregistrer le CSS personnalisé (${shortcutKey}+S)`;
};
// Add keyboard listener on mount
onMounted(() => {
window.addEventListener('keydown', handleKeyDown);
});
// Remove keyboard listener on unmount
onUnmounted(() => {
window.removeEventListener('keydown', handleKeyDown);
});
</script> </script>
<style scoped> <style scoped>