Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Add defaultStyling.json support for persistent per-type vertex and edge styling#1589

Open
jkemmererupgrade wants to merge 7 commits into
aws:mainfrom
jkemmererupgrade:feature/default-styling-1265
Open

Add defaultStyling.json support for persistent per-type vertex and edge styling#1589
jkemmererupgrade wants to merge 7 commits into
aws:mainfrom
jkemmererupgrade:feature/default-styling-1265

Conversation

@jkemmererupgrade
Copy link
Copy Markdown

Description

Add support for a defaultStyling.json file that provides persistent per-type vertex and edge styling defaults. When mounted into the Docker container, the file's values are merged into the user styling
store on startup, giving teams a consistent visual baseline across non-persistent browser sessions (e.g., AWS WorkSpaces Web).

Key capabilities:

  • Docker mount: Place a defaultStyling.json at the configuration folder path to auto-apply styling on load
  • Lucide icon support: Reference icons by name (e.g., "icon": "user") — resolved to SVG data URIs at runtime
  • Import / Export / Reset UI: New controls in Settings to import a styling file, export current styling, and reset all styling to defaults
  • Per-type Reset to Default: Each node/edge type's style dialog has a "Reset to Default" button that restores the mounted file's values
  • Zod validation: Strict schema validation with clear error logging for malformed files

Validation

  • All 1365 tests pass (pnpm test)
  • pnpm checks passes (lint, format, types)
  • Docker tested with mounted defaultStyling.json — styling applied on startup, import/export/reset all functional
  • Incognito window testing confirmed clean-state behavior
  • New unit tests cover: Zod parsing, icon resolution, import/export hooks, merge logic, configuration integration
Screenshot 2026-03-10 at 2 09 40 PM Screenshot 2026-03-10 at 2 04 31 PM

Related Issues

Addresses #1265, #112, #173, #573, #689

Check List

  • I confirm that my contribution is made under the terms of the Apache 2.0 license.
  • I have run pnpm checks to ensure code compiles and meets standards.
  • I have run pnpm test to check if all tests are passing.
  • I have covered new added functionality with unit tests if necessary.
  • I have added an entry in the Changelog.md.

…ge styling

Adds an optional defaultStyling.json file that can be mounted into the
Docker container to provide per-type vertex and edge styling defaults.
This addresses the need for persistent styling in environments where
browser storage is cleared between sessions (e.g., AWS WorkSpaces Web).

On startup, file values are merged into the user's per-type styling
preferences (IndexedDB). Default values fill in properties the user
hasn't explicitly set; existing user overrides are preserved. The file
also serves as a reference for per-type "Reset to Default" in the
Node/Edge Style dialogs.

The Settings page adds Export/Import/Reset All styling controls:
- Export: saves current styling as defaultStyling.json for sharing or
  Docker-mounting as team defaults
- Import: merges a defaultStyling.json into user styling and updates
  the reset reference so reset-after-import restores imported values
- Reset All: reverts all styling to defaults (from file or hardcoded)

Supports lucide icon names (resolved to SVG data URIs at runtime via
dynamic imports), custom icon URLs, colors, shapes, border styles, edge
line styles, and arrow styles. Includes Zod validation with strict type
checking for shapes and arrow styles.

Includes 58 new tests with 100% line coverage on new modules, example
file, and documentation.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@jkemmererupgrade jkemmererupgrade force-pushed the feature/default-styling-1265 branch from 44da021 to 89910a2 Compare March 12, 2026 14:33
Adds a searchable icon browser popover alongside the existing Upload
button in the node style dialog. Users can browse ~1,900 Lucide icons
with search filtering, capped at 50 visible results for performance.
Icons are lazy-loaded using the existing lucideIconToDataUri helper.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@jkemmererupgrade
Copy link
Copy Markdown
Author

jkemmererupgrade commented Mar 12, 2026

I also have a follow-on PR that will add a picker to the vertex/edge to filter and select one of the lucide icons. merged it as a commit to this PR. This is ready for review @kmcginnes.

Screenshot 2026-03-17 at 10 43 27 AM

Add Lucide icon picker to node styling dialog
@jkemmererupgrade
Copy link
Copy Markdown
Author

A note on the Lucide Licensing:
https://lucide.dev/license

Lucide uses the ISC License — one of the most permissive open-source licenses. It allows:

  - Use in commercial and open-source projects
  - Bundling and distribution
  - Modification
  - Any purpose, with or without fee

  The only requirement is keeping the copyright notice in distributed copies. Graph Explorer already ships lucide-react as a dependency (package.json line 43), so the license is already included in node_modules. 

@kmcginnes
Copy link
Copy Markdown
Collaborator

@jkemmererupgrade thanks for the submission, and I apologize for the slow response.

This looks like a great set of features, and they are ones I've been really wanting for myself as a user.

I won't have a chance to dive in to the details until next week at the earliest. Let me know if that works for you.

@jkemmererupgrade
Copy link
Copy Markdown
Author

@jkemmererupgrade thanks for the submission, and I apologize for the slow response.

This looks like a great set of features, and they are ones I've been really wanting for myself as a user.

I won't have a chance to dive in to the details until next week at the earliest. Let me know if that works for you.

Thank you @kmcginnes! Next week is great. Please let me know what else I can do to assist.

