Files
RecipesCam/docker/frontend/src/ui/ToolRail.tsx
T
3dtours f13fc37b5a feat(panel): cascading columns, WB colour swatches, stronger HDF glow
Layout
- the panel is a cascade of columns: the rail's tabs, the tab's chips, the
  open chip's sub-chips, then the ruler. A child column no longer hides the
  column it came from (TEMP -> COLOR TEMP keeps TEMP visible); chips stack one
  per row instead of wrapping
- FRAME's WATERMARK opens its own column, so the frame chips stay put
- CREATE RECIPES gets the wide column its two-up form needs

WB colour swatches
- the ruler draws a colour box under the slider that follows the value:
  COLOR TEMP is the Kelvin colour (Tanner Helland), TINT runs green -10 ->
  neutral 0 -> magenta +10

HDF EFFECT
- knee 0.55..0.85 -> 0.45..0.75, blur 0.004+0.015n -> 0.006+0.024n of the
  width, screen alpha 0.15+0.35n -> 0.28+0.52n: a wide halo on the highlights
  instead of a hairline glow. Web copy of toneShader only — the phone keeps
  its own tuning.

Tabs
- rail order is PRESETS, FAVORITED, WB, LIGHT, FX, FRAME, CREATE RECIPES
2026-09-18 06:42:38 +07:00

38 lines
1.4 KiB
TypeScript

import type { MsgKey } from '../i18n/vi';
import { useI18n } from '../i18n/I18nProvider';
// The app's seven tabs. WB leads LIGHT — white balance is the first thing the
// eye corrects, and the web rail draws them in the order the panel opens. The
// rail is a single column on desktop and becomes the bottom bar under 860px
// (see styles/app.css).
export type TabId = 'presets' | 'favorited' | 'wb' | 'light' | 'fx' | 'frame' | 'create';
export const TABS: { id: TabId; label: MsgKey; glyph: string }[] = [
{ id: 'presets', label: 'tab.presets', glyph: '◉' },
{ id: 'favorited', label: 'tab.favorited', glyph: '★' },
{ id: 'wb', label: 'tab.wb', glyph: '◐' },
{ id: 'light', label: 'tab.light', glyph: '☀' },
{ id: 'fx', label: 'tab.fx', glyph: '✦' },
{ id: 'frame', label: 'tab.frame', glyph: '▣' },
{ id: 'create', label: 'tab.create', glyph: '✎' },
];
export function ToolRail({ tab, onTab }: { tab: TabId; onTab: (tab: TabId) => void }) {
const { t } = useI18n();
return (
<nav className="rail" aria-label="tool tabs">
{TABS.map((entry) => (
<button
key={entry.id}
type="button"
aria-pressed={tab === entry.id}
onClick={() => onTab(entry.id)}
>
<span className="glyph" aria-hidden="true">{entry.glyph}</span>
{t(entry.label)}
</button>
))}
</nav>
);
}