Fix styling

This commit is contained in:
Jeremy Thomas 2024-06-27 01:26:39 +01:00
parent bb62f531e1
commit 762926d492
7 changed files with 131 additions and 157 deletions

View File

@ -7,16 +7,6 @@
<title>Vite + React</title> <title>Vite + React</title>
<style type="text/css"> <style type="text/css">
#bulma-customizer-app { #bulma-customizer-app {
background: var(--bulma-body-background-color);
border-radius: 0.5rem;
border: 1px solid var(--bulma-border);
bottom: 1rem;
overflow: auto;
position: fixed;
right: 1rem;
top: 1rem;
width: 33rem;
z-index: 100;
} }
</style> </style>
</head> </head>
@ -42,7 +32,7 @@
<table class="table"></table> <table class="table"></table>
<div class="tag"></div> <div class="tag"></div>
<div class="title"></div> <div class="title"></div>
<input class="input"> <input class="input" />
<div class="file"></div> <div class="file"></div>
<div class="columns"></div> <div class="columns"></div>
<div class="grid"></div> <div class="grid"></div>

View File

@ -413,8 +413,8 @@ function App() {
"--bulma-tabs-link-active-color": "var(--bulma-primary)", "--bulma-tabs-link-active-color": "var(--bulma-primary)",
}; };
const appClass = classNames({ const customizerClass = classNames({
[cn.app]: true, [cn.customizer]: true,
[cn.open]: context.isOpen, [cn.open]: context.isOpen,
}); });
@ -425,46 +425,48 @@ function App() {
return ( return (
<CustomizerContext.Provider value={context}> <CustomizerContext.Provider value={context}>
<style ref={styleRef} /> <div className={cn.app}>
<style ref={styleRef} />
<div className={appClass}> <div className={customizerClass}>
<div className={cn.controls}> <div className={cn.controls}>
<div className="select" style={tabsStyle}> <div className="select" style={tabsStyle}>
<select onChange={handleTabChange} value={context.currentTab}> <select onChange={handleTabChange} value={context.currentTab}>
{TAB_IDS.map((tabId) => { {TAB_IDS.map((tabId) => {
return ( return (
<option key={tabId} value={tabId}> <option key={tabId} value={tabId}>
<a>{unslug(tabId)}</a> {unslug(tabId)}
</option> </option>
); );
})} })}
</select> </select>
</div>
{PAGE_IDS[context.currentTab].map((pageId) => {
const buttonClass = classNames({
button: true,
"is-primary": pageId === context.currentPage,
});
return (
<button
className={buttonClass}
key={pageId}
onClick={(e) => handlePageChange(e, pageId)}
>
{unslug(pageId)}
</button>
);
})}
</div> </div>
{PAGE_IDS[context.currentTab].map((pageId) => { {PAGE_TO_COMPONENT[context.currentPage]}
const buttonClass = classNames({
button: true,
"is-primary": pageId === context.currentPage,
});
return (
<button
className={buttonClass}
key={pageId}
onClick={(e) => handlePageChange(e, pageId)}
>
{unslug(pageId)}
</button>
);
})}
</div> </div>
{PAGE_TO_COMPONENT[context.currentPage]} <button className={buttonClass} onClick={handleOpening}>
{context.isOpen ? "Close Customizer" : "Open Customizer"}
</button>
</div> </div>
<button className={buttonClass} onClick={handleOpening}>
{context.isOpen ? "Close Customizer" : "Open Customizer"}
</button>
</CustomizerContext.Provider> </CustomizerContext.Provider>
); );
} }

View File

@ -3,15 +3,31 @@
--var-item-slider-width: 30rem; --var-item-slider-width: 30rem;
--var-item-padding: 1rem; --var-item-padding: 1rem;
--var-item-gap: 1rem; --var-item-gap: 1rem;
bottom: 1rem;
overflow: auto;
position: fixed;
right: 1rem;
top: 1rem;
width: 33rem;
z-index: 100;
}
.customizer {
background: var(--bulma-background);
border-radius: 0.5rem;
transform-origin: bottom right; transform-origin: bottom right;
transition-duration: 300ms; transition-duration: 300ms;
transition-property: opacity, transform; transition-property: opacity, transform;
transform: scale(0.9); transform: scale(0.98) translate(2px, 2px);
margin-bottom: 4rem;
opacity: 0; opacity: 0;
pointer-events: none;
min-height: 100%;
} }
.open { .open {
opacity: 1; opacity: 1;
pointer-events: auto;
transform: none; transform: none;
} }
@ -19,11 +35,11 @@
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 0.5rem; gap: 0.5rem;
padding: 1.5rem; padding: 0.5rem;
} }
.button { .button {
bottom: 1rem; bottom: 1.5rem;
right: 1rem; right: 1.5rem;
position: fixed; position: fixed;
} }

View File

@ -1,4 +1,4 @@
import { useContext, useEffect, useState } from "react"; import { useContext } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import Slider from "./Slider"; import Slider from "./Slider";
@ -7,7 +7,7 @@ import cn from "./Color.module.css";
import { CustomizerContext } from "../App"; import { CustomizerContext } from "../App";
import classNames from "classnames"; import classNames from "classnames";
function hslToHex(h, s, l) { export function hslToHex(h, s, l) {
s /= 100; s /= 100;
l /= 100; l /= 100;
@ -102,7 +102,6 @@ function hexToHsl(hex) {
function Color({ color }) { function Color({ color }) {
const { cssvars, updateVar } = useContext(CustomizerContext); const { cssvars, updateVar } = useContext(CustomizerContext);
const [hexValue, setHexValue] = useState("");
const hName = `${color}-h`; const hName = `${color}-h`;
const sName = `${color}-s`; const sName = `${color}-s`;
@ -152,42 +151,11 @@ function Color({ color }) {
updateVar(l.id, lightness); updateVar(l.id, lightness);
}; };
const handleHexChange = (event) => {
let value = event.target.value;
if (value.startsWith("#")) {
value = value.replace(/^#/, "");
}
setHexValue(value);
const hexPattern = /^([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6})$/;
if (!hexPattern.test(value) || value.length < 6) {
return;
}
const { hue, saturation, lightness } = hexToHsl(value);
updateVar(h.id, hue);
updateVar(s.id, saturation);
updateVar(l.id, lightness);
};
const handleInputChange = (event, cssvar) => { const handleInputChange = (event, cssvar) => {
let value = event.target.value; let value = event.target.value;
updateVar(cssvar.id, value); updateVar(cssvar.id, value);
}; };
useEffect(() => {
if (!h) {
return;
}
const hex = hslToHex(h.current, s.current, l.current);
setHexValue(hex);
}, [h, s, l]);
if (!h) { if (!h) {
return; return;
} }
@ -205,12 +173,7 @@ function Color({ color }) {
return ( return (
<div className={cn.main} style={mainStyle}> <div className={cn.main} style={mainStyle}>
<div className={cn.side}> <div className={cn.side}>
<div className={cn.name}> <div className="buttons are-small is-float-right ml-2">
<div className={cn.swatch} />
<p>{name}</p>
</div>
<div className="buttons are-small">
<button className="button" onClick={handleHexInput}> <button className="button" onClick={handleHexInput}>
Enter a Hex code Enter a Hex code
</button> </button>
@ -225,72 +188,66 @@ function Color({ color }) {
</button> </button>
</div> </div>
<div className="is-hidden field has-addons"> <div className={cn.name}>
<p className="control"> <div className={cn.swatch} />
<span className="button is-static">#</span> <p>{name}</p>
</p>
<p className="control">
<input
className="input"
type="text"
value={hexValue}
onChange={handleHexChange}
/>
</p>
<p className="control">
<span className="button is-icon">Copy</span>
</p>
</div> </div>
</div> </div>
<div className={cn.lines}> <div className={cn.lines}>
<div className={cn.line}> <div className={cn.line}>
<p>Hue</p> <p className={cn.label}>Hue</p>
<Slider id={hName} kind="hue" color={color} /> <div className={cn.slider}>
<p className={cn.form}> <Slider id={hName} kind="hue" color={color} />
<input <p className={cn.form}>
type="text" <input
className="input" type="text"
value={Number(h.current)} className="input"
onChange={(e) => handleInputChange(e, h)} value={Number(h.current)}
size="3" onChange={(e) => handleInputChange(e, h)}
/> size="3"
<span>{h.unit}</span> />
</p> <span>{h.unit}</span>
</p>
</div>
</div> </div>
<div className={cn.line}> <div className={cn.line}>
<p>Saturation</p> <p className={cn.label}>Saturation</p>
<Slider id={sName} kind="saturation" color={color} /> <div className={cn.slider}>
<p className={cn.form}> <Slider id={sName} kind="saturation" color={color} />
<input <p className={cn.form}>
type="text" <input
className="input" type="text"
value={Number(s.current)} className="input"
onChange={(e) => handleInputChange(e, s)} value={Number(s.current)}
size="3" onChange={(e) => handleInputChange(e, s)}
/> size="3"
<span>{s.unit}</span> />
</p> <span>{s.unit}</span>
</p>
</div>
</div> </div>
<div className={cn.line}> <div className={cn.line}>
<p>Lightness</p> <p className={cn.label}>Lightness</p>
<Slider id={lName} kind="lightness" color={color} /> <div className={cn.slider}>
<p className={cn.form}> <Slider id={lName} kind="lightness" color={color} />
<input <p className={cn.form}>
type="text" <input
className="input" type="text"
value={Number(l.current)} className="input"
onChange={(e) => handleInputChange(e, l)} value={Number(l.current)}
size="3" onChange={(e) => handleInputChange(e, l)}
/> size="3"
<span>{l.unit}</span> />
</p> <span>{l.unit}</span>
</p>
</div>
</div> </div>
</div> </div>
<div className={cn.side}> <div className={cn.example}>
<button className={`button is-${color}`}>{name}</button> <button className={`button is-${color}`}>{name}</button>
</div> </div>
</div> </div>

View File

@ -1,17 +1,9 @@
.main { .main {
background-color: var(--bulma-body-background-color); border-top: 1px solid var(--bulma-border);
display: flex;
flex-wrap: wrap;
gap: var(--var-item-gap);
box-shadow: 0 0 0 1px var(--bulma-border);
padding: var(--var-item-padding); padding: var(--var-item-padding);
justify-content: center; justify-content: center;
} }
.side {
width: 15rem;
}
.swatch { .swatch {
background-color: hsl(var(--h) var(--s) var(--l)); background-color: hsl(var(--h) var(--s) var(--l));
height: 1.25rem; height: 1.25rem;
@ -42,13 +34,23 @@
.line { .line {
display: flex; display: flex;
flex-wrap: wrap;
align-items: center; align-items: center;
gap: 1.5rem; gap: 0 1.5rem;
} }
.line p { .line p {
color: var(--bulma-text-strong); color: var(--bulma-text-strong);
width: 6rem; }
.label {
width: 100%;
}
.slider {
display: flex;
align-items: center;
gap: 0 1.5rem;
} }
.form { .form {
@ -56,6 +58,7 @@
align-items: center; align-items: center;
font-family: var(--bulma-family-code); font-family: var(--bulma-family-code);
gap: 0.25em; gap: 0.25em;
width: 6rem;
} }
.form input { .form input {
@ -71,3 +74,7 @@
.form span { .form span {
opacity: 0.5; opacity: 0.5;
} }
.example {
margin-top: 0.5rem;
}

View File

@ -67,11 +67,14 @@ function Slider({ id, color }) {
// }, [current, id, start, unit]); // }, [current, id, start, unit]);
useEffect(() => { useEffect(() => {
if (!isMoving) {
return;
}
const slider = sliderRef.current; const slider = sliderRef.current;
const sliderRect = slider.getBoundingClientRect(); const sliderRect = slider.getBoundingClientRect();
const final = xToValue(x, sliderRect.width, min, max); const final = xToValue(x, sliderRect.width, min, max);
updateVar(id, final); updateVar(id, final);
}, [id, min, max, updateVar, x]); }, [id, isMoving, min, max, updateVar, x]);
useEffect(() => { useEffect(() => {
const newX = valueToX(current, 360, min, max); const newX = valueToX(current, 360, min, max);

View File

@ -1,7 +1,6 @@
.main { .main {
background-color: var(--bulma-body-background-color);
gap: var(--var-item-gap); gap: var(--var-item-gap);
box-shadow: 0 0 0 1px var(--bulma-border); border-top: 1px solid var(--bulma-border);
padding: var(--var-item-padding); padding: var(--var-item-padding);
transition-property: background-color; transition-property: background-color;
transition-duration: var(--bulma-duration); transition-duration: var(--bulma-duration);