-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patheyedar.html
More file actions
343 lines (307 loc) · 19.3 KB
/
eyedar.html
File metadata and controls
343 lines (307 loc) · 19.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Jeff Halpin - Interaction Design, User Experience, Product Design, UX Research, UX Writing: Eyedar mobile application</title>
<link rel="icon" type="image/x-icon" href="/projects/portfolio/favicon.ico?v=2" />
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Kaisei+Opti&family=Lato:wght@400;700&family=Playfair+Display:wght@400;700&family=Poppins:wght@400;600;700&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Kaisei Opti', serif;
}
</style>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
'off-white': '#FFFEF9',
'white': '#FFFFFF',
'near-black': '#181818',
'light-gray': '#F7F7F7',
'aquamarine': '#61EDD8',
'accent': '#079E87',
'text-primary': '#181818',
'text-secondary': '#DFE1E3',
'accent-primary': '#61EDD8',
'background-base': '#FFFFFF',
'mid-gray': '#DFE1E3',
'surface-default': '#FFFEF9',
'border-subtle': '#F7F7F7',
'text-tertiary': '#526AC2',
},
fontFamily: {
'kaisei': ['Kaisei Opti', 'serif'],
'lato': ['Lato', 'sans-serif'],
'playfair': ['Playfair Display', 'serif'],
'poppins': ['Poppins', 'sans-serif'],
}
}
}
}
</script>
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-PLH7LQ');</script>
<!-- End Google Tag Manager -->
</head>
<body class="bg-[#FFFEF9] font-kaisei min-h-screen relative">
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-PLH7LQ"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
<!-- HEADER -->
<header class="bg-[#FFFEF9] border-b-0 md:border-b md:border-neutral-200 sticky top-0 z-40 h-[60px]">
<div class="flex items-center justify-between gap-4 max-w-7xl mx-auto h-full px-4">
<a href="index.html" class="font-kaisei text-2xl text-black font-medium hover:text-accent transition-colors">Jeff Halpin</a>
<nav class="hidden md:flex items-center gap-6">
<a href="index.html#about" class="text-sm text-black hover:text-accent transition-colors">About</a>
<a href="index.html#work" class="text-sm text-black hover:text-accent transition-colors">Work</a>
<a href="index.html#approach" class="text-sm text-black hover:text-accent transition-colors">Approach</a>
<a href="contact.html" class="text-sm text-black hover:text-accent transition-colors">Contact</a>
</nav>
<button id="menu-toggle" class="md:hidden w-[35px] h-[44px] flex flex-col items-center justify-center gap-[8px] p-2" aria-label="Toggle menu">
<span class="w-full h-[2px] bg-black"></span>
<span class="w-full h-[2px] bg-black"></span>
</button>
</div>
</header>
<!-- Mobile Menu -->
<div id="mobile-menu" class="hidden fixed inset-0 z-50 bg-black/50 md:hidden">
<div class="bg-[#FFFEF9] w-4/5 h-full p-6 flex flex-col gap-6">
<button id="menu-close" class="self-end text-2xl" aria-label="Close menu">×</button>
<nav class="flex flex-col gap-4">
<a href="index.html#about" class="text-lg text-black hover:text-accent transition-colors">About</a>
<a href="index.html#work" class="text-lg text-black hover:text-accent transition-colors">Work</a>
<a href="index.html#approach" class="text-lg text-black hover:text-accent transition-colors">Approach</a>
<a href="contact.html" class="text-lg text-black hover:text-accent transition-colors">Contact</a>
</nav>
</div>
</div>
<!-- HERO IMAGE (full-bleed) -->
<section>
<img src="images/Eyedar_hero.png" alt="Eyedar Mobile Application" class="w-full max-w-[1440px] mx-auto">
</section>
<!-- PROJECT TITLE & SHORT DESCRIPTION -->
<section class="px-4 md:px-0 pt-[80px] pb-[48px]">
<div class="max-w-[1200px] mx-auto">
<h1 class="text-[40px] md:text-[48px] leading-tight text-text-primary font-normal mb-6">Mobile Application Design: EYEDAR</h1>
<p class="text-lg text-text-primary leading-relaxed">
A LIDAR-based echolocation application that translates spatial data into audio signals, enabling blind and visually impaired users to navigate their environment through sound.
</p>
</div>
</section>
<!-- PROJECT CONTENT & METADATA -->
<section class="px-4 md:px-0">
<div class="max-w-[1200px] mx-auto flex flex-col md:flex-row gap-[32px] md:gap-[64px]">
<!-- Left: Main Content -->
<div class="md:w-[750px] flex flex-col gap-[32px]">
<div>
<h3 class="text-2xl text-text-primary font-normal mb-4">The Challenge</h3>
<p class="text-base text-text-primary leading-relaxed mb-4">
Designing for blind users isn't about adding accessibility features to a visual interface. It requires abandoning visual paradigms entirely. Eyedar needed an interaction model that blind and visually impaired users could learn, trust, and operate confidently while moving through physical space.
</p>
<p class="text-base text-text-primary leading-relaxed">
The core constraint: every interaction had to be discoverable and executable without sight. No buttons. No screen hierarchy. No visual confirmation. The interface would live entirely in gesture, sound, and haptic feedback.
</p>
</div>
<div>
<h3 class="text-2xl text-text-primary font-normal mb-4">My Role</h3>
<p class="text-base text-text-primary leading-relaxed">
Senior UX Architect, responsible for interaction design, user flows, and UX writing. I led user testing sessions with blind participants and created all training materials and instructions-for-use documentation.</p>
</div>
<div>
<h3 class="text-2xl text-text-primary font-normal mb-4">Research & Discovery</h3>
<p class="text-base text-text-primary leading-relaxed mb-4">Our research combined interviews, usability testing, and field observation with blind users. I synthesized findings into design documentation that guided both product design and development. Early testing challenged our assumptions quickly. One example: the placement of the audio cue for "end of section" wasn't registering clearly. For a sighted user, this would be like scrolling past the content into empty space without realizing the page had ended. Under tight deadlines, we rapidly prototyped and tested multiple options to ensure that the cue was landing in the expected location. Small details like this carried outsized weight when every interface signal had to land without visual backup.
</p>
<p class="text-base text-text-primary leading-relaxed">Users also told us they needed a slower ramp. The audio landscape vocabulary was learnable, but not instantly. This insight drove a multi-stage onboarding process that introduced capabilities progressively rather than all at once. We conducted four rounds of usability testing with blind users, iterating on the interaction model and audio vocabulary until we achieved a flow that was both effective and delightful.
</p>
</div>
<!-- Wireframes Image with Caption -->
<figure>
<img src="images/eyedar_wires_01_sm.png" alt="Complete interaction specification for Eyedar"
class="w-full rounded-xl cursor-pointer hover:opacity-90 transition-opacity lightbox-trigger">
<figcaption class="text-sm text-neutral-600 mt-3 text-center">
Complete interaction specification documenting gesture controls, VoiceOver feedback, and screen flows across the application.
</figcaption>
</figure>
<div>
<h3 class="text-2xl text-text-primary font-normal mb-4">Key Design Decisions</h3>
<p class="text-base text-text-primary leading-relaxed mb-4">
1. Gesture vocabulary over menu hierarchy:<br>
Traditional mobile interfaces rely on spatial memory: users remember where buttons live on screen. That model fails completely for blind users in motion. I relied on user feedback to design a gesture vocabulary using swipe patterns and tap zones that users could execute confidently without visual reference. The tradeoff: learnability. Although we were leveraging standard Speak Screen and VoiceOver functionality, each new application requires upfront training and familiarization that a visual menu does not. This led directly to the onboarding approach below.
</p>
<p class="text-base text-text-primary leading-relaxed mb-4">2. Audio landscape as primary feedback:
Our developer leveraged LiDAR data and spatial audio to create a 3D soundscape that represented the user's environment. I worked closely with the team on audio engineering to refine how different sounds would represent various objects and distances. For example, closer objects produced louder, more distinct sounds, while distant objects were softer and more diffuse. This design choice allowed users to build a mental map of their surroundings through auditory cues alone. Speed of scan, frequency and sound type were all variables we tested and refined through user feedback.
</p>
<p class="text-base text-text-primary leading-relaxed">
3. Progressive onboarding through documentation:
Because the interface had no visual safety net, users needed to build confidence before real-world use. I developed the Instructions For Use at a sixth-grade reading level that introduced the audio vocabulary incrementally. I advocated for an incremental approach that built on blind users' existing spatial navigation abilities. Familiar skills reinforced new learning, building confidence before introducing complexity. We ensured that testers could successfully navigate simple environments before progressing to more complex scenarios.
</p>
</div>
<!-- Onboarding Image with Caption -->
<figure>
<img src="images/eyedar_wireframes_user_research.png" alt="Annotated wireframes for Eyedar onboarding and scanning"
class="w-full rounded-xl cursor-pointer hover:opacity-90 transition-opacity lightbox-trigger">
<figcaption class="text-sm text-neutral-600 mt-3 text-center">
Annotated wireframes for onboarding and active scanning. The Welcome screen introduces the gesture vocabulary; the scan screen shows the LIDAR view with spatial audio cues mapped to user actions.
</figcaption>
</figure>
<div>
<h3 class="text-2xl text-text-primary font-normal mb-4">Outcome</h3>
<p class="text-base text-text-primary leading-relaxed">Eyedar launched as a functional application and received industry recognition including 2x Grand Clio Health, 2x Gold Clio Health, Silver Pencil at One Show, Silver Cannes Lion, and a Manny Award.</p>
</div>
<div>
<h3 class="text-2xl text-text-primary font-normal mb-4">Reflection</h3>
<p class="text-base text-text-primary leading-relaxed">This project fundamentally changed how I approach accessibility. Compliance checklists are a starting point, not a destination. The real work is designing for lived experience, which requires direct collaboration with the people you're designing for. I've carried that principle into every project since.</p>
</div>
</div>
<!-- Right: Metadata Sidebar -->
<div class="md:w-[360px] md:flex-shrink-0 p-[24px] flex flex-col gap-[24px] h-fit">
<div>
<h4 class="text-sm text-accent uppercase mb-2 tracking-wide">Client</h4>
<p class="text-base text-text-primary">Horizon Pharmaceuticals</p>
</div>
<div>
<h4 class="text-sm text-accent uppercase mb-2 tracking-wide">Discipline</h4>
<p class="text-base text-text-primary">Accessibility Design<br>Application Design<br>Interaction Design<br>UX Writing</p>
</div>
<div>
<h4 class="text-sm text-accent uppercase mb-2 tracking-wide">Role</h4>
<p class="text-base text-text-primary">Senior UX Architect</p>
</div>
<div>
<h4 class="text-sm text-accent uppercase mb-2 tracking-wide">Year</h4>
<p class="text-base text-text-primary">2022</p>
</div>
<div>
<h4 class="text-sm text-accent uppercase mb-2 tracking-wide">Technologies</h4>
<p class="text-base text-text-primary">LIDAR Sensors<br>Spatial Audio<br>iOS<br>Scan Speak<br>VoiceOver</p>
</div>
<div>
<h4 class="text-sm text-accent uppercase mb-2 tracking-wide">Awards</h4>
<p class="text-base text-text-primary">
2x Grand Clio Health<br>
2x Gold Clio Health<br>
3x Gold Pencil, One Show<br>
Silver Cannes Lion<br>
Manny Award
</p>
</div>
</div>
</div>
</section>
<!-- SPATIAL AUDIO DEMO -->
<section class="px-4 md:px-0 py-8 mb-12">
<div class="max-w-[1200px] mx-auto">
<figure class="my-8">
<img src="images/eyedar_nick_01.png" alt="Eyedar demonstration" class="w-full rounded-xl cursor-pointer hover:opacity-90 transition-opacity lightbox-trigger">
<figcaption class="text-sm text-neutral-600 mt-3 text-center">
User testing session validating our approach to Eyedar's spatial audio navigation.
</figcaption>
</figure>
</div>
</section>
<!-- EXTERNAL LINK -->
<section class="px-4 md:px-0 py-8 mb-12">
<div class="max-w-[1200px] mx-auto">
<a href="https://eye-dar.com/" target="_blank" rel="noopener noreferrer" class="inline-flex items-center gap-2 text-accent hover:underline text-lg">
Visit Eyedar.com →
</a>
</div>
</section>
<!-- BACK TO WORK -->
<section class="px-4 md:px-0 py-8 mb-12">
<div class="max-w-[1200px] mx-auto">
<a href="index.html" class="inline-flex items-center gap-2 text-accent hover:underline font-lato">
← Back to Work
</a>
</div>
</section>
<!-- FOOTER -->
<footer class="bg-[#FFFEF9] border-t border-[#F6F6F6] px-4 pt-6 pb-16 md:pb-8 flex flex-col items-center justify-center gap-4 text-sm text-black text-center">
<p>© 2026 Jeff Halpin</p>
<div class="flex items-center justify-center gap-6">
<a href="https://www.linkedin.com/in/jeffrey-halpin/" target="_blank" rel="noopener noreferrer"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 16 16">
<path d="M0 1.146C0 .513.526 0 1.175 0h13.65C15.474 0 16 .513 16 1.146v13.708c0 .633-.526 1.146-1.175 1.146H1.175C.526 16 0 15.487 0 14.854zm4.943 12.248V6.169H2.542v7.225zm-1.2-8.212c.837 0 1.358-.554 1.358-1.248-.015-.709-.52-1.248-1.342-1.248S2.4 3.226 2.4 3.934c0 .694.521 1.248 1.327 1.248zm4.908 8.212V9.359c0-.216.016-.432.08-.586.173-.431.568-.878 1.232-.878.869 0 1.216.662 1.216 1.634v3.865h2.401V9.25c0-2.22-1.184-3.252-2.764-3.252-1.274 0-1.845.7-2.165 1.193v.025h-.016l.016-.025V6.169h-2.4c.03.678 0 7.225 0 7.225z"/>
</svg></a>
<a href="https://github.com/JDHalpin" target="_blank" rel="noopener noreferrer"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 16 16">
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8"/>
</svg></a>
<a href="mailto:jeff.halpin@gmail.com"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 16 16">
<path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1zm13 2.383-4.708 2.825L15 11.105zm-.034 6.876-5.64-3.471L8 9.583l-1.326-.795-5.64 3.47A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.741M1 11.105l4.708-2.897L1 5.383z"/>
</svg></a>
</div>
</footer>
<!-- LIGHTBOX MODAL -->
<div id="lightbox" class="hidden fixed inset-0 z-50 bg-black/80 flex items-center justify-center p-4">
<button id="lightbox-close" class="absolute top-4 right-4 text-white text-3xl hover:text-accent">×</button>
<img id="lightbox-img" src="" alt="" class="max-w-full max-h-[90vh] rounded-lg">
</div>
<script>
// Mobile menu logic
const menuToggle = document.getElementById('menu-toggle');
const menuClose = document.getElementById('menu-close');
const mobileMenu = document.getElementById('mobile-menu');
menuToggle?.addEventListener('click', () => {
mobileMenu.classList.remove('hidden');
document.body.classList.add('overflow-hidden');
});
menuClose?.addEventListener('click', () => {
mobileMenu.classList.add('hidden');
document.body.classList.remove('overflow-hidden');
});
mobileMenu?.addEventListener('click', (e) => {
if (e.target === mobileMenu) {
mobileMenu.classList.add('hidden');
document.body.classList.remove('overflow-hidden');
}
});
document.querySelectorAll('#mobile-menu a').forEach(link => {
link.addEventListener('click', () => {
mobileMenu.classList.add('hidden');
document.body.classList.remove('overflow-hidden');
});
});
// Lightbox functionality
const lightbox = document.getElementById('lightbox');
const lightboxImg = document.getElementById('lightbox-img');
const lightboxClose = document.getElementById('lightbox-close');
// Open lightbox on image click
document.querySelectorAll('.lightbox-trigger').forEach(img => {
img.addEventListener('click', () => {
lightboxImg.src = img.src;
lightboxImg.alt = img.alt;
lightbox.classList.remove('hidden');
document.body.classList.add('overflow-hidden');
});
});
// Close lightbox on close button click
lightboxClose?.addEventListener('click', () => {
lightbox.classList.add('hidden');
document.body.classList.remove('overflow-hidden');
});
// Close lightbox on backdrop click
lightbox?.addEventListener('click', (e) => {
if (e.target === lightbox) {
lightbox.classList.add('hidden');
document.body.classList.remove('overflow-hidden');
}
});
// Close lightbox on Escape key
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && !lightbox.classList.contains('hidden')) {
lightbox.classList.add('hidden');
document.body.classList.remove('overflow-hidden');
}
});
</script>
</body>
</html>