feat: integrate Coloris color picker for background field

Add Coloris.js library for enhanced color selection in PageSettings with
automatic button state sync across tab changes.

Features:
- Color picker with swatches, alpha support, and format toggle (hex/rgb/hsl)
- Button positioned to the left of input field
- Automatic sync when switching tabs (remembers selected color)
- Close button and click-outside-to-close functionality
- Dark theme with pill UI style

Changes:
- Install @melloware/coloris package
- PageSettings.vue: Integrate Coloris with data-coloris attribute,
  add tab visibility detection via provide/inject, force button update
  when returning to document tab
- EditorPanel.vue: Provide activeTab to child components, increase
  panel width to 30rem
- _forms.scss: Add .input-with-color styles with custom Coloris
  button positioning (absolute positioned to left of input)
- Temporarily comment out rgb/hex format buttons (replaced by Coloris
  format toggle)

Technical details:
- Uses provide/inject pattern to detect tab changes
- Triggers synthetic input events to force Coloris button refresh
- Custom CSS overrides to position swatch button correctly

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
isUnknown 2025-12-04 15:03:29 +01:00
parent 467ae905bd
commit 9af36fb422
17 changed files with 359 additions and 179 deletions

View file

@ -0,0 +1,21 @@
button {
cursor: pointer;
border: 1px solid var(--color-browngray-300);
color: var(--color-browngray-300);
border-radius: var(--border-radius);
padding: 0.1rem 0.3rem;
&.active {
border: 1px solid #000;
color: #000;
}
&.tab {
&.active {
background-color: #000;
color: #fff;
border: none;
}
}
}

View file

@ -0,0 +1,72 @@
select,
input[type="text"],
input[type="number"] {
background-color: var(--color-browngray-300);
}
.field--view-only {
opacity: 0.3;
}
.settings-section {
h2 {
border-bottom: 1px solid #000;
}
.settings-subsection:not(:last-child) {
border-bottom: 1px solid var(--color-browngray-050);
}
.settings-subsection {
padding: 0.5rem 0;
.field {
display: flex;
label {
width: 50%;
}
.input-with-unit {
display: flex;
}
.input-with-color {
.clr-field {
display: flex;
button {
position: absolute;
transform: none;
height: 1rem;
top: auto;
right: auto;
cursor: pointer;
}
input {
padding-left: 2.5rem;
}
}
}
}
&.margins {
display: flex;
flex-wrap: wrap;
h3 {
width: 100%;
}
.field {
width: 50%;
label {
width: 50%;
}
.input-with-unit {
input {
width: 50%;
}
}
}
}
}
}

View file

@ -0,0 +1,27 @@
body,
html {
padding: 0;
margin: 0;
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0;
}
input,
select {
border: none;
outline: none;
border-radius: var(--border-radius);
}
button {
background-color: transparent;
border: none;
}

View file

@ -0,0 +1,15 @@
body,
h1,
h2,
h3,
h4,
h5,
h6,
p,
a,
input,
select,
figcaption,
label {
font-family: sans-serif;
}

View file

@ -0,0 +1,8 @@
:root {
--color-panel-bg: #e8e6e5;
--color-browngray-050: #f5f3f0;
--color-browngray-200: #d0c4ba;
--color-browngray-300: #b5a9a1;
--border-radius: 0.2rem;
}

View file

@ -1 +0,0 @@

View file

