Skip to content

Enhance Properties panel section behavior and persistence#3787

Draft
jsjgdh wants to merge 2 commits intoGraphiteEditor:masterfrom
jsjgdh:State
Draft

Enhance Properties panel section behavior and persistence#3787
jsjgdh wants to merge 2 commits intoGraphiteEditor:masterfrom
jsjgdh:State

Conversation

@jsjgdh
Copy link
Contributor

@jsjgdh jsjgdh commented Feb 18, 2026

@jsjgdh jsjgdh marked this pull request as draft February 18, 2026 17:23
@gemini-code-assist
Copy link

Summary of Changes

Hello @jsjgdh, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the user experience of the properties panel by enabling sections to be collapsed and expanded, with their state being persisted. It also introduces convenient shortcuts for managing the expansion of all sections at once, improving navigation and focus within complex property layouts.

Highlights

  • Properties Panel Section Expansion: Introduced an expanded field to LayoutGroup::Section to control the collapsed/expanded state of sections in the properties panel, allowing for persistence of this state.
  • State Management for Section Expansion: The PropertiesPanelMessageHandler now maintains a HashMap to store the expanded state of individual sections, ensuring their state is remembered across refreshes.
  • New Messages for Expansion Control: Added SetSectionExpanded and SetAllSectionsExpanded messages to manage the expanded state of individual sections and to toggle the state of all sections simultaneously.
  • Frontend Interaction and Shortcuts: The WidgetSection.svelte component was updated to reflect and dispatch expanded state changes. It also includes a new feature to expand/collapse all sections by holding Alt while clicking a section header.
  • Default Expansion for Merge Nodes: Implemented a special case where 'Merge' nodes in the properties panel will default to a collapsed state for better organization.
Changelog
  • editor/src/messages/layout/utility_types/layout_widget.rs
    • Added expanded field to LayoutGroup::Section enum
    • Updated Diffable implementation for LayoutGroup to include the new expanded field
  • editor/src/messages/portfolio/document/node_graph/document_node_definitions.rs
    • Added section_expanded HashMap to NodePropertiesContext to pass expanded state to node properties generation
  • editor/src/messages/portfolio/document/node_graph/node_properties.rs
    • Implemented logic to determine the expanded state for each section, defaulting 'Merge' nodes to collapsed
    • Passed the calculated expanded state to the LayoutGroup::Section constructor
  • editor/src/messages/portfolio/document/properties_panel/properties_panel_message.rs
    • Introduced SetAllSectionsExpanded message to toggle the expanded state of all sections
    • Added SetSectionExpanded message to control the expanded state of a specific section
  • editor/src/messages/portfolio/document/properties_panel/properties_panel_message_handler.rs
    • Imported HashMap for state management
    • Added section_expanded HashMap field to PropertiesPanelMessageHandler to store section states
    • Passed the section_expanded HashMap to NodePropertiesContext during properties collation
    • Implemented handlers for SetAllSectionsExpanded to update all stored states and refresh the panel
    • Implemented handlers for SetSectionExpanded to update a specific section's state and refresh the panel
  • frontend/src/components/widgets/WidgetSection.svelte
    • Updated expanded state to be derived from widgetData.expanded
    • Removed the TODO comment regarding collapsable sections
    • Modified click handler for section headers to dispatch setSectionExpanded for individual sections
    • Added Alt key modifier to the click handler to dispatch setAllSectionsExpanded for all sections
  • frontend/src/messages.ts
    • Updated WidgetSection type definition to include the expanded: boolean property
    • Adjusted createLayoutGroup function to correctly parse the new expanded property for sections
  • frontend/wasm/src/editor_api.rs
    • Exposed setSectionExpanded function to WASM for setting an individual section's expanded state
    • Exposed setAllSectionsExpanded function to WASM for setting the expanded state of all sections
Activity
  • The pull request was initiated by jsjgdh.
  • A discussion regarding these changes took place on Discord with @Keavon.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a great enhancement to the Properties panel by making sections collapsible and persisting their state. The implementation is well-structured, touching both the backend state management and the frontend UI components. The use of Alt+click to expand/collapse all sections is a nice UX improvement.

My main feedback is regarding the implementation of the "expand/collapse all" feature, which currently has a bug where it doesn't affect sections that haven't been individually toggled. I've left detailed comments with suggestions on how to address this by introducing a global expansion state.

Overall, this is a solid contribution that improves user experience. Addressing the issue I've pointed out will make it even more robust.

Comment on lines 22 to +25
#[derive(Debug, Clone, Default, ExtractField)]
pub struct PropertiesPanelMessageHandler {}
pub struct PropertiesPanelMessageHandler {
pub section_expanded: HashMap<u64, bool>,
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The current implementation of SetAllSectionsExpanded has a flaw where it only affects sections that have been individually toggled. To fix this, I suggest adding a field to track a global expansion state. I'll leave another comment on the message handlers with more details.

Suggested change
#[derive(Debug, Clone, Default, ExtractField)]
pub struct PropertiesPanelMessageHandler {}
pub struct PropertiesPanelMessageHandler {
pub section_expanded: HashMap<u64, bool>,
}
#[derive(Debug, Clone, Default, ExtractField)]
pub struct PropertiesPanelMessageHandler {
pub section_expanded: HashMap<u64, bool>,
pub all_sections_expanded: Option<bool>,
}

Comment on lines +68 to +77
PropertiesPanelMessage::SetAllSectionsExpanded { expanded } => {
for value in self.section_expanded.values_mut() {
*value = expanded;
}
responses.add(PropertiesPanelMessage::Refresh);
}
PropertiesPanelMessage::SetSectionExpanded { node_id, expanded } => {
self.section_expanded.insert(node_id, expanded);
responses.add(PropertiesPanelMessage::Refresh);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Using the new all_sections_expanded field, this updated logic correctly handles the global expand/collapse behavior.

  • SetAllSectionsExpanded now acts as a global override by setting all_sections_expanded and clearing individual states.
  • SetSectionExpanded clears the global override, allowing individual control again.

To complete this change, you'll also need to:

  1. Pass self.all_sections_expanded to NodePropertiesContext in the Refresh handler (this requires adding all_sections_expanded: Option<bool> to NodePropertiesContext).
  2. In generate_node_properties, prioritize all_sections_expanded when determining a section's expanded state.
Suggested change
PropertiesPanelMessage::SetAllSectionsExpanded { expanded } => {
for value in self.section_expanded.values_mut() {
*value = expanded;
}
responses.add(PropertiesPanelMessage::Refresh);
}
PropertiesPanelMessage::SetSectionExpanded { node_id, expanded } => {
self.section_expanded.insert(node_id, expanded);
responses.add(PropertiesPanelMessage::Refresh);
}
PropertiesPanelMessage::SetAllSectionsExpanded { expanded } => {
self.all_sections_expanded = Some(expanded);
self.section_expanded.clear();
responses.add(PropertiesPanelMessage::Refresh);
}
PropertiesPanelMessage::SetSectionExpanded { node_id, expanded } => {
self.all_sections_expanded = None;
self.section_expanded.insert(node_id, expanded);
responses.add(PropertiesPanelMessage::Refresh);
}

Comment on lines +1846 to +1851
let is_merge_node = context
.network_interface
.reference(&node_id, context.selection_network_path)
.as_ref()
.is_some_and(|id| id.implementation_name_from_identifier() == "Merge");
let default_expanded = !is_merge_node;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic needs to occur when originally creating the merge node, like when adding a new layer to the document.

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

Comments