()
| 43 | } |
| 44 | |
| 45 | const ToolSettingsSidebar = () => { |
| 46 | const selectedTool = useStateStore((state) => state.selectedTool); |
| 47 | |
| 48 | const isPropTool = isPropertyTool(selectedTool); |
| 49 | |
| 50 | const toolProperties = useToolPropertiesStore((state) => |
| 51 | isPropTool ? state.properties[selectedTool] : undefined |
| 52 | ); |
| 53 | |
| 54 | const updateProperties = useToolPropertiesStore( |
| 55 | (state) => state.updateProperties |
| 56 | ); |
| 57 | |
| 58 | if (!isPropTool || !toolProperties) { |
| 59 | return null; |
| 60 | } |
| 61 | |
| 62 | const toolKey: ToolKey = selectedTool; |
| 63 | const rectangleProps: RectangleProperties | null = |
| 64 | toolKey === "rectangle" ? (toolProperties as RectangleProperties) : null; |
| 65 | |
| 66 | return ( |
| 67 | <aside className="fixed left-5 top-1/2 -translate-y-1/2 z-50 select-none"> |
| 68 | <div className="bg-white rounded-xl shadow-lg border border-gray-200 p-3 flex flex-col items-start gap-3"> |
| 69 | {"stroke" in toolProperties && ( |
| 70 | <section className="flex flex-col gap-3"> |
| 71 | <span className="text-xs font-semibold text-gray-500 uppercase tracking-wider"> |
| 72 | Stroke |
| 73 | </span> |
| 74 | <div className="flex flex-wrap gap-2"> |
| 75 | {strokes.map((color) => ( |
| 76 | <button |
| 77 | key={color} |
| 78 | type="button" |
| 79 | className={`size-8 rounded-full border border-gray-200 hover:scale-110 transition-all cursor-pointer ${ |
| 80 | toolProperties.stroke === color |
| 81 | ? "ring-2 ring-offset-2 ring-gray-900 border-transparent" |
| 82 | : "" |
| 83 | }`} |
| 84 | style={{ backgroundColor: color }} |
| 85 | aria-label={`Set stroke color to ${color}`} |
| 86 | onClick={() => updateProperties(toolKey, { stroke: color })} |
| 87 | /> |
| 88 | ))} |
| 89 | </div> |
| 90 | </section> |
| 91 | )} |
| 92 | |
| 93 | {"fill" in toolProperties && ( |
| 94 | <section className="flex flex-col gap-3"> |
| 95 | <span className="text-xs font-semibold text-gray-500 uppercase tracking-wider"> |
| 96 | Background |
| 97 | </span> |
| 98 | <div className="flex flex-wrap gap-2"> |
| 99 | {backgroundColors.map((color) => ( |
| 100 | <button |
| 101 | key={color} |
| 102 | type="button" |
nothing calls this directly
no test coverage detected