the device toggle is three labelled tabs
Icons alone told three things apart by proportion at 12 pixels. Full width, one of three filled, and the word from DEVICES. The `size` prop is gone with the bar that needed the small one, and so is the second copy inside Spacing — the panel header scopes the whole editor now. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+22
-18
@@ -2,7 +2,7 @@ import { Monitor, Smartphone, Tablet } from 'lucide-react';
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useSearchParams } from 'react-router';
|
import { useSearchParams } from 'react-router';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import type { DeviceName } from './ViewMode';
|
import { DEVICES, type DeviceName } from './ViewMode';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Which width everything is showing, and the control for changing it.
|
* Which width everything is showing, and the control for changing it.
|
||||||
@@ -44,35 +44,39 @@ const OPTIONS: { value: DeviceName; Icon: typeof Monitor }[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The control itself, for an editor section that has per-view settings.
|
* The control itself: three tabs across the width of whatever holds it.
|
||||||
*
|
*
|
||||||
* `size` because the one in the panel's bar is chrome and these are part of a form: the bar's is as
|
* ── One shape, not two ──
|
||||||
* small as a bar allows, and a section's sits above its own fields and should read as belonging to
|
*
|
||||||
* them.
|
* There was a `size` prop. `bar` was a small icon-only cluster for the panel bar across the top of the
|
||||||
|
* detail panel, and that bar is gone — so what is left is the one shape, and a prop with a single
|
||||||
|
* value is a decision nobody makes.
|
||||||
|
*
|
||||||
|
* ── Labelled, and spread ──
|
||||||
|
*
|
||||||
|
* The icons alone were a rebus: a rectangle, a slightly narrower rectangle, and a narrower one still,
|
||||||
|
* telling three things apart by proportion at 12 pixels. They read as tabs now because they behave
|
||||||
|
* like tabs — one of three, the whole width, the chosen one filled — and the word is what makes the
|
||||||
|
* choice legible without hovering for a tooltip.
|
||||||
|
*
|
||||||
|
* The label comes from DEVICES, which is also what the preview names in its own caption. One list.
|
||||||
*/
|
*/
|
||||||
export const DeviceToggle = ({ size = 'bar' }: { size?: 'bar' | 'section' }) => {
|
export const DeviceToggle = () => {
|
||||||
const [device, setDevice] = useDevice();
|
const [device, setDevice] = useDevice();
|
||||||
const compact = size === 'bar';
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div className="flex w-full items-center rounded-md border border-border p-0.5">
|
||||||
// In a section it spans the width and spreads its three: it scopes everything below it, so it
|
|
||||||
// reads as a header for the group rather than a control sitting in a corner of one.
|
|
||||||
className={`flex items-center rounded-md border border-border p-0.5 ${
|
|
||||||
compact ? 'gap-0.5' : 'w-full justify-around'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{OPTIONS.map(({ value, Icon }) => (
|
{OPTIONS.map(({ value, Icon }) => (
|
||||||
<Button
|
<Button
|
||||||
key={value}
|
key={value}
|
||||||
size="sm"
|
size="sm"
|
||||||
variant={device === value ? 'secondary' : 'ghost'}
|
variant={device === value ? 'secondary' : 'ghost'}
|
||||||
className={compact ? 'h-5 gap-1 px-2 text-xs' : 'h-7 flex-1 text-xs'}
|
className="h-7 flex-1 gap-1.5 text-xs"
|
||||||
onClick={() => setDevice(value)}
|
onClick={() => setDevice(value)}
|
||||||
aria-label={value}
|
aria-label={DEVICES[value].label}
|
||||||
title={value}
|
|
||||||
>
|
>
|
||||||
<Icon className="size-3" />
|
<Icon className="size-3.5" />
|
||||||
|
{DEVICES[value].label}
|
||||||
</Button>
|
</Button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+2
-2
@@ -32,8 +32,8 @@ export const EditorPanel = () => {
|
|||||||
return (
|
return (
|
||||||
<div className="flex size-full flex-col overflow-hidden">
|
<div className="flex size-full flex-col overflow-hidden">
|
||||||
{/* Outside the scroll area, so a long editor cannot carry it off the screen. */}
|
{/* Outside the scroll area, so a long editor cannot carry it off the screen. */}
|
||||||
<div className="flex shrink-0 justify-center border-b border-border px-3 py-2">
|
<div className="shrink-0 border-b border-border px-3 py-2">
|
||||||
<DeviceToggle size="bar" />
|
<DeviceToggle />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{editor ? (
|
{editor ? (
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import { useAutosave } from '../useAutosave';
|
|||||||
import { usePreviewable, useViewMode } from '../ViewMode';
|
import { usePreviewable, useViewMode } from '../ViewMode';
|
||||||
import { applySpacing, paintMeasure, type SpacingDraft } from '../canvas';
|
import { applySpacing, paintMeasure, type SpacingDraft } from '../canvas';
|
||||||
import { SitePreview, useDevPort } from '../SitePreview';
|
import { SitePreview, useDevPort } from '../SitePreview';
|
||||||
import { DeviceToggle } from '../DeviceToggle';
|
|
||||||
import { useEditorSlot } from '../useEditorSlot';
|
import { useEditorSlot } from '../useEditorSlot';
|
||||||
import { type LayoutBand } from './PaddingTab';
|
import { type LayoutBand } from './PaddingTab';
|
||||||
import { SpacingTab } from './SpacingTab';
|
import { SpacingTab } from './SpacingTab';
|
||||||
@@ -348,10 +347,6 @@ export const LayoutPanel = () => {
|
|||||||
<AccordionItem value="padding" className="rounded-lg border border-border px-4">
|
<AccordionItem value="padding" className="rounded-lg border border-border px-4">
|
||||||
<AccordionTrigger className="text-xs">Spacing</AccordionTrigger>
|
<AccordionTrigger className="text-xs">Spacing</AccordionTrigger>
|
||||||
<AccordionContent>
|
<AccordionContent>
|
||||||
{/* The width these settings are for. Reads `?device=`, so it moves the preview too. */}
|
|
||||||
<div className="mb-3">
|
|
||||||
<DeviceToggle size="section" />
|
|
||||||
</div>
|
|
||||||
{/* Three bands. PaddingTab is still the per-SECTION control, for the pages. */}
|
{/* Three bands. PaddingTab is still the per-SECTION control, for the pages. */}
|
||||||
<SpacingTab
|
<SpacingTab
|
||||||
spacing={draft.spacing}
|
spacing={draft.spacing}
|
||||||
|
|||||||
Reference in New Issue
Block a user