Product Design · 2025
How I turned the most support-heavy feature into a guided, accurate setup flow
Role
Lead UX Designer
Design direction
Timeline
8 weeks
Research to shipped
Impact
–50% setup time
Web · Vue 3 · 2 FE + 1 BE + CTO
Context
Wildeye monitors more than just water. Field-deployed sensors capture temperature, soil moisture, barometric pressure, water flow, water pressure, geotech, and anything else that comes down to measuring primitive data. The platform serves councils, irrigators, and industrial operators across New Zealand, Australia, and California, transmitting data to our cloud around the clock.
Alarms are the single most critical feature in the product.
They are the bridge between raw data and human action. A misconfigured alarm means a burst pipe goes unnoticed overnight. A missing recipient means the right person never gets the call. For many of our customers, alarms are the only reason they log into Wildeye at all.
Despite this, the alarm configuration experience had barely changed since the product's early days. It was functional, but it was showing its age, and our customers were telling us so in ways both direct and indirect.
The rebuild was also an opportunity to expand what alarms could actually do. The legacy system only supported three types: High, Low, and Minimum Night Flow. Customers were asking for rate-of-change alerts, sustained-threshold detection, schedule-based alarms, and multi-condition logic. Bolting those new capabilities onto the old form would have made a bad UX worse; a new surface was the only way to introduce them without compounding complexity.
Preview, finished V2

The shipped V2 interactive demo
The problem
Alarm-related support tickets accounted for nearly a third of all inbound requests. It took three versions to get this right — each attempt taught us something the previous one missed.
Legacy alarm editor — full-page form, all fields visible

Legacy recipients — comma-separated SMS numbers, no channel control

"I set up an alarm but nobody got the notification"
"How do I turn off an alarm temporarily without deleting it?"
"Can someone just set this up for me?"
What the data showed
23%
Zero recipients
Alarms saved with nobody to notify
61%
High/Low type
Most common alarm created
14%
Disabled < 24h
Suggesting misconfiguration
31%
Support tickets
Mentioning "alarm" in Q3
Nearly a quarter of alarms were essentially silent. They would trigger, but nobody would ever know.
Research
5 stakeholder interviews
CEO, CTO, 3 reseller partners
15 user sessions
Think-aloud tasks across 6 new users, 5 operators, 4 reseller techs
6 months of usage data
Audit of alarm configuration patterns
From the stakeholder interviews
"Resellers tell me their clients give up and just ask them to do it. If someone can't get an alarm working in the first session, they stop trusting the platform."
"The form makes it feel like configuring a spacecraft. Half the fields don't apply to their situation but they're all visible."
User observation highlights
15 moderated sessions
Quantitative evidence
9 / 15
Abandoned on first attempt
Gave up before saving a valid alarm
40%
Completed unassisted
Legacy UI baseline
42 / 100
SUS score (legacy)
"Marginal" usability band
3.2
Field errors per session
Avg. corrections before save
2:00
Median time-on-task
Range 1:10 – 3:20
Research synthesis
Recipients are forgotten, not optional
23% zero-recipient alarms; users missed the tab consistently
Recipients must be in the primary flow
Most alarms follow predictable patterns
61% High/Low; resellers describe "same setup fifty times"
Start simple, reveal complexity on demand
Setup is a high-stakes moment
Misconfigured alarms lead to missed events; 14% disabled <24h
Guide with smart defaults and validation
Power users need speed, not simplicity
Reseller tech completes in ~1 min but wants groups and bulk paste
Support both novice and expert workflows
First attempt
Armed with the research, I designed and shipped a complete redesign. The approach was clean: a modal dialog with two tabs — Conditions and Recipients — to reduce cognitive load by separating concerns.
The UI was significantly better than what it replaced. Modern inputs, proper spacing, a design-system-backed component library. We moved from a full-page route-based editor to an inline modal. Resellers responded well to the visual quality.
We also redesigned the alarm list view with a cleaner table layout, condition previews, and a streamlined creation flow. Everything looked like it was heading in the right direction.
Figma exploration — alarm modal iterations

V1: Tabbed modal — shipped to pilot
Conditions tab

Alarm list view — redesigned table with condition previews

Recipients tab (separate from conditions)

What went wrong
We deployed V1 to three reseller partners for a four-week pilot. The feedback was mixed — and the data was worse than we expected.
Pilot results — V1 vs legacy
-16%
Setup time
3:48 → 3:12 — target was 50%+
19%
Still zero recipients
Down from 23% — barely moved
0%
Support ticket change
No measurable improvement
62%
First-attempt completion
Target was 85%+
Reseller C
"It looks better but I'm still clicking between tabs to set up one alarm. Same number of steps, just prettier."
Participant 2 (re-test)
"I forgot the recipients tab again. It's still on a different page basically."
Separating conditions and recipients into tabs reduced visual complexity but increased operational complexity. Users didn't forget recipients because the form was ugly — they forgot because recipients were out of sight.
The tab model was an information architecture failure disguised as a UI improvement. We'd made the same mistake the old system made — just in a nicer wrapper.
This was the hardest conversation of the project. I had to go back to the team and say: the thing we just shipped isn't working. We need to rethink the structure, not just the surface.
V2: One surface
The V1 failure made the next decision obvious: everything had to live on one surface. No tabs. No page switches. If a user can see both the trigger condition and the recipient list at the same time, they can't forget either one.
I proposed a single modal with two collapsible sections instead of two tabs. The CTO was supportive — consolidating six components into one would also reduce maintenance. But Reseller B pushed back:
Reseller B — AU Agricultural
"A modal feels small. Our users have big monitors. Why would we make the editing space smaller?"
I addressed this by designing the modal at XL size (896px max) with a scrollable body and a pinned header/footer. The header itself became an editing surface — alarm name as an inline transparent input, the type badge alongside it, and the enabled/disabled toggle as a first-class control. The most-accessed controls live outside the scroll area. Collapsible sections actually give each section more vertical space than the old tabbed layout.
CEO — sign-off
"This feels like a settings panel in a modern app, not a form from 2010."
V2 — single modal, two collapsible sections


