the empty size option names the size
"Inherit (default)" answers a question nobody asked. What somebody wants from that dropdown is what it is now — and a label that will not say makes them change the setting to find out, which is the one way to lose the answer. It reads Default (4xl) at the smallest width and Inherit (2xl) above it. The stylesheet's own sizes come from the API, which reads them out of styles.css. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -13,8 +13,16 @@ import { ROLES } from './roles';
|
|||||||
* ── One value per field ──
|
* ── One value per field ──
|
||||||
*
|
*
|
||||||
* The tabs at the top of the panel say which width. Unset inherits the smaller one, so "the same
|
* The tabs at the top of the panel say which width. Unset inherits the smaller one, so "the same
|
||||||
* everywhere" is one choice; the option names what it is inheriting rather than leaving it to be
|
* everywhere" is one choice.
|
||||||
* worked out.
|
*
|
||||||
|
* ── The empty option NAMES the size ──
|
||||||
|
*
|
||||||
|
* It said "Inherit (default)", which answers a question nobody asked. What somebody wants from that
|
||||||
|
* dropdown is "what is it now", and a label that does not say makes them change the setting to find
|
||||||
|
* out — which is the one way to lose the answer.
|
||||||
|
*
|
||||||
|
* So it names the size that will actually apply: the nearest smaller width that has one, or the
|
||||||
|
* stylesheet's own, which the API reads out of styles.css rather than this file guessing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export type FontSizes = Partial<Record<'title' | 'body' | 'sub' | 'display', Partial<Record<'base' | 'md' | 'lg', string>>>>;
|
export type FontSizes = Partial<Record<'title' | 'body' | 'sub' | 'display', Partial<Record<'base' | 'md' | 'lg', string>>>>;
|
||||||
@@ -36,11 +44,14 @@ const inherited = (
|
|||||||
export const FontSizesTab = ({
|
export const FontSizesTab = ({
|
||||||
sizes,
|
sizes,
|
||||||
steps,
|
steps,
|
||||||
|
defaults,
|
||||||
onChange,
|
onChange,
|
||||||
}: {
|
}: {
|
||||||
sizes: FontSizes;
|
sizes: FontSizes;
|
||||||
/** The scale, sent by the API so this file holds no copy of it. */
|
/** The scale, sent by the API so this file holds no copy of it. */
|
||||||
steps: string[];
|
steps: string[];
|
||||||
|
/** What each role is with nothing chosen, read from the site's stylesheet. */
|
||||||
|
defaults: Record<string, string>;
|
||||||
onChange: (sizes: FontSizes) => void;
|
onChange: (sizes: FontSizes) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const [device] = useDevice();
|
const [device] = useDevice();
|
||||||
@@ -64,7 +75,8 @@ export const FontSizesTab = ({
|
|||||||
{ROLES.map((role) => {
|
{ROLES.map((role) => {
|
||||||
const current = sizes[role.size];
|
const current = sizes[role.size];
|
||||||
const own = current?.[key];
|
const own = current?.[key];
|
||||||
const from = inherited(current, key);
|
// The nearest smaller width that has one, or the stylesheet's. Either way, a size to read.
|
||||||
|
const from = inherited(current, key) ?? defaults[role.size];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={role.size} className="flex flex-col gap-1">
|
<div key={role.size} className="flex flex-col gap-1">
|
||||||
@@ -74,10 +86,10 @@ export const FontSizesTab = ({
|
|||||||
onChange={(event) => set(role.size, event.currentTarget.value)}
|
onChange={(event) => set(role.size, event.currentTarget.value)}
|
||||||
className="h-8 rounded-md border border-input bg-transparent px-2 text-xs"
|
className="h-8 rounded-md border border-input bg-transparent px-2 text-xs"
|
||||||
>
|
>
|
||||||
{/* Mobile is the smallest, so there is nothing below it to inherit from — and nothing
|
{/* Mobile is the smallest, so nothing below it: what it falls back to is the
|
||||||
chosen there means the stylesheet's own size. */}
|
stylesheet's own size rather than another breakpoint's. */}
|
||||||
<option value="">
|
<option value="">
|
||||||
{key === 'base' ? 'Default' : from === null ? 'Inherit (default)' : `Inherit (${from})`}
|
{from ? `${key === 'base' ? 'Default' : 'Inherit'} (${from})` : 'Default'}
|
||||||
</option>
|
</option>
|
||||||
{steps.map((step) => (
|
{steps.map((step) => (
|
||||||
<option key={step} value={step}>
|
<option key={step} value={step}>
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ type Layout = {
|
|||||||
font_sizes: FontSizes;
|
font_sizes: FontSizes;
|
||||||
/** The type scale, sent by the API so this file holds no copy of it. */
|
/** The type scale, sent by the API so this file holds no copy of it. */
|
||||||
text_steps: string[];
|
text_steps: string[];
|
||||||
|
/** What each role is with nothing chosen, read from the site's stylesheet. */
|
||||||
|
size_defaults: Record<string, string>;
|
||||||
/** Each step's length, so the live preview can build the same CSS the site would. */
|
/** Each step's length, so the live preview can build the same CSS the site would. */
|
||||||
text_sizes: Record<string, string>;
|
text_sizes: Record<string, string>;
|
||||||
/**
|
/**
|
||||||
@@ -390,6 +392,7 @@ export const LayoutPanel = () => {
|
|||||||
<FontSizesTab
|
<FontSizesTab
|
||||||
sizes={draft.font_sizes}
|
sizes={draft.font_sizes}
|
||||||
steps={draft.text_steps}
|
steps={draft.text_steps}
|
||||||
|
defaults={draft.size_defaults}
|
||||||
onChange={(font_sizes) => patch({ font_sizes })}
|
onChange={(font_sizes) => patch({ font_sizes })}
|
||||||
/>
|
/>
|
||||||
</AccordionContent>
|
</AccordionContent>
|
||||||
|
|||||||
Reference in New Issue
Block a user