@ -1,171 +0,0 @@
/* CSS for Paged.js interface v0.4 */
/* Change the look */
:root {
--color-background: whitesmoke;
--color-pageSheet: #cfcfcf;
--color-pageBox: violet;
--color-paper: white;
--color-marginBox: transparent;
--pagedjs-crop-color: black;
--pagedjs-crop-shadow: white;
--pagedjs-crop-stroke: 1px;
}
/* To define how the book look on the screen: */
@media screen, pagedjs-ignore {
body {
background-color: var(--color-background);
}
.pagedjs_pages {
display: flex;
width: calc(var(--pagedjs-width) * 2);
flex: 0;
flex-wrap: wrap;
margin: 0 auto;
}
.pagedjs_page {
background-color: var(--color-paper);
box-shadow: 0 0 0 1px var(--color-pageSheet);
margin: 0;
flex-shrink: 0;
flex-grow: 0;
margin-top: 10mm;
}
.pagedjs_first_page {
margin-left: var(--pagedjs-width);
}
.pagedjs_page:last-of-type {
margin-bottom: 10mm;
}
.pagedjs_pagebox {
box-shadow: 0 0 0 1px var(--color-pageBox);
}
.pagedjs_left_page {
z-index: 20;
width: calc(
var(--pagedjs-bleed-left) + var(--pagedjs-pagebox-width)
) !important;
}
.pagedjs_left_page .pagedjs_bleed-right .pagedjs_marks-crop {
border-color: transparent;
}
.pagedjs_left_page .pagedjs_bleed-right .pagedjs_marks-middle {
width: 0;
}
.pagedjs_right_page {
z-index: 10;
position: relative;
left: calc(var(--pagedjs-bleed-left) * -1);
}
/* show the margin-box */
.pagedjs_margin-top-left-corner-holder,
.pagedjs_margin-top,
.pagedjs_margin-top-left,
.pagedjs_margin-top-center,
.pagedjs_margin-top-right,
.pagedjs_margin-top-right-corner-holder,
.pagedjs_margin-bottom-left-corner-holder,
.pagedjs_margin-bottom,
.pagedjs_margin-bottom-left,
.pagedjs_margin-bottom-center,
.pagedjs_margin-bottom-right,
.pagedjs_margin-bottom-right-corner-holder,
.pagedjs_margin-right,
.pagedjs_margin-right-top,
.pagedjs_margin-right-middle,
.pagedjs_margin-right-bottom,
.pagedjs_margin-left,
.pagedjs_margin-left-top,
.pagedjs_margin-left-middle,
.pagedjs_margin-left-bottom {
box-shadow: 0 0 0 1px inset var(--color-marginBox);
}
/* uncomment this part for recto/verso book : ------------------------------------ */
/*
.pagedjs_pages {
flex-direction: column;
width: 100%;
}
.pagedjs_first_page {
margin-left: 0;
}
.pagedjs_page {
margin: 0 auto;
margin-top: 10mm;
}
.pagedjs_left_page{
width: calc(var(--pagedjs-bleed-left) + var(--pagedjs-pagebox-width) + var(--pagedjs-bleed-left))!important;
}
.pagedjs_left_page .pagedjs_bleed-right .pagedjs_marks-crop{
border-color: var(--pagedjs-crop-color);
}
.pagedjs_left_page .pagedjs_bleed-right .pagedjs_marks-middle{
width: var(--pagedjs-cross-size)!important;
}
.pagedjs_right_page{
left: 0;
}
*/
/*--------------------------------------------------------------------------------------*/
/* uncomment this par to see the baseline : -------------------------------------------*/
/* .pagedjs_pagebox {
--pagedjs-baseline: 22px;
--pagedjs-baseline-position: 5px;
--pagedjs-baseline-color: cyan;
background: linear-gradient(transparent 0%, transparent calc(var(--pagedjs-baseline) - 1px), var(--pagedjs-baseline-color) calc(var(--pagedjs-baseline) - 1px), var(--pagedjs-baseline-color) var(--pagedjs-baseline)), transparent;
background-size: 100% var(--pagedjs-baseline);
background-repeat: repeat-y;
background-position-y: var(--pagedjs-baseline-position);
} */
/*--------------------------------------------------------------------------------------*/
}
/* Marks (to delete when merge in paged.js) */
.pagedjs_marks-crop {
z-index: 999999999999;
}
.pagedjs_bleed-top .pagedjs_marks-crop,
.pagedjs_bleed-bottom .pagedjs_marks-crop {
box-shadow: 1px 0px 0px 0px var(--pagedjs-crop-shadow);
}
.pagedjs_bleed-top .pagedjs_marks-crop:last-child,
.pagedjs_bleed-bottom .pagedjs_marks-crop:last-child {
box-shadow: -1px 0px 0px 0px var(--pagedjs-crop-shadow);
}
.pagedjs_bleed-left .pagedjs_marks-crop,
.pagedjs_bleed-right .pagedjs_marks-crop {
box-shadow: 0px 1px 0px 0px var(--pagedjs-crop-shadow);
}
.pagedjs_bleed-left .pagedjs_marks-crop:last-child,
.pagedjs_bleed-right .pagedjs_marks-crop:last-child {
box-shadow: 0px -1px 0px 0px var(--pagedjs-crop-shadow);
}

View file

@ -1,24 +0,0 @@
@page {
size: A4;
margin: 20mm 15mm 26mm 15mm;
}
@page {
@bottom-center { content: string(title); }
}
h2 {
break-before: page;
}
.chapter > h2 {
string-set: title content(text);
}
#chapter-2 {
font-size: 2rem;
}
p {
font-size: 1rem;
}