feat: shortcut from node Appearance to canvas-wide type style

Adds a link under the colour swatches in the add/edit node modal that opens the
Custom Style editor with the node's type preselected, so a user can edit the
style for every node of that type without navigating Style -> Customize -> pick
type manually.

- CustomStyleModal: new optional `initialNodeType` prop; when set, the modal
  opens straight into that node type's editor instead of the empty placeholder.
- NodeModal: new optional `onEditTypeStyle(type)` prop renders the shortcut link
  (hidden for group/groupRect and when no handler is wired).
- App: `styleEditorType` state; both Add and Edit NodeModals forward the handler,
  and a standalone CustomStyleModal instance opens preselected (stacked over the
  node modal so in-progress node edits are preserved).

ha-relevant: yes
This commit is contained in:
Pouzor
2026-07-04 15:14:33 +02:00
parent e39ab7d530
commit e8530ad3db
5 changed files with 58 additions and 5 deletions
@@ -300,9 +300,11 @@ type Selection = { kind: 'node'; type: NodeType } | { kind: 'edge'; type: EdgeTy
interface CustomStyleModalProps {
open: boolean
onClose: () => void
/** When opening, preselect this node type's editor (shortcut from NodeModal). */
initialNodeType?: NodeType
}
export function CustomStyleModal({ open, onClose }: CustomStyleModalProps) {
export function CustomStyleModal({ open, onClose, initialNodeType }: CustomStyleModalProps) {
const { customStyle, setCustomStyle } = useThemeStore()
const { markUnsaved, applyTypeNodeStyle, applyTypeEdgeStyle, applyAllCustomStyles } = useCanvasStore()
@@ -320,7 +322,12 @@ export function CustomStyleModal({ open, onClose }: CustomStyleModalProps) {
useEffect(() => {
if (open) {
setDraft({ nodes: { ...customStyle.nodes }, edges: { ...customStyle.edges } })
setSelection(null)
if (initialNodeType) {
setTab('nodes')
setSelection({ kind: 'node', type: initialNodeType })
} else {
setSelection(null)
}
}
// Intentional snapshot-on-open: we don't want live customStyle changes to
// clobber an in-progress edit, only a fresh open should reset.