Progressive disclosure
The old system showed every field for every alarm type. A farm manager setting up a simple High/Low alarm saw the same form as a reseller configuring a Weekly Minimum Night Flow. The cost was visible in the data: 23% of alarms shipped with zero recipients because the form's complexity hid what mattered. I restructured this around two ideas: a type picker that explains what each alarm does, and a form that rewrites itself based on the selection.
I considered a stepped wizard and per-type sub-pages first. Both fragmented a task that users described as a single thought — "I want to know if X goes wrong" — so I kept the modal whole and made the form itself the variable surface.
Before: technical dropdown
After: 3-column card grid
Each type owns a tonal pair — light tint behind a dark icon — and that colour carries through to the type badge on the edit form header. The alarm gains a visual identity, not just a label.
Same modal, six experiences
Each alarm type renders a completely different set of fields — only the controls relevant to the selected type appear.
A farm manager creating a basic High/Low alarm sees 3 fields. A reseller configuring a Weekly MNF sees check hours defaulting to 22:00–06:00 (overnight, when you detect leaks). The complexity is there — it's just not visible until it's relevant. Setup time fell from 3:48 to under a minute, and zero-recipient alarms dropped from 23% to under 3% — see Section 11.
Sentence-style
The old form stacked labels above inputs vertically. Users had to mentally connect "Direction: High" with "Threshold: 120" with "Unit: L/hr" across three separate rows. I restructured each condition as a single inline sentence that reads like natural language — directly mirroring how users mentally construct alarms.
Each WildSegmentedToggle is fixed at 180px so the sentence layout stays stable regardless of which option is selected. When you switch from High to Low, the label dynamically rewrites — "above" becomes "below". The form reads itself.
Participant 4 — Compliance officer
"I just want to know if something's wrong. I don't care about the technical details of how the alarm works."
How a trigger condition reads
Each row is one decision. Toggles, labels, and values sit inline — the form reads like a sentence, not a spreadsheet.
The hardest part
Simple input fields
RejectedKept it minimal — just an email input and a phone input with "Add" buttons. Clean, but it didn't solve the power-user speed problem.
"This is prettier but it's actually slower. At least before I could paste a list of numbers."
— Reseller C
Unified smart input
RejectedCombined email and phone into a single smart input that would detect the format. Testing revealed confusion — users couldn't tell what to type.
"What do I put in here? An email? A phone number? A name?"
— Participant 2
Identity-aware recipients
ShippedSeparate email and phone inputs with identity autocomplete, inline channel toggles per chip, recipient groups, and bulk paste detection. Two audiences served by one system.
Recipient chip architecture
Recipients aren't names in a list — they're interactive chips with embedded channel controls. Each chip renders inline SMS, Voice, and Email toggles as 24px round buttons. Which channels appear depends on what we know about the contact.
Known Wildeye users get a blue chip background; raw contacts stay grey — an instant visual signal of "this person is in your system." The remove button is transparent until hover, when it fades to red — a destructive preview before commitment.
The autocomplete fires after two characters and searches by name, email, or phone. If a typed email matches a known user, it auto-upgrades to an identity chip — pulling in their name, phone number, and enabling all channels. The system rewards known contacts without blocking anyone.
Context-aware channel defaults
Blue chips = known users. Grey chips = raw contacts. Channels that can't work simply don't appear.
Interaction craft
WildSegmentedToggle
Hand-built animated toggle used 8× in the alarm modal. Sliding indicator is DOM-measured for pixel accuracy. Elastic cubic-bezier(0.22, 1, 0.36, 1) easing makes state changes feel physical. Keyboard navigable with arrow keys.
Anti-layout-shift inputs
Every input border goes from 1.5px to 2px on focus. Padding decreases 0.5px per side to compensate — the content never jumps. Invisible when done right; jarring when not.
Advanced options hierarchy
Rarely-used fields (AND condition, Dial at reset) collapse behind a disclosure link. When expanded, a 2px left border with padding creates visual nesting — communicating "optional, secondary" through layout alone.
Smart defaults
Developer concern — Internal testing
"What if I collapse the Notify section and forget I haven't added anyone?"
This led to summary pills on each collapsible section header — always visible regardless of whether the section is expanded or collapsed. A red warning on an empty Notify section creates mild but appropriate urgency. Sections use v-show rather than v-if, preserving form state when collapsed so users don't lose work.
For validation, I chose to disable the save button until minimum requirements are met — and those requirements change per alarm type. A basic High/Low alarm needs a threshold and reset logic. MNF needs valid check hour ranges. LastXDays needs a day count. No red error messages. The form guides through absence, not punishment.
Domain-informed defaults
Check hours (MNF)
22:00 – 06:00Nighttime — when you detect leaks in water networks
Alarm message
#sitename #inputname is above #alarmsetvalue #unitDynamic tags auto-populate from sensor data
Hold time options
Calculated from device frequency"2 readings = 10 min" for a 5-minute sensor
Direction label
Rewrites dynamicallyHigh → "above", Low → "below" — self-documenting
Channel defaults
Based on contact dataKnown user → all on. Raw email → email only.
Each default matches the most common real-world configuration — reducing decisions without removing control.
How we built it
1,050 lines of design specification
Two spec documents covering every conditional branch, pixel dimension, colour token, input state, and animation timing. A 9-phase build order. Not a Figma handoff — an engineering blueprint.
7 Storybook stories as source of truth
One story per alarm type plus the creation flow. Developers, CEO, and resellers all reacted to the same interactive artefact. Eliminated "that's not what I meant."
Pair design sessions for edge cases
For complex interactions like the channel toggles and bulk paste, I sat with the developer and we worked through every permutation in real time.
Pattern reuse — proof the design language scales
The sentence-style pattern proved transferable. I applied the same structure to InviteUsersModal: "Invite [emails] To [sites/groups] As [roles]." Same philosophy — the form reads like a sentence, complexity is progressive, and inputs match the mental model.
Two new design system primitives — WildChipInput and WildResourceSelect — were extracted from the alarm work and now serve both features. The alarm redesign didn't just fix a feature; it established a design language.
40+ commits of iterative refinement. Each one tightened a layout, refined a chip interaction, or extracted a reusable primitive. The git history reads like a design journal.
Before & after
A screenshot comparison makes this look like a UI reskin. It wasn't. The structure underneath changed completely — how fields render, how recipients work, how the form relates to what the user is trying to do.
The visual difference between V1 and V2 is subtle. The structural difference is everything. V1 moved the same form into a modal. V2 redesigned what a form could be — sentence-style configuration, identity-aware recipients, and a surface that adapts to what you're actually building.
Results
-50%
Alarm setup time
2 min → under 60 seconds
<3%
Zero-recipient alarms
Down from 23% — projected from internal testing
-83%
Codebase reduction
6 components → 1 unified modal
-50%
Reseller setup time
~1 min 30s → ~45 seconds
<15%
Support ticket target
Down from 31% — target, monitoring post-launch
What stakeholders said
CEO
"This is the first time I've been able to demo alarm setup to a prospect without apologising for the UI. It just works."
Reseller C
"The paste thing alone saves me an hour a day. And the groups — finally. I've been asking for that for two years."
Participant 2 (re-test)
"Oh, this is completely different. I can actually see what I'm doing. And I like that it tells me I haven't added anyone yet."
Developer impact
The old system required six parallel component files with shared-but-duplicated logic. The new system is a single component with conditional rendering. Bug fixes apply once. New alarm types can be added by extending the type picker and adding a template block.
Reflection
What went well
Research-driven prioritisation
The 23% zero-recipient statistic converted every sceptical stakeholder instantly. Investing in real usage data meant I never had to argue from opinion.
Iterating on the hardest part
The notification section went through three distinct iterations. Reseller C's blunt feedback was the catalyst for the system that shipped.
Storybook as communication
Using Storybook as the shared reference eliminated "that's not what I meant." Everyone reacted to the same interactive artefact.
What I'd do differently
Earlier reseller involvement
Their input on bulk paste and recipient groups could have shaped the design earlier if I'd included them in the initial research phase.
More investment in empty states
A more guided empty state — perhaps suggesting common recipients or recently used groups — could further reduce the zero-recipient problem.
Accessibility audit
The channel toggle buttons use colour as the primary indicator. A dedicated pass with screen reader testing would strengthen the design.
01
The most dangerous UI element is the one users don't see
Putting recipients on a separate tab didn't make them optional — it made them invisible. 23% of alarms were silently broken because of an IA decision.
02
Power users and novices need the same interface
Progressive disclosure, smart defaults, and bulk operations serve both audiences without bifurcating the experience.
03
A modal can replace a page if you design it right
The constraint forced better prioritisation. Every field had to earn its place.
04
Fake simplicity is worse than honest complexity
Users don't want fewer inputs — they want inputs they understand.
Data moves rooms that opinions can't.
The zero-recipient metric, the support ticket analysis, the session recordings — these aren't just research artefacts. They're decision-making tools that align stakeholders faster than any design argument.
Next Project