@kmcginnes kmcginnes self-requested a review March 23, 2026 21:36
@jkemmererupgrade
Copy link
Copy Markdown
Author

@kmcginnes checking in on the review, how's the testing going? anything I can do to help? Thank you!

@kmcginnes
Copy link
Copy Markdown
Collaborator

Hi, @jkemmererupgrade. Sorry for the slow progress on this. Bandwidth for PR reviews has been non-existent the last few weeks. I now have a backlog of PRs to go through once my availability improves. Please hang in there and thanks for checking in.

jkemmererupgrade and others added 4 commits April 20, 2026 12:00
- Resolved Changelog.md conflict: kept Unreleased defaultStyling entry above Release 3.0.1 section
- Resolved node-server.ts conflict: adopted createApp() refactor from main; moved /defaultStyling and /custom-icons endpoints into app.ts
- All 1680 tests pass, TypeScript checks clean

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- Resolved Changelog.md conflict: kept Unreleased section above new Release 3.0.2
- Resolved docs/references/README.md conflict: kept Default Connection and Default Styling links
- Resolved SettingsGeneral.tsx conflict: kept both defaultStylingAtom and diagnosticLoggingAtom imports
- Added @vitest-environment happy-dom to PR test files that use browser globals
- Added eslint-disable comments for react-hooks/set-state-in-effect in useInitCytoscape.tsx
  and Tabular.tsx (pre-existing intentional patterns, flagged by react-hooks v7)
- All 1709 tests pass, TypeScript checks clean

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
…n conventions

Merge from aws/graph-explorer main (includes PR 1738 and other recent changes).

Conflict resolutions:
- Changelog.md: kept Unreleased feature section alongside new Release 3.0.3 section
- useTabular.ts: took mains oxlint disable comments for react-table v7 patterns
- configuration.ts: kept HEAD comments about defaultStyling.json; removed defensive spreads
- userPreferences.ts: kept mergeDefaultsIntoUserStyling; dropped obsolete useStoredGraphPreferences

Post-merge adaptations (adapt feature branch to new main conventions):
- defaultStyling.test.ts, configuration.test.ts: replace if(result) guards with assert()
  to satisfy new oxlint no-conditional-expect rule
- vite.config.ts: add custom-icons and defaultStyling to Vite dev proxy whitelist regex
  (PR 1738 introduced explicit whitelist; without these paths the features Express static
  routes 404 in dev mode)
- packages/graph-explorer/package.json: remove redundant nested lint-staged config block
  (oxlint was not installed; root package.json lint-staged already covers all TS/JS files;
  the nested block caused lint-staged v16 to invoke oxlint from the package subdirectory
  where it treats the root .oxlintrc.json as a non-root config, triggering a typeAware error)
@kmcginnes
Copy link
Copy Markdown
Collaborator

Thanks for this, there's a lot of solid work here. The icon picker, the Zod-validated styling schema, the merge logic, and the import/export UI are all capabilities we want in the project. I'd like to see this ship as a series of smaller, independently mergeable PRs so I can share some context on direction for each piece:

Slice 1: Lucide icon resolver + icon picker UI
The icon resolution utility, the searchable picker in the node style dialog, and the rendering integration. This is the foundation the other slices build on. I've reviewed the direction of this part in depth and have specific feedback below.

Slice 2: Styling import/export/reset UI
The Export, Import, and Reset All buttons in Settings. Gives users manual control over their styling configuration. I haven't reviewed this closely yet, but the experience looks good from your description. This one is pretty straightforward once slice 1 goes in and I don't expect to have much to say on direction here.

Slice 3: Server-provided default styles
Rather than a standalone defaultStyling.json endpoint, I'd like styles to be part of the unified server config file planned in #1660. The merge logic and defaultStylingAtom you've built here are solid building blocks for that, but the delivery mechanism and overall shape will likely change. I could see styles being the first feature to use the unified config approach, but this will require some more back and forth between us to scope it out. I still need to review this part in detail.

Each slice can go in independently and builds on the previous one. Feel free to tackle these however works best for you, whether that's narrowing this PR to slice 1, closing and reopening as separate PRs, or whatever you prefer.

Architecture change: lucide:<name> storage

The current implementation resolves Lucide icons to base64 data URIs at selection time and stores the data URI in iconUrl. I'd like to change this to store "lucide:plane" (the symbolic reference) and resolve to a data URI at render time instead.

Once the icon name is converted to base64, it's gone. There's no way to recover which Lucide icon was selected, which causes a couple problems:

  1. The picker can't highlight the current selection. To show "plane is selected" when the user reopens the dialog, the picker would need to compare base64 strings against every icon in the library. With lucide:plane stored, it's a simple prefix check and string match.

  2. Config files can't use icon names. I want operators to be able to write "icon": "lucide:plane" in a config file, and I want exported styling files to contain icon references rather than opaque blobs. If the stored value is already a data URI, the export can't reverse it back to a name. The lucide: prefix also keeps the door open for additional icon packs in the future.

The render-time resolution approach works well with the existing React Query caching in renderNode.tsx. Each icon resolves once per session and stays cached (staleTime: Infinity). The dynamicIconImports mechanism you're already using is the right tool for this; it just moves from selection-time to render-time.

I've captured the full spec in #1774 if you want to see the details.

I'll deep dive in to slice 2 next as you've implemented it here to see if I have any direction changes to make.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants