mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-08-03 01:38:06 +00:00
Add settings tooltips and search to the web UI
Help users quickly find settings and understand how each one works. Tooltips: a new delegated controller (static/v3/js/tooltips.js) drives an accessible (i) info tooltip that appears on hover, keyboard focus, and tap. A shared `help_tip` Jinja macro (partials/_macros.html) emits the trigger; the plugin config macro and the core settings partials now surface help text through it. Per the design, the always-visible field help paragraphs are folded into the tooltip to declutter the forms, and the hardware/display settings carry authored detail (default, range, recommendation). Search: a global header search box finds settings across every settings tab — even ones not yet opened — via a lazy client-side index built by scanning the same field markup (static/v3/js/settings-search.js). Selecting a result switches tabs, waits for the field to load, then scrolls to and flashes it. A per-tab filter box hides non-matching fields on the current tab. Plugin settings get tooltips for free by reusing each field's schema `description`; every settings field also gets a stable `setting-<tab>-<key>` anchor id for search navigation. Styling uses the existing --color-* theme vars so light/dark mode both work, and honors prefers-reduced-motion. Adds Flask render smoke tests that assert each settings partial ships tooltips, anchors, and a filter box. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014gZxznuxw8L92FUMBN3Nqz
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
{# Plugin Configuration Partial - Server-side rendered form #}
|
||||
{# This template is loaded via HTMX when a plugin tab is clicked #}
|
||||
|
||||
{% import 'v3/partials/_macros.html' as ui %}
|
||||
|
||||
{# ===== MACROS FOR FORM FIELD GENERATION ===== #}
|
||||
|
||||
{# Render a single form field based on schema type #}
|
||||
@@ -18,9 +20,8 @@
|
||||
{% if obj_widget == 'schedule-picker' %}
|
||||
{# Schedule picker widget - renders enable/mode/times UI #}
|
||||
{% set obj_value = value if value is not none else {} %}
|
||||
<div class="form-group mb-4">
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">{{ label }}</label>
|
||||
{% if description %}<p class="text-sm text-gray-500 mb-2">{{ description }}</p>{% endif %}
|
||||
<div class="form-group mb-4" id="setting-{{ field_id }}" data-setting-key="{{ full_key }}">
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">{{ label }}{{ ui.help_tip(description, label) }}</label>
|
||||
<div id="{{ field_id }}_container" class="schedule-picker-container mt-1"></div>
|
||||
<input type="hidden" id="{{ field_id }}_data" name="{{ full_key }}" value='{{ (obj_value|tojson|safe)|replace("'", "'") }}'>
|
||||
</div>
|
||||
@@ -46,9 +47,8 @@
|
||||
{% elif obj_widget == 'time-range' %}
|
||||
{# Time range widget - renders start/end time inputs #}
|
||||
{% set obj_value = value if value is not none else {} %}
|
||||
<div class="form-group mb-4">
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">{{ label }}</label>
|
||||
{% if description %}<p class="text-sm text-gray-500 mb-2">{{ description }}</p>{% endif %}
|
||||
<div class="form-group mb-4" id="setting-{{ field_id }}" data-setting-key="{{ full_key }}">
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">{{ label }}{{ ui.help_tip(description, label) }}</label>
|
||||
<div id="{{ field_id }}_container" class="time-range-container mt-1"></div>
|
||||
<input type="hidden" id="{{ field_id }}_data" name="{{ full_key }}" value='{{ (obj_value|tojson|safe)|replace("'", "'") }}'>
|
||||
</div>
|
||||
@@ -75,15 +75,11 @@
|
||||
{{ render_nested_section(key, prop, value, prefix, plugin_id) }}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<div class="form-group mb-4">
|
||||
<div class="form-group mb-4" id="setting-{{ field_id }}" data-setting-key="{{ full_key }}">
|
||||
<label for="{{ field_id }}" class="block text-sm font-medium text-gray-700 mb-1">
|
||||
{{ label }}
|
||||
{{ label }}{{ ui.help_tip(description, label) }}
|
||||
</label>
|
||||
|
||||
{% if description %}
|
||||
<p class="text-sm text-gray-500 mb-2">{{ description }}</p>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{# Boolean - check for widget first #}
|
||||
{% if field_type == 'boolean' %}
|
||||
{% set bool_widget = prop.get('x-widget') or prop.get('x_widget') %}
|
||||
|
||||
Reference in New Issue
Block a user