Horizontal Level
A horizontal bar that fills as the value grows. Use it for tank levels, signal strength, charge state — anything that lives on a 0-to-max axis.
[image] Horizontal Level on canvas at 70 %, gradient fill, value displayed in the center
What it does
Horizontal Level shows a number as a horizontal fill bar. Three styles — Solid, Gradient, Segmented — each with its own visual character. Optional value display, optional external pointer indicator (Top / Bottom positions), and optional threshold zones that change the bar color when the value crosses defined points.
When to use it
- Tank level — Range 0–100, unit %, thresholds at 20 % (red) and 80 % (green).
- Battery indicator — Range 0–100, segmented style with 10 segments.
Properties
The Inspector opens as a bottom sheet with a Widget ID field at the top, then these sections in order.
Widget ID
| Property | Type | What it controls |
|---|---|---|
| Widget ID | text | Identifier used by your sketch (IHorizontalLevel("…")). |
1. Essential
| Property | Type | Default | What it controls |
|---|---|---|---|
| Enabled | toggle | on | Whether the widget displays content. |
| Style | Solid / Gradient / Segmented | Solid | Bar visualization. |
| Value display | None / % / Value / Both | % | What appears as the value text. |
| Value position | None / Left / Center / Right / Top / Bot. | Center | Where the value text appears. |
| Animate changes | toggle | on | Smooth bar fill changes. |
2. Header
| Property | Type | Default | What it controls |
|---|---|---|---|
| Show header | toggle | off | Display a header above the bar. |
| Header text | text | empty (placeholder Label) | Header text. Only when Show header is on. |
| Alignment | Left / Center / Right | Center | Header text position. Only when Show header is on. |
3. Value
| Property | Type | Default | What it controls |
|---|---|---|---|
| Current value | slider | 0 | Initial value (clamped to Min..Max). |
| Min value | number | 0 | Lower bound. |
| Max value | number | 100 | Upper bound. |
| Unit | text | empty (placeholder %, mL, °C…) | Unit appended to the value. |
4. Appearance
| Property | Type | Default | What it controls |
|---|---|---|---|
| Show border | toggle | on | Show outer border. |
| Border width | 1–6 | 2 | Border stroke. Only when Show border is on. |
| Corner radius | 0–24 | 8 | Bar corner roundness. |
| Segment count | 3–20 | 10 | Number of segments. Only when Style is Segmented. |
| Segment spacing | 1–10 | 2 | Gap between segments. Only when Style is Segmented. |
5. Indicator
Only when Value position is Top or Bottom.
| Property | Type | Default | What it controls |
|---|---|---|---|
| Style | ▼ Triangle / ● Circle / | Line / ◆ Diamond / → Arrow | ▼ Triangle |
| Size | 6–20 | 12 | Pointer size. |
| Indicator color | color (optional) | theme | Pointer color. |
6. Colors · Bar
When Style is Solid or Segmented.
| Property | Type | What it controls |
|---|---|---|
| Fill | color | Filled portion. |
| Background | color | Unfilled portion. |
| Border | color | Border. |
| Text | color | Value text. |
6 bis. Colors · Gradient
When Style is Gradient.
| Property | Type | What it controls |
|---|---|---|
| Start | color | Gradient start (left). |
| End | color | Gradient end (right). |
7. Colors · Bar (Gradient companion)
When Style is Gradient — second block.
| Property | Type | What it controls |
|---|---|---|
| Background | color | Unfilled portion. |
| Border | color | Border. |
| Text | color | Value text. |
8. Thresholds
A dynamic list of value-color pairs that color zones along the bar.
For each threshold:
| Property | Type | What it controls |
|---|---|---|
| Color swatch | color picker | Zone color above this threshold. |
| Value display | read-only | Shows the value as integer and % of range. |
| Slider | range Min..Max | Adjusts the threshold value. |
Plus per-threshold action:
| Action | Type | What it does |
|---|---|---|
| Delete | button | Remove this threshold. |
Plus list-level action:
| Action | Type | What it does |
|---|---|---|
| Add threshold | button | Creates a new threshold at mid-range with a default amber color. |
States and behavior
[image] Three styles side by side — Solid 30 %, Gradient 70 %, Segmented 50 %
The bar fills from left to right. Out-of-range values are clamped to the bar’s edge. Thresholds apply visual color zones — useful to surface alarm levels without writing color logic in your sketch.
In code
The widget mirrors what your sketch sends. To update its value:
instant.hLevel("water_tank").setValue(75.0);
That single line is what shows up on the dashboard. Don’t put it directly in loop() — Arduino’s loop() runs thousands of times per second, which would flood the link. Use a timer to push at a sensible rate (200–1000 ms is plenty).
Available methods: .setValue(float), .setRange(float min, float max), .update(float value, float min, float max). See InstantIoT Library / Send Data to App.
Working Arduino code example
A complete sketch you can flash. The Widget ID water_tank matches the one you set on your Horizontal Level in the app.
[gif] Horizontal Level on the dashboard filling and emptying as the ESP32 reads an ultrasonic sensor
Direct Mode
Your phone connects directly to the ESP32’s SoftAP — no router, no server. Best for prototyping and standalone setups.
#include <InstantIoTWiFiAP.hpp>
#include <utils/InstantIoTTimer.hpp>
const char* AP_SSID = "InstantIoT-Greenhouse";
const char* AP_PASS = "12345678";
InstantIoTWiFiAP instant(AP_SSID, AP_PASS);
InstantTimer timers;
float readUltrasonic() {
// Replace with your real HC-SR04 read (cm)
return 5.0f + (random(0, 250) / 10.0f);
}
void pushTank() {
if (!instant.connected()) return;
float distanceCm = readUltrasonic();
float fillPct = map(distanceCm * 10, 300, 50, 0, 1000) / 10.0f;
instant.hLevel("water_tank").setValue(constrain(fillPct, 0.0f, 100.0f));
}
void setup() {
instant.begin();
timers.every(500, pushTank);
}
void loop() {
instant.loop();
timers.run();
}
Server Mode
The ESP32 connects to your self-hosted InstantIoT Server over WiFi. Multiple devices, persistent state, history.
#include <InstantIoTWiFiServer.hpp>
#include <utils/InstantIoTTimer.hpp>
const char* WIFI_SSID = "YOUR_WIFI_SSID";
const char* WIFI_PASS = "YOUR_WIFI_PASSWORD";
const char* SERVER_IP = "192.168.1.42";
const uint16_t SERVER_PORT = 9001;
const char* DEVICE_TOKEN = "YOUR_DEVICE_TOKEN";
InstantIoTWiFiServer instant(SERVER_IP, SERVER_PORT, DEVICE_TOKEN);
InstantTimer timers;
float readUltrasonic() {
// Replace with your real HC-SR04 read (cm)
return 5.0f + (random(0, 250) / 10.0f);
}
void pushTank() {
if (!instant.connected()) return;
float distanceCm = readUltrasonic();
float fillPct = map(distanceCm * 10, 300, 50, 0, 1000) / 10.0f;
instant.hLevel("water_tank").setValue(constrain(fillPct, 0.0f, 100.0f));
}
void setup() {
instant.begin(WIFI_SSID, WIFI_PASS);
timers.every(500, pushTank);
}
void loop() {
instant.loop();
timers.run();
}
The widget code is identical — only the include and constructor change.
Notes
- This is a Display — no Target Devices dropdown.
- Indicator section only appears when Value position is Top or Bottom.
- Color sections change layout based on Style: Solid and Segmented share one Colors · Bar section; Gradient has Colors · Gradient + a separate Colors · Bar for background, border, text.
Next
→ Vertical Level — Same widget, oriented vertically.
→ Gauge — When the arc form fits better than a bar.
→ Advanced Chart — When you want the level’s history, not just the current state.