Multi-action keys with tap/long-press/double-tap/hold, gesture timing, display output colors, global font, and display output JSON/color parsing
- Multi-action system: each key supports multiple actions with different triggers (tap, long_press, double_tap, hold_start, hold_end) - GestureEngine: timing-based gesture detection with configurable thresholds - New config types: KeyAction, TimingConfig, DisplayOutput - Display output now supports JSON format (text/background/text_color) and first-line-as-hex-color format for dynamic key backgrounds - Display background colors are reflected in the web UI on the grid - renderUnicodeText/renderUnicodeTextOnImage accept custom text color (fg) - Global font setting (medium/regular) in Settings UI - PageManager.defaultFont used as fallback for per-key font - Alpine.js bundled locally (no CDN dependency) - Web UI: action tabs (Tap/Long Press/Double Tap/Hold), unified More section with appearance + display settings, gesture timing sliders in Settings - Grid: subtle action type icons in top-left corner matching display indicator style - Backward compatible: old config 'action' field auto-migrated to 'actions' array - M+ 1m font files in assets/ for reference - Updated config.example.json and README with all new features
This commit is contained in:
+87
-1
@@ -596,7 +596,7 @@ main {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
/* ── Display indicator on grid keys ── */
|
||||
/* ── Indicators on grid keys ── */
|
||||
.display-indicator {
|
||||
position: absolute;
|
||||
bottom: 4px;
|
||||
@@ -607,6 +607,23 @@ main {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.action-icons {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
left: 4px;
|
||||
display: flex;
|
||||
gap: 3px;
|
||||
pointer-events: none;
|
||||
flex-wrap: wrap;
|
||||
max-width: calc(100% - 6px);
|
||||
}
|
||||
.action-icon {
|
||||
font-size: 7px;
|
||||
color: var(--accent);
|
||||
opacity: 0.6;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/* ── Tab buttons ── */
|
||||
.tab-row {
|
||||
display: flex;
|
||||
@@ -721,3 +738,72 @@ main {
|
||||
font-size: 11px;
|
||||
margin: 0 2px;
|
||||
}
|
||||
|
||||
/* ── Action tabs ── */
|
||||
.action-tabs {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.action-tab {
|
||||
flex: 1;
|
||||
padding: 5px 2px;
|
||||
background: var(--bg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-xs);
|
||||
color: var(--text-muted);
|
||||
font-size: 9px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
text-align: center;
|
||||
transition: all var(--transition);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 3px;
|
||||
line-height: 1.3;
|
||||
}
|
||||
.action-tab:hover { color: var(--text); border-color: var(--border-light); }
|
||||
.action-tab.active {
|
||||
background: var(--accent);
|
||||
color: #fff;
|
||||
border-color: var(--accent);
|
||||
}
|
||||
.action-tab.configured {
|
||||
border-color: var(--success);
|
||||
color: var(--success);
|
||||
}
|
||||
.action-tab.active.configured {
|
||||
background: var(--accent);
|
||||
color: #fff;
|
||||
border-color: var(--accent);
|
||||
}
|
||||
.tab-check { font-size: 8px; }
|
||||
|
||||
/* ── Hold sub-tabs ── */
|
||||
.hold-subtabs {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.hold-stab {
|
||||
flex: 1;
|
||||
padding: 4px 8px;
|
||||
background: var(--bg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-xs);
|
||||
color: var(--text-muted);
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
text-align: center;
|
||||
transition: all var(--transition);
|
||||
}
|
||||
.hold-stab:hover { color: var(--text); border-color: var(--border-light); }
|
||||
.hold-stab.active {
|
||||
background: var(--accent);
|
||||
color: #fff;
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user