feat: enhance bottom controls and UI components
- Updated BottomControlsIsland for improved layout and styling. - Refactored LayersSheet to enhance usability and visual consistency. - Modified ToolOverlay for better tool selection experience. - Improved BrushControls with new ColorPicker and Slider components. - Enhanced PanControls and TransformControls for better user interaction. - Updated ZoomControls for consistent button sizes and styles. - Introduced new styles for bottom controls in styles.ts and index.css. - Added BottomControlColorPicker, BottomControlSelectMenu, and BottomControlSlider components for better modularity and reusability.
This commit is contained in:
@@ -1,9 +1,13 @@
|
||||
import { Eraser, PaintBrush } from "@phosphor-icons/react";
|
||||
import { commandIds } from "@commands/ids";
|
||||
import type { AppStore } from "@editor/store";
|
||||
import type { MaskViewMode } from "@editor/state";
|
||||
import type { BrushSettings, ToolId } from "@editor/tools";
|
||||
import { BottomControlColorPicker } from "./ColorPicker";
|
||||
import { BottomControlDivider } from "./Divider";
|
||||
import { bottomControlLabelClass } from "./styles";
|
||||
import { BottomControlSelectMenu, type BottomControlSelectOption } from "./SelectMenu";
|
||||
import { BottomControlSlider } from "./Slider";
|
||||
import { bottomControlFieldClass, bottomControlIconSlotClass, bottomControlLabelClass, bottomControlMenuClass } from "./styles";
|
||||
|
||||
export type BrushControlsProps = {
|
||||
tool: Extract<ToolId, "brush" | "eraser">;
|
||||
@@ -13,71 +17,71 @@ export type BrushControlsProps = {
|
||||
dispatch: AppStore["dispatch"];
|
||||
};
|
||||
|
||||
const maskViewModeOptions = [
|
||||
{ value: "composite", label: "Image" },
|
||||
{ value: "blackWhite", label: "B/W" },
|
||||
{ value: "alpha", label: "Alpha" },
|
||||
{ value: "overlay", label: "Overlay" },
|
||||
] satisfies readonly BottomControlSelectOption<MaskViewMode>[];
|
||||
|
||||
export function BrushControls({ tool, settings, editingMask = false, maskViewMode = "composite", dispatch }: BrushControlsProps) {
|
||||
return (
|
||||
<div className="flex w-full items-center justify-center gap-2 tabular-nums">
|
||||
<span className="px-2 font-medium text-white/85">{editingMask ? `Mask · ${tool === "eraser" ? "Hide" : "Reveal"}` : tool === "eraser" ? "Eraser" : "Brush"}</span>
|
||||
<div className={bottomControlMenuClass()}>
|
||||
<span className={bottomControlIconSlotClass()} title={editingMask ? `Mask ${tool === "eraser" ? "hide" : "reveal"}` : tool === "eraser" ? "Eraser" : "Brush"}>
|
||||
{tool === "eraser" ? <Eraser size={24} weight="regular" /> : <PaintBrush size={24} weight="regular" />}
|
||||
</span>
|
||||
<BottomControlDivider />
|
||||
{tool === "brush" && !editingMask ? (
|
||||
<label className="flex items-center gap-1.5">
|
||||
<label className={bottomControlFieldClass()}>
|
||||
<span className={bottomControlLabelClass()}>Color</span>
|
||||
<input
|
||||
type="color"
|
||||
className="h-7 w-8 cursor-pointer rounded border-0 bg-transparent p-0"
|
||||
<BottomControlColorPicker
|
||||
value={settings.color}
|
||||
aria-label="Brush color"
|
||||
onChange={(event) => dispatch(commandIds.toolSetBrushSettings, { color: event.target.value })}
|
||||
onValueChange={(color) => dispatch(commandIds.toolSetBrushSettings, { color })}
|
||||
/>
|
||||
</label>
|
||||
) : null}
|
||||
<label className="flex items-center gap-1.5">
|
||||
<label className={bottomControlFieldClass()}>
|
||||
<span className={bottomControlLabelClass()}>Size</span>
|
||||
<input
|
||||
type="range"
|
||||
<BottomControlSlider
|
||||
min={1}
|
||||
max={200}
|
||||
value={settings.size}
|
||||
className="w-24 accent-white"
|
||||
className="w-48"
|
||||
aria-label={`${tool} size`}
|
||||
onChange={(event) => dispatch(commandIds.toolSetBrushSettings, { size: Number(event.target.value) })}
|
||||
onValueChange={(size) => dispatch(commandIds.toolSetBrushSettings, { size })}
|
||||
/>
|
||||
<span className="w-8 text-right text-white">{Math.round(settings.size)}</span>
|
||||
<span className="w-12 text-right text-base text-white">{Math.round(settings.size)}</span>
|
||||
</label>
|
||||
<BottomControlDivider />
|
||||
<label className="flex items-center gap-1.5">
|
||||
<label className={bottomControlFieldClass()}>
|
||||
<span className={bottomControlLabelClass()}>Hard</span>
|
||||
<input
|
||||
type="range"
|
||||
<BottomControlSlider
|
||||
min={0}
|
||||
max={100}
|
||||
value={settings.hardness}
|
||||
className="w-24 accent-white"
|
||||
className="w-48"
|
||||
aria-label={`${tool} hardness`}
|
||||
onChange={(event) => dispatch(commandIds.toolSetBrushSettings, { hardness: Number(event.target.value) })}
|
||||
onValueChange={(hardness) => dispatch(commandIds.toolSetBrushSettings, { hardness })}
|
||||
/>
|
||||
<span className="w-8 text-right text-white">{Math.round(settings.hardness)}</span>
|
||||
<span className="w-12 text-right text-base text-white">{Math.round(settings.hardness)}</span>
|
||||
</label>
|
||||
{editingMask ? (
|
||||
<>
|
||||
<BottomControlDivider />
|
||||
<label className="flex items-center gap-1.5">
|
||||
<label className={bottomControlFieldClass()}>
|
||||
<span className={bottomControlLabelClass()}>View</span>
|
||||
<select
|
||||
className="h-7 rounded-full border border-white/10 bg-black/70 px-2 text-white outline-none"
|
||||
<BottomControlSelectMenu
|
||||
value={maskViewMode}
|
||||
options={maskViewModeOptions}
|
||||
aria-label="Mask view mode"
|
||||
onChange={(event) => dispatch(commandIds.toolSetMaskViewMode, { mode: event.target.value as MaskViewMode })}
|
||||
>
|
||||
<option value="composite">Image</option>
|
||||
<option value="blackWhite">B/W</option>
|
||||
<option value="alpha">Alpha</option>
|
||||
<option value="overlay">Overlay</option>
|
||||
</select>
|
||||
onValueChange={(mode) => dispatch(commandIds.toolSetMaskViewMode, { mode })}
|
||||
/>
|
||||
</label>
|
||||
<BottomControlDivider />
|
||||
<button
|
||||
type="button"
|
||||
className="rounded-full bg-white px-3 py-1 font-medium text-black transition hover:bg-white/90"
|
||||
className="rounded-full bg-white px-5 py-2 text-base font-medium text-black transition hover:bg-white/90"
|
||||
onClick={() => dispatch(commandIds.toolExitMaskEdit, undefined)}
|
||||
>
|
||||
Done
|
||||
|
||||
Reference in New Issue
Block a user