From 8398832960363f865dbe0d4ac255b93a41fdac64 Mon Sep 17 00:00:00 2001 From: eduard256 Date: Wed, 8 Apr 2026 08:54:40 +0000 Subject: [PATCH] Redesign HomeKit page, add design system reference Rebuild homekit.html with centered layout, cleaner PIN input, and consistent styling matching the rest of the frontend. Add www/design-system.html as a living component reference for all UI elements used across the Strix frontend. --- www/design-system.html | 2037 ++++++++++++++++++++++++++++++++++++++++ www/homekit.html | 263 +++--- 2 files changed, 2143 insertions(+), 157 deletions(-) create mode 100644 www/design-system.html diff --git a/www/design-system.html b/www/design-system.html new file mode 100644 index 0000000..7c80c4d --- /dev/null +++ b/www/design-system.html @@ -0,0 +1,2037 @@ + + + + + + + Strix - Design System + + + + +
+
+

Strix Design System

+

All components used across the Strix frontend

+
+ + +
+
1. Colors
+
CSS variables from :root
+ +
+
+
Backgrounds
+
+
+
+
+
+
+
+
+
Purple Accent
+
+
+
+
+
+
+
+
Semantic
+
+
+
+
+
+
+
+ +
+
+
Text Hierarchy
+
--text-primary: Main content text
+
--text-secondary: Labels, descriptions
+
--text-tertiary: Hints, placeholders
+
--text-disabled: Disabled elements
+
+
+
+ + +
+
2. Typography
+
Headings, labels, mono text
+ +
+

STRIX

+
Page Title (.page-title)
+
Screen Title (.screen-title)
+
Section Title (.section-title)
+
Label (.label)
+
Field Label (.field-label)
+
+
Monospace text (--font-mono)
+
+
+ + +
+
3. Buttons
+
All button variants
+ +
+
Primary
+
+ + +
+ +
Primary Large (full width)
+
+ +
+ +
Outline
+
+ +
+ +
Small Buttons
+
+ + +
+ +
Stop / Danger
+
+ + +
+ +
Add Sub / Secondary Action
+
+ +
+ +
Save (Green)
+
+ +
+ +
Back Navigation
+ + +
+ +
Add (+) Button
+
+ +
+ +
Use as Stream Button (card action)
+
+ +
+
+
+ + +
+
4. Form Elements
+
Inputs, selects, toggles
+ +
+
+
+
Standard Input
+
+ + +

IP address or stream URL

+
+
+
+
Large Input
+
+ +
+
+
+ +
+
+
Validated Input (readonly)
+
+
+ + + + +
+
+
+
+
Password with Toggle
+
+
+ + +
+
+
+
+ +
+
+
Select Dropdown
+
+
HW Acceleration
+ +
+
+
+
Small Inputs in Row
+
+
FPS
+
Width
+
Height
+
+
+
+ +
Add Row (input + button)
+
+ + +
+ +
Toggle Switches
+
+
Enabled (on)
+
Disabled (off)
+
+ +
+
Optional Label
+
+ + +
+
+
+ + +
+
5. Badges & Tags
+
Status indicators, type labels
+ +
+
Type Badges
+
+ standard + homekit + unreachable +
+ +
Status Badges
+
+
running
+
done
+
+ +
Mode Badge
+
+ Stream Testing + sub +
+ +
Tags (selected items)
+
+ + preset + Top 1000 Stream Patterns + + + + brand + Hikvision + + +
+ +
Card Tags (codec overlays)
+
+ H264 + AAC + MJPEG +
+ +
Latency Colors
+
+ 42ms (fast) + 320ms (medium) + 850ms (slow) +
+
+
+ + +
+
6. Cards
+
Stream cards, media cards
+ +
+
Stream Card (info)
+
+
+
Main Stream
+
rtsp://admin:pass@192.168.1.100:554/stream1
+
+
+
Sub Stream
+
rtsp://admin:pass@192.168.1.100:554/stream2
+
+
+ +
Media Card (test result)
+
+
+
+
+ + + + + +
+
+ H264 + AAC +
+ 1920x1080 +
+
+
rtsp://admin:***@192.168.1.100:554/stream1
+
+ 42ms + 1920x1080 +
+
+
+ +
+
+ +
+
+
+ + + + + +
+
+ H265 +
+ 640x480 +
+
+
rtsp://admin:***@192.168.1.100:554/stream2
+
+ 280ms + 640x480 +
+
+
+ +
+
+
+
+
+ + +
+
7. Progress & Status
+
Status bars, counters, progress, spinners
+ +
+
Status Bar (complete component)
+
+
+
running
+ sess_abc123 +
+
+
48
total
+
32
tested
+
5
alive
+
3
screenshots
+
+
+
+
+
+ +
+ +
Loading Spinner
+
+
+ Building stream URLs... +
+
+
+ + +
+
8. Collapsible Sections
+
Expandable settings, grouped results
+ +
+
Expand Button (settings)
+ + + +
+ +
Group with Collapse (results)
+
+
+ + Recommended - Main + (3) +
+
+
Cards would go here...
+
+
+
+
+ + +
+
9. Feedback
+
Toasts, errors, results, info boxes, notices
+ +
+
+
+
Error Box
+
Connection error: timeout after 5s
+
+
+
Info Box
+
+
How to use
+
Add these URLs to your NVR software.
+
+
+
+ +
+ +
+
+
Result OK
+
Added to go2rtc: camera_main. Open go2rtc UI
+
+
+
Result Error
+
camera_main: go2rtc not found
+
+
+ +
+ +
Notice Banner
+
+
Frigate NVR not detected
+
If you have Frigate NVR, we recommend running Strix on the same server.
+
+ +
+ +
Toast (click to demo)
+ +
+
+ + +
+
10. Config Panel
+
Code display with diff highlighting
+ +
+
+ Generated Config +
+ + +
+
+
go2rtc: + streams: + camera_main: + - rtsp://admin:pass@192.168.1.100:554/stream1 + camera_sub: + - rtsp://admin:pass@192.168.1.100:554/stream2 + +cameras: + camera: + ffmpeg: + inputs: + - path: rtsp://127.0.0.1:8554/camera_sub + input_args: preset-rtsp-restream + roles: + - detect + - path: rtsp://127.0.0.1:8554/camera_main + input_args: preset-rtsp-restream + roles: + - record
+
+ +
+ +
Config Example Block (copyable)
+
+
go2rtc.yaml
+
streams: + 'camera_main': + - rtsp://admin:pass@192.168.1.100:554/stream1
+ +
+
+ + +
+
11. Lists & Tables
+
Stream lists, device info tables
+ +
+
+
+
Streams Box (scrollable list)
+
3 streams
+
+
rtsp://admin:pass@192.168.1.100:554/stream1
+
rtsp://admin:pass@192.168.1.100:554/stream2
+
http://192.168.1.100:80/video.cgi
+
+
+
+
Device Info Table
+
+
IP Address192.168.1.100
+
ModelDS-2CD2043G2-I
+
VendorHikvision
+
MACAA:BB:CC:DD:EE:FF
+
+
+
+ +
+ +
Stream URL with Copy Button
+
+
Main Stream
+
+
rtsp://admin:pass@192.168.1.100:554/stream1
+ +
+
+
+
+ + +
+
12. Mobile Tabs
+
Tab switcher for two-column layouts on mobile
+ +
+
+
+ + +
+
+
+
+ + +
+
13. Sticky Bottom Bar
+
Fixed action bar at page bottom (not shown fixed in this demo)
+ +
+
+ +
+
+
+ + +
+
14. Autocomplete Dropdown
+
Searchable dropdown with type badges
+ +
+
+ +
+
+ + preset + Top 1000 + + +
+
+ brand + Hikvision +
+
+ model + Hikvision DS-2CD2043G2-I +
+
+ model + Hikvision DS-2CD2347G2-LU +
+
+
+
+
+ + +
+
15. SVG Icons
+
All inline SVG icons used across pages (never use emoji or icon fonts)
+ +
+
+
+ +
back
+
+
+ +
info
+
+
+ +
add
+
+
+ +
close
+
+
+ +
chevron
+
+
+ +
chevron-down
+
+
+ +
check
+
+
+ + + + +
copy
+
+
+ + + +
eye
+
+
+ + + + + +
image
+
+
+
+
+
+ + + + + + + + diff --git a/www/homekit.html b/www/homekit.html index deb1b84..acd90e3 100644 --- a/www/homekit.html +++ b/www/homekit.html @@ -42,103 +42,84 @@ } .screen { - min-height: 100vh; padding: 1.5rem; - display: flex; align-items: flex-start; justify-content: center; + min-height: 100vh; + padding: 1.5rem; + display: flex; + align-items: center; + justify-content: center; animation: fadeIn var(--transition-base); } - .container { max-width: 520px; width: 100%; margin-top: 6vh; } + .container { max-width: 480px; width: 100%; } @media (min-width: 768px) { .screen { padding: 3rem 1.5rem; } + .container { max-width: 540px; } } - .btn-back { - display: inline-flex; align-items: center; gap: 0.5rem; - background: none; border: none; - color: var(--text-secondary); font-size: 0.875rem; - font-family: var(--font-primary); cursor: pointer; - padding: 0.5rem 0; margin-bottom: 2rem; - transition: color var(--transition-fast); - } - .btn-back:hover { color: var(--purple-primary); } + .hero { text-align: center; margin-bottom: 3rem; } - .card { - background: var(--bg-secondary); - border: 1px solid var(--border-color); - border-radius: 12px; - padding: 2rem; - text-align: center; + .title { + font-size: 4rem; font-weight: 700; + letter-spacing: 0.1em; margin-bottom: 0.5rem; + background: linear-gradient(135deg, var(--purple-light), var(--purple-primary)); + -webkit-background-clip: text; -webkit-text-fill-color: transparent; + background-clip: text; } - .card-icon { - width: 48px; height: 48px; - margin: 0 auto 1.25rem; - color: var(--purple-light); + .subtitle { font-size: 0.875rem; color: var(--text-secondary); } + + .form-group { margin-bottom: 1.5rem; } + + .label { + display: flex; align-items: center; gap: 0.5rem; + font-size: 0.875rem; font-weight: 500; + color: var(--text-secondary); margin-bottom: 0.75rem; + justify-content: center; } - .card-title { - font-size: 1.25rem; font-weight: 600; - margin-bottom: 0.5rem; + /* Info icon + tooltip */ + .info-icon { + position: relative; display: inline-flex; + align-items: center; justify-content: center; + width: 16px; height: 16px; cursor: help; + color: var(--text-tertiary); transition: color var(--transition-fast); } - .card-badge { - display: inline-block; - padding: 0.25rem 0.75rem; - background: rgba(139, 92, 246, 0.15); - border: 1px solid rgba(139, 92, 246, 0.3); - border-radius: 6px; - font-size: 0.75rem; font-weight: 600; - color: var(--purple-light); - text-transform: uppercase; - letter-spacing: 0.05em; - margin-bottom: 1.5rem; + .info-icon:hover { color: var(--purple-primary); } + .info-icon svg { width: 16px; height: 16px; } + + .tooltip { + position: absolute; top: calc(100% + 8px); left: 50%; + transform: translateX(-50%); + background: var(--bg-elevated); + border: 1px solid var(--purple-primary); + border-radius: 8px; padding: 1rem; + width: 320px; max-width: 90vw; + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.6), 0 0 0 1px var(--purple-glow); + z-index: 1000; opacity: 0; visibility: hidden; + transition: opacity var(--transition-fast), visibility var(--transition-fast); + pointer-events: none; } - .device-info { - background: var(--bg-tertiary); - border: 1px solid var(--border-color); - border-radius: 8px; - padding: 1rem; - margin-bottom: 1.5rem; - text-align: left; + .tooltip::after { + content: ''; position: absolute; bottom: 100%; left: 50%; + transform: translateX(-50%); + border: 6px solid transparent; border-bottom-color: var(--purple-primary); } - .device-row { - display: flex; justify-content: space-between; - padding: 0.375rem 0; - font-size: 0.8125rem; - } + .info-icon:hover .tooltip { opacity: 1; visibility: visible; } - .device-row:not(:last-child) { - border-bottom: 1px solid rgba(139, 92, 246, 0.07); - } - - .device-label { color: var(--text-tertiary); } - .device-value { color: var(--text-primary); font-family: var(--font-mono); font-size: 0.75rem; } + .tooltip-title { font-weight: 600; color: var(--purple-primary); margin-bottom: 0.5rem; font-size: 0.875rem; } + .tooltip-text { font-size: 0.75rem; line-height: 1.5; color: var(--text-secondary); } /* PIN input */ - .pin-section { margin-bottom: 1.5rem; } - - .pin-label { - font-size: 0.875rem; font-weight: 500; - color: var(--text-secondary); - margin-bottom: 0.75rem; - } - - .pin-hint { - font-size: 0.75rem; color: var(--text-tertiary); - margin-top: 0.625rem; - } - .pin-row { display: flex; align-items: center; justify-content: center; gap: 0; } - .pin-group { - display: flex; gap: 0.375rem; - } + .pin-group { display: flex; gap: 0.375rem; } .pin-separator { font-size: 1.5rem; font-weight: 300; @@ -149,8 +130,8 @@ } .pin-digit { - width: 44px; height: 56px; - background: var(--bg-primary); + width: 57px; height: 69px; + background: var(--bg-secondary); border: 2px solid var(--border-color); border-radius: 8px; color: var(--text-primary); @@ -195,27 +176,28 @@ .pin-group { gap: 0.25rem; } } - /* Error message */ - .error-msg { - margin-top: 1rem; padding: 0.75rem 1rem; - background: rgba(239, 68, 68, 0.08); - border: 1px solid rgba(239, 68, 68, 0.2); + /* Error */ + .error-box { + padding: 1rem; + background: rgba(239, 68, 68, 0.1); + border: 1px solid rgba(239, 68, 68, 0.3); border-radius: 8px; - font-size: 0.8125rem; color: var(--error); - text-align: left; + color: var(--error); + font-size: 0.875rem; + margin-bottom: 1.5rem; display: none; animation: fadeIn var(--transition-fast); } - .error-msg.visible { display: block; } + .error-box.visible { display: block; } /* Buttons */ .btn { display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem; padding: 1rem 1.5rem; border-radius: 8px; - font-size: 0.9375rem; font-weight: 600; font-family: var(--font-primary); + font-size: 1rem; font-weight: 600; font-family: var(--font-primary); cursor: pointer; transition: all var(--transition-fast); - border: none; outline: none; width: 100%; + border: none; outline: none; } .btn-primary { @@ -229,14 +211,20 @@ .btn-primary:active:not(:disabled) { transform: translateY(0); } .btn-primary:disabled { opacity: 0.5; cursor: not-allowed; } + .btn-large { width: 100%; padding: 1.5rem; font-size: 1.125rem; } + .btn-outline { + display: inline-flex; align-items: center; justify-content: center; + gap: 0.5rem; padding: 1rem 1.5rem; border-radius: 8px; + font-size: 1rem; font-weight: 600; font-family: var(--font-primary); + cursor: pointer; transition: all var(--transition-fast); background: transparent; color: var(--text-secondary); - border: 1px solid var(--border-color); + border: 1px solid var(--border-color); width: 100%; margin-top: 0.75rem; } .btn-outline:hover { border-color: var(--purple-primary); color: var(--purple-light); } - /* Pairing state */ + /* Pairing spinner */ .pairing-spinner { width: 20px; height: 20px; border: 2px solid rgba(255, 255, 255, 0.3); @@ -258,43 +246,38 @@
- - -
- - - - - -

HomeKit Camera

-
Apple HomeKit
- -
- -
-
Enter the 8-digit code from your camera
- -
-
- - -
- - -
-
- -
Printed on the camera or in the manual
-
- -
- - - +
+

HOME KIT

+ +
+ + +
+
+ - +
+ - +
+
+
+ +
+ + +
@@ -315,34 +298,6 @@ var mdnsPaired = params.get('mdns_paired') || ''; var mdnsDeviceId = params.get('mdns_device_id') || ''; - // title - if (mdnsName) document.getElementById('card-title').textContent = mdnsName; - - // device info - var infoDiv = document.getElementById('device-info'); - var rows = []; - if (ip) rows.push(['IP Address', ip]); - if (mdnsModel) rows.push(['Model', mdnsModel]); - if (mdnsCategory) rows.push(['Category', mdnsCategory]); - if (vendor) rows.push(['Vendor', vendor]); - if (mac) rows.push(['MAC', mac]); - - rows.forEach(function(r) { - var row = document.createElement('div'); - row.className = 'device-row'; - var label = document.createElement('span'); - label.className = 'device-label'; - label.textContent = r[0]; - var value = document.createElement('span'); - value.className = 'device-value'; - value.textContent = r[1]; - row.appendChild(label); - row.appendChild(value); - infoDiv.appendChild(row); - }); - - if (rows.length === 0) infoDiv.style.display = 'none'; - // PIN input -- 8 digits: 3-2-3 var pinGroups = [3, 2, 3]; var inputs = []; @@ -444,14 +399,14 @@ } function showError(msg) { - var el = document.getElementById('error-msg'); + var el = document.getElementById('error-box'); el.textContent = msg; el.classList.add('visible'); inputs.forEach(function(input) { input.classList.add('error'); }); } function hideError() { - document.getElementById('error-msg').classList.remove('visible'); + document.getElementById('error-box').classList.remove('visible'); } function showSuccess() { @@ -515,9 +470,7 @@ var data = await r.json(); showSuccess(); - btnPair.textContent = ''; - var check = document.createTextNode('Paired!'); - btnPair.appendChild(check); + btnPair.textContent = 'Paired!'; // redirect to create.html with the homekit URL setTimeout(function() { @@ -540,10 +493,6 @@ } // navigation - document.getElementById('btn-back').addEventListener('click', function() { - window.location.href = 'index.html'; - }); - document.getElementById('btn-standard').addEventListener('click', function() { var p = new URLSearchParams(); if (ip) p.set('ip', ip);