From d3619584d6c4d7cd573f8e1232fb3c9e9b6f2948 Mon Sep 17 00:00:00 2001 From: ChuckBuilds Date: Thu, 16 Jul 2026 10:23:05 -0400 Subject: [PATCH] feat(web): x-advanced schema flag groups plugin config fields under a collapsed Advanced Settings section Plugin config pages show every schema property at equal visual priority, which overwhelms first-time users. Plugin authors can now add "x-advanced": true to any flat (non-object) property in config_schema.json to move it into one collapsed "Advanced Settings (N)" section rendered after the basic fields - progressive disclosure with zero loss of control. Implementation: the main render loop in plugin_config.html splits ordered properties into basic/advanced tiers; the advanced group reuses the exact .nested-section/.nested-content/toggleSection() shell that nested object sections already use, so the settings search's expand-on-match behavior works on advanced fields with no JS changes. Object-type properties ignore the flag (they already render as their own collapsible sections). No backend change needed: jsonschema ignores unknown x-* keywords exactly as it does for x-widget/x-propertyOrder. Documented in docs/widget-guide.md alongside the other x-* extensions. Validation (rendered with real Jinja, not just parsed): - synthetic schema with 2 advanced fields: basic fields render before the section, advanced inside the collapsed shell, count badge correct, x-advanced on an object property correctly ignored - schema without any x-advanced: output is identical to the pre-change template (whitespace-normalized diff against git HEAD's version) Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01KEZK1P1Q1fu5pcuVrkrCFZ --- docs/widget-guide.md | 34 +++++++++++++++ .../templates/v3/partials/plugin_config.html | 42 ++++++++++++++++++- 2 files changed, 74 insertions(+), 2 deletions(-) diff --git a/docs/widget-guide.md b/docs/widget-guide.md index dadda4cf..7a1ed850 100644 --- a/docs/widget-guide.md +++ b/docs/widget-guide.md @@ -206,6 +206,40 @@ To use an existing widget in your plugin's `config_schema.json`, simply add the The widget will be automatically rendered when the plugin configuration form is loaded. +## Marking Fields as Advanced (`x-advanced`) + +Add `"x-advanced": true` to any top-level, non-object property to move it out +of the main form and into a single collapsed **Advanced Settings** section at +the bottom of the plugin's configuration page: + +```json +{ + "properties": { + "city": { + "type": "string", + "title": "City" + }, + "request_timeout": { + "type": "integer", + "default": 10, + "description": "HTTP timeout in seconds", + "x-advanced": true + } + } +} +``` + +Guidelines: + +- Use it for fine-tuning knobs most users never touch (timeouts, retry + behavior, cache TTLs, styling overrides). Anything a first-time user must + set to get the plugin working should stay basic. +- Nothing is hidden permanently — the section expands on click, and the + settings search finds and auto-expands advanced fields like any others. +- The flag is ignored on `object`-type properties (they already render as + their own collapsible sections) and is safely ignored by older cores, so + adding it never breaks compatibility. + ## Creating Custom Widgets ### Step 1: Create Widget File diff --git a/web_interface/templates/v3/partials/plugin_config.html b/web_interface/templates/v3/partials/plugin_config.html index e427918f..edb98056 100644 --- a/web_interface/templates/v3/partials/plugin_config.html +++ b/web_interface/templates/v3/partials/plugin_config.html @@ -1005,13 +1005,51 @@ {# Use property order if defined, otherwise use natural order #} {# Skip 'enabled' field - it's handled by the header toggle #} {% set property_order = schema['x-propertyOrder'] if 'x-propertyOrder' in schema else schema.properties.keys()|list %} + {# Flat (non-object) properties flagged "x-advanced": true are + grouped into one collapsed "Advanced Settings" section after + the basic fields. Object-type properties already render as + their own collapsible sections, so the flag is ignored for + them. Schemas without the flag render exactly as before. #} + {% set tiers = namespace(basic=[], advanced=[]) %} {% for key in property_order %} {% if key in schema.properties and key != 'enabled' %} {% set prop = schema.properties[key] %} - {% set value = config[key] if key in config else none %} - {{ render_field(key, prop, value, '', plugin.id) }} + {% set is_object = prop.type is defined and 'object' in prop.type %} + {% if prop.get('x-advanced') and not is_object %} + {% set tiers.advanced = tiers.advanced + [key] %} + {% else %} + {% set tiers.basic = tiers.basic + [key] %} + {% endif %} {% endif %} {% endfor %} + {% for key in tiers.basic %} + {% set prop = schema.properties[key] %} + {% set value = config[key] if key in config else none %} + {{ render_field(key, prop, value, '', plugin.id) }} + {% endfor %} + {% if tiers.advanced %} + {% set adv_section_id = (plugin.id ~ '-section-advanced-settings')|replace('.', '-')|replace('_', '-') %} +
+ + +
+ {% endif %} {% else %} {# No schema - render simple form from config #} {% if config %}