The detail modal was a narrow column: a 15px icon, eighteen key-value rows in one grey block, and a form that grew the dialog to `max-w-lg` while the header and the buttons scrolled away with the content. It reads as a device sheet now, following NodeModal's shape: - One wide dialog with three fixed regions — header, scrolling body, footer — so the title and the actions stay put. - The header identifies the row at a glance: a type-coloured icon tile (the accent the node wears on the canvas), then a badge per discovery source, the type, live reachability with a dot, and how many canvases draw the device. - Three columns instead of one: identity, operations, curation. A section stays put when it has nothing to show and says why, rather than disappearing and leaving the reader unsure whether the field is absent or unsupported. - Timestamps read relative with the exact value on hover, matching the inventory cards. IP / hostname / MAC / IEEE offer a copy button. - The form uses the same control sizing as the canvas modals, and gains inputs for `friendly_name` and `device_subtype` — both were already submitted, so they could not be corrected here. Hardware is a property like any other, so the modal no longer edits it: nothing draws `cpu_*` / `ram_gb` / `disk_gb` / `show_hardware`, and the CPU / RAM / Disk keys are property suggestions instead. The columns are still sent back untouched — Proxmox and the YAML import write them and the YAML export reads them. Two assertions in the edit tests covered the removed section: the curated-fields test drops the hardware line, and the numeric-payload test stops editing a field that no longer exists while still checking the values leave as numbers. ha-relevant: maybe
React + TypeScript + Vite
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
Currently, two official plugins are available:
- @vitejs/plugin-react uses Babel (or oxc when used in rolldown-vite) for Fast Refresh
- @vitejs/plugin-react-swc uses SWC for Fast Refresh
React Compiler
The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see this documentation.
Expanding the ESLint configuration
If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
// Other configs...
// Remove tseslint.configs.recommended and replace with this
tseslint.configs.recommendedTypeChecked,
// Alternatively, use this for stricter rules
tseslint.configs.strictTypeChecked,
// Optionally, add this for stylistic rules
tseslint.configs.stylisticTypeChecked,
// Other configs...
],
languageOptions: {
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
])
You can also install eslint-plugin-react-x and eslint-plugin-react-dom for React-specific lint rules:
// eslint.config.js
import reactX from 'eslint-plugin-react-x'
import reactDom from 'eslint-plugin-react-dom'
export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
// Other configs...
// Enable lint rules for React
reactX.configs['recommended-typescript'],
// Enable lint rules for React DOM
reactDom.configs.recommended,
],
languageOptions: {
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
])