<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Craig Dennis — Product Designer]]></title><description><![CDATA[I build things that work—whether that’s to drive adoption, grow revenue, or help cross-functional teams move faster.]]></description><link>https://craigmdennis.com/</link><image><url>https://craigmdennis.com/favicon.png</url><title>Craig Dennis — Product Designer</title><link>https://craigmdennis.com/</link></image><generator>Ghost 6.30</generator><lastBuildDate>Tue, 14 Apr 2026 11:54:23 GMT</lastBuildDate><atom:link href="https://craigmdennis.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Designing an invisible premium radio product for people who hate technology]]></title><description><![CDATA[<h3 id="my-dad-has-been-asking-the-same-question-for-months-how-can-we-listen-to-ad-free-radio-in-the-kitchen-without-upsetting-your-mother">My dad has been asking the same question for months: &quot;How can we listen to ad-free radio in the kitchen without upsetting your mother?&quot;</h3><p>The radio station in question has an app and is available on smart speakers but the kitchen is a sacred space for my mother.</p>]]></description><link>https://craigmdennis.com/designing-an-invisible-product-for-people-who-hate-technology/</link><guid isPermaLink="false">69430ad99d2cda0001dbeee8</guid><category><![CDATA[Hobby]]></category><category><![CDATA[Electronics]]></category><category><![CDATA[Code]]></category><category><![CDATA[AI]]></category><category><![CDATA[Design]]></category><dc:creator><![CDATA[Craig Dennis]]></dc:creator><pubDate>Tue, 23 Dec 2025 10:23:00 GMT</pubDate><media:content url="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2025/12/IMG_0619.jpeg" medium="image"/><content:encoded><![CDATA[<h3 id="my-dad-has-been-asking-the-same-question-for-months-how-can-we-listen-to-ad-free-radio-in-the-kitchen-without-upsetting-your-mother">My dad has been asking the same question for months: &quot;How can we listen to ad-free radio in the kitchen without upsetting your mother?&quot;</h3><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2025/12/IMG_0619.jpeg" alt="Designing an invisible premium radio product for people who hate technology"><p>The radio station in question has an app and is available on smart speakers but the kitchen is a sacred space for my mother. The only technology allowed is a 10 year old Denon Hi-Fi system and a landline telephone.</p><p>What I find amazing is <strong>they actively want to give this service their money</strong> and <strong>technology is making things <em>harder</em></strong>.<em> </em>The irony wasn&apos;t lost on me.</p><p>I&apos;m a designer. I work in tech. I should be able to build a device that can do this, right?</p><h1 id="vision">Vision</h1><h3 id="plug-in-the-device-%E2%86%92-radio-starts-playing">Plug in the device &#x2192; Radio starts playing</h3><p><strong>It really needs to be that simple. </strong>That level of simplicity is, in fact, incredibly difficult to achieve.</p><h3 id="thinking-like-a-designer">Thinking like a designer</h3><p>Who&apos;s the audience, what are they familiar with, what feedback do they need when there&apos;s no interface? What happens when wifi drops, or the stream fails, or their subscription expires? These are types of experiential risks I consider all the time at work.</p><h3 id="my-approach">My approach</h3><p>There will be no visual interface so everything needs to happen automatically, invisibly, and only make a sound when it&#x2019;s really important. </p><p><strong>Boot sound &#x2014;</strong>Acknowledge that the device is on (there are also some LEDs as visual indicators). Unfortunately there is no way to create a true boot sound and nor is there an onboard speaker so playing this after 20 seconds will have to do.</p><p><strong>Status messages &#x2014; </strong>Spoken messages (rather than sounds) that loop every 30 seconds that include instructions on how to &apos;fix&apos; the issue &quot;Turn it off and on again&quot;. I used ElevenLabs to generate messages in an approachable British accent.</p><p><strong>Auto-connect</strong> &#x2014; I know their Wi-Fi name and password so I created a dummy Wi-FI network to test. This <em>should</em> allow the device to connect automatically when it arrives.</p><h2 id="this-cant-be-a-unique-problem">This can&apos;t be a unique problem</h2><p>What about actually streaming the radio? I can&apos;t be the only one to face this issue, or a version of it. I subscribed to the station and ordered a Raspberry Pi, then searched for ways to stream radio on it.</p><p>I found a few music servers but only Lyrion Music Server was mature enough and had plugins that support the station I needed. Install it, add the plugin, log-in, click play and DONE. Almost. It was unstable, and difficult to automate.</p><p>I spent hours working through the documentation, building watchdog services to monitor and restart the audio. And every morning it was dead. Checking the logs gave no specific errors. </p><p>Troubleshooting for my parents needs to be no more complicated than &quot;unplug it and plug it back in&quot;. This was not going to work. Back to the drawing board.</p><h2 id="the-solution">The solution</h2><p>I was overthinking things. If a third-party plugin could stream this app-only radio station then surely I could as well. I instructed Claude Code to inspect the plugin and the stream URL (from the first-party app) and reverse engineer a way for me to get direct access. We discovered the URL does not contain API keys or be obfuscated in any way; it simply contains the user ID of the paying user (so it does some internal check before playing).</p><p>This means if I could get the user ID, I could use the stream directly and drop Lyrion entirely. This solved 95% of my problems and the stream ran for days while I was working through other parts of the experience.</p><p>With the hardware issues sorted I needed to work on how I would explain, even to my father, how to put it all together.</p><h2 id="a-quick-start-guide">A quick-start guide</h2><p>I designed and printed a card to sit just inside the lid of an Apple TV box that I&apos;m shipping everything in. My dad will set it up and he&apos;s more tech-savvy. This was just a bit of fun.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2025/12/image-5.png" class="kg-image" alt="Designing an invisible premium radio product for people who hate technology" loading="lazy" width="2000" height="1415" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2025/12/image-5.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2025/12/image-5.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1600/2025/12/image-5.png 1600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w2400/2025/12/image-5.png 2400w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Card front: With intro text and the image of an old radio on the right</span></figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2025/12/image-15.png" class="kg-image" alt="Designing an invisible premium radio product for people who hate technology" loading="lazy" width="2000" height="1415" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2025/12/image-15.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2025/12/image-15.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1600/2025/12/image-15.png 1600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w2400/2025/12/image-15.png 2400w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Back: 5 Bullets and a QR code</span></figcaption></figure><p>Great! Now they know to plug in the antenna first, where to plug in the cables, and what to do <em>before</em> turning on the device (so they can hear the personal message I&apos;ve recorded for when the device is warming up).</p><h2 id="packaging">Packaging</h2><p>Why stop at a quick-start guide? Let&apos;s cover up the fact that it&apos;s an Apple TV box. After all I don&apos;t want them to think I&apos;ve bought them an actual Apple TV; <strong>that&apos;s the last thing they want.</strong></p><figure class="kg-card kg-video-card kg-width-regular" data-kg-thumbnail="https://craigmdennis.com/content/media/2025/12/IMG_0732---01_thumb.jpg" data-kg-custom-thumbnail>
            <div class="kg-video-container">
                <video src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/media/2025/12/IMG_0732---01.mp4" poster="https://img.spacergif.org/v1/1152x2048/0a/spacer.png" width="1152" height="2048" loop autoplay muted playsinline preload="metadata" style="background: transparent url(&apos;https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/media/2025/12/IMG_0732---01_thumb.jpg&apos;) 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"/>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"/>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:17</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1&#xD7;</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"/>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"/>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            
        </figure><figure class="kg-card kg-image-card"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2025/12/image-12.png" class="kg-image" alt="Designing an invisible premium radio product for people who hate technology" loading="lazy" width="2000" height="2771" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2025/12/image-12.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2025/12/image-12.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1600/2025/12/image-12.png 1600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2025/12/image-12.png 2100w" sizes="(min-width: 720px) 720px"></figure><p>I had some fun copying the technical details from the side of the Apple TV. I don&apos;t know if they&apos;ll read it but it was fun and tongue-in-cheek.</p><figure class="kg-card kg-image-card"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2025/12/image-11.png" class="kg-image" alt="Designing an invisible premium radio product for people who hate technology" loading="lazy" width="2000" height="1429" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2025/12/image-11.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2025/12/image-11.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1600/2025/12/image-11.png 1600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2025/12/image-11.png 2100w" sizes="(min-width: 720px) 720px"></figure><p></p><h1 id="the-finished-product">The finished product</h1><h3 id="the-always-on-zero-setup-plug-and-play-premium-radio-streaming-box"><strong>The always-on, zero-setup, plug-and-play Premium Radio Streaming Box.</strong></h3><figure class="kg-card kg-image-card"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2025/12/59E68137-2B5E-489B-869E-AF0E352AA1AA_1_105_c.jpeg" class="kg-image" alt="Designing an invisible premium radio product for people who hate technology" loading="lazy" width="1024" height="768" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2025/12/59E68137-2B5E-489B-869E-AF0E352AA1AA_1_105_c.jpeg 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2025/12/59E68137-2B5E-489B-869E-AF0E352AA1AA_1_105_c.jpeg 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2025/12/59E68137-2B5E-489B-869E-AF0E352AA1AA_1_105_c.jpeg 1024w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-video-card kg-width-regular" data-kg-thumbnail="https://craigmdennis.com/content/media/2025/12/Timmer-Final_thumb.jpg" data-kg-custom-thumbnail>
            <div class="kg-video-container">
                <video src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/media/2025/12/Timmer-Final.mp4" poster="https://img.spacergif.org/v1/360x640/0a/spacer.png" width="360" height="640" playsinline preload="metadata" style="background: transparent url(&apos;https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/media/2025/12/Timmer-Final_thumb.jpg&apos;) 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"/>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"/>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:39</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1&#xD7;</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"/>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"/>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            
        </figure><h1 id="the-reveal"><strong>The reveal</strong></h1><p>Christmas morning, I watched the video call as my dad unwrapped the box. &quot;Oh, that&apos;s great,&quot; he said, genuinely pleased. &quot;Where did you find that?&quot;</p><p><em>Find</em>&#xA0;it. Not&#xA0;<em>make</em>&#xA0;it.</p><p>For a moment I considered explaining the week I&apos;d spent debugging Lyrion, the hours on the self-healing uptime monitoring, CLI tooling, the ElevenLabs voice generation, the tongue-in-cheek packaging I&apos;d laboured over (maybe one day I will) but right then I simply replied: &quot;I made it&quot;.</p><p>We hung up. He went to set it up.</p><p><strong>A few minutes later</strong> my phone buzzed with an Uptime Kuma alert: Device online. I opened my laptop, SSH&apos;d in through Tailscale and ran a status check:</p><pre><code>System uptime: 7 minutes  
Stream status: Playing
Playback duration: 6:30</code></pre><p>It worked.</p><p><strong>My parents experienced it as magic.</strong> Plug it in, radio plays. I experienced it as a well-designed system. Monitoring dashboards, remote SSH access, automated logging.</p><p>Two completely different experiences of the same product.</p><p>The CLI I&apos;d carefully designed? The watchdog service? The backup documentation? None of that exists in my parents&apos; mental model. For them, it&apos;s just a box that plays radio that they&apos;ll never think about. To them, &quot;AUX&quot; on the Denon Hi-Fi now means &apos;ad free radio&apos;. </p><h4 id="i-did-my-job-so-well-that-they-assumed-someone-else-made-it">I did my job so well that they assumed someone else made it.</h4><figure class="kg-card kg-image-card"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2026/01/B43C6B56-6D73-4F37-AF0C-57E155CFCF50-1.jpeg" class="kg-image" alt="Designing an invisible premium radio product for people who hate technology" loading="lazy" width="1536" height="960" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2026/01/B43C6B56-6D73-4F37-AF0C-57E155CFCF50-1.jpeg 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2026/01/B43C6B56-6D73-4F37-AF0C-57E155CFCF50-1.jpeg 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2026/01/B43C6B56-6D73-4F37-AF0C-57E155CFCF50-1.jpeg 1536w" sizes="(min-width: 720px) 720px"></figure><hr><h1 id="designing-my-experience">Designing <em>my</em> experience</h1><p>I knew I was going to be administrating this and fixing anything that I couldn&apos;t account for; but how can I do that from 2500km away? And how can I make my experience less painful and maybe even enjoyable?</p><h2 id="the-ux-of-a-command-line-utility">The UX of a command line utility</h2><p>As I used the terminal more I realised that it, too, requires the same care and attention as any other interface. How can I make this intuitive, predictable, and usable. I found a great resource <a href="https://clig.dev/?ref=craigmdennis.com">https://clig.dev/</a> which has a wealth of  HCI guidance for terminal output.</p><figure class="kg-card kg-image-card"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2025/12/Terminal-2025-12-27-at-21.23.51@2x-1.png" class="kg-image" alt="Designing an invisible premium radio product for people who hate technology" loading="lazy" width="1140" height="1022" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2025/12/Terminal-2025-12-27-at-21.23.51@2x-1.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2025/12/Terminal-2025-12-27-at-21.23.51@2x-1.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2025/12/Terminal-2025-12-27-at-21.23.51@2x-1.png 1140w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2025/12/Terminal-2025-12-27-at-23.30.34@2x-2.png" class="kg-image" alt="Designing an invisible premium radio product for people who hate technology" loading="lazy" width="1140" height="742" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2025/12/Terminal-2025-12-27-at-23.30.34@2x-2.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2025/12/Terminal-2025-12-27-at-23.30.34@2x-2.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2025/12/Terminal-2025-12-27-at-23.30.34@2x-2.png 1140w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2025/12/Terminal-2025-12-28-at-00.02.08@2x-1.png" class="kg-image" alt="Designing an invisible premium radio product for people who hate technology" loading="lazy" width="1140" height="742" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2025/12/Terminal-2025-12-28-at-00.02.08@2x-1.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2025/12/Terminal-2025-12-28-at-00.02.08@2x-1.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2025/12/Terminal-2025-12-28-at-00.02.08@2x-1.png 1140w" sizes="(min-width: 720px) 720px"></figure><p><strong>Access</strong>&#xA0;&#x2014; I can use Tailscale to ssh into the Pi as if it were at my desk.</p><p><strong>Monitoring</strong> &#x2014; I already use Uptime Kuma on my homelab so I can add a monitor for the Tailscale IP of the device and detect basic connectivity issues and when it&apos;s powered on for the first time.</p><p><strong>Logging &#x2014; </strong>I added detailed logging to track down issues and get a radio &apos;uptime&apos; percentage. I want over 95% because this is a set and forget, always-on device. </p><p><strong>Watchdog &#x2014; </strong>I need something that actively monitors internet connectivity, audio output, memory usage etc. and can restart services or the whole device automatically if necessary.</p><p><strong>Backup &#x2014; </strong>I want to be able to back up all relevant files that I change. I also want to include included a restore document for file locations and commands to run after.</p><p><strong>Readme &#x2014; </strong>I don&apos;t know when the next time I will need to do any work on this machine. I will forget what I&apos;ve done, why, and where. Keeping a <code>README.md</code> file on disk means I&apos;ll be able to get up to speed quickly. It should also be backed up.</p>]]></content:encoded></item><item><title><![CDATA[Practical Designer Performance Reviews]]></title><description><![CDATA[A practical way to run designer performance reviews using a living document with clear keep/start/stop feedback, goal tracking, and AI tools to make you more efficient.]]></description><link>https://craigmdennis.com/practical-designer-performance-reviews/</link><guid isPermaLink="false">68756344df606a0001629aea</guid><category><![CDATA[Design Management]]></category><dc:creator><![CDATA[Craig Dennis]]></dc:creator><pubDate>Mon, 14 Jul 2025 21:32:02 GMT</pubDate><media:content url="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2025/07/photo-1578450671530-5b6a7c9f32a8.jpeg" medium="image"/><content:encoded><![CDATA[<img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2025/07/photo-1578450671530-5b6a7c9f32a8.jpeg" alt="Practical Designer Performance Reviews"><p>In many early-stage startups, performance reviews can feel like box&#x2011;ticking exercises. The process is often high&#x2011;level, managed through generic Google forms, and leaves designers with vague comments or bland affirmations. Without actionable feedback or a clear path to promotion, both manager and direct report end up frustrated.</p><p>Over the last few years, I&#x2019;ve been refining a system that brings clarity and continuity to designer performance reviews. The secret: take good notes and treat your feedback as a living document and tie everything back to real, specific work.</p><hr><h2 id="the-ratings-system-more-than-just-successful">The Ratings System: More Than Just &quot;Successful&quot;</h2><p>Most organisations use a simple status rubric. Ours includes five choices:</p><ul><li><strong>Role Model</strong></li><li><strong>Exceeds Expectations</strong></li><li><strong>Successful</strong></li><li><strong>Developing</strong></li><li><strong>Not Delivering</strong></li></ul><p>&quot;Successful&quot; is the baseline. Nothing to complain about. You&apos;re rock solid.</p><p>For designers aiming to grow though, you need to be hitting&#xA0;<strong>Exceeds Expectations</strong>. It helps signals readiness for the next level. Promotions tend to reward work you&apos;re already doing.</p><p>For feedback we also write some bullets for what people should keep, start, and stop doing. This is useful but is often biased to the last few weeks.</p><hr><h2 id="how-i-track-reviews-a-living-google-doc">How I Track Reviews: A Living Google Doc</h2><p>Rather than juggling multiple forms, I keep one shared Google Doc per direct report. Each review date gets its own page, so past discussions never vanish into inboxes.</p><ol><li><strong>Status</strong>&#xA0;(pick one of the five above)</li><li><strong>Keep Doing, Start Doing, Stop Doing</strong></li><li><strong>From Last Time</strong></li><li><strong>For Next Time</strong></li></ol><p>This setup means every conversation builds on the last. Copy, paste, and edit. There&#x2019;s no reinventing the wheel for each review (though I am always open to feedback).</p><p>Every bullet needs to tie directly to real work, both successes and failures, and maps back to one of our feedback buckets.</p><hr><h2 id="goal-tracking-that-actually-works">Goal Tracking That Actually Works</h2><p>Review time isn&#x2019;t just a status update, it&#x2019;s a checkpoint on past commitments and future direction; all in one place.</p><ul><li><strong>Unchecked:</strong>&#xA0;We didn&#x2019;t hit this goal. Let&#x2019;s either re-commit or swap in a new, higher-priority objective.</li><li><strong>Intermediate:</strong>&#xA0;We made progress. Keep it rolling or pivot scope.</li><li><strong>Checked:</strong>&#xA0;Goal achieved! Time to celebrate and pick a fresh challenge.</li></ul><p>Because goals live alongside feedback in the same document, revisiting them is as simple as ticking boxes and editing a line or two. The best thing is that you can scroll back through time and see your progress.</p><p><strong>Anonymised Example:</strong></p><pre><code class="language-text">AREAS OF OPPORTUNITY:
From last time:
[-] Embed user research findings directly into sprint planning
[ ] Adjust fidelity of prototypes based on project phase
[x] Lead design reviews for at least one major feature launch</code></pre><hr><h2 id="designing-for-promotion">Designing for Promotion</h2><p>Promotion isn&#x2019;t about higher fidelity mockups or pixel perfection; it&#x2019;s about your problem solving, visibility, credibility, and&#x2014;most importantly&#x2014;your impact. That&apos;s how a business views your value.</p><p>Here&#x2019;s how I map next-role behaviours onto today&#x2019;s work:</p><p><strong>Keep doing</strong><br>Ensure you choose something that they&apos;re <em>already</em> doing that maps to behaviours needed for their next role; even if they&apos;re only doing them loosely or not deliberately. Call them out as positives to reinforce the behaviour.</p><p><strong>Start doing</strong><br>Pick one or two things that can easily augment their existing behaviour. Make sure they&apos;re not a huge leap from where they are now. Remember that they have to do their job <em>as well</em> as these new things aimed at promotion.</p><p><strong>Stop doing</strong><br>Identify behaviours that are having the opposite effect and highlight ways to channel this behaviour. This could be related to communication, professionalism, proactivity. If it&apos;s related to work quality (which is important to remember) then this person is probably not ready for promotion.</p><p><strong>Areas of opportunity (aka goals)</strong><br>Take the high level keep, start, and stop, and translate them into 3 specific, actionable, and achievable goal.</p><pre><code>For next time:
- Mentor a junior designer through an entire feature cycle, from discovery to delivery
- Demonstrate a quantifiable uplift in user activation metrics (e.g., +10% sign-up completion rate)
- Initiate bi-weekly design critique sessions with product managers to foster continual learning</code></pre><p>This clarity helps designers practice the behaviours that define a lead role, long before the promotion conversation.</p><h3 id="put-it-all-together">Put it all together</h3><pre><code class="language-text">15 June 2025

Rating: Exceeds Expectations

KEEP DOING:
- Conducting rapid user journey sketches before high-fidelity mocks
- Collaborating with the data team early to ground designs in real user insights
- Sharing clickable prototypes in #design-review to gather cross-functional feedback

START DOING:
- Incorporating accessibility checks into initial wireframes to catch issues sooner
- Running small-scale A/B tests on key interface changes before full release

STOP DOING:
- Keeping design rationale hidden in private notes; move context and decisions into our team wiki for transparency

AREAS OF OPPORTUNITY:
From last time:
[-] Embed user research findings directly into sprint planning
[x] Adjust fidelity of prototypes based on project phase
[x] Lead design reviews for at least one major feature launch

For next time:
- Mentor a junior designer through an entire feature cycle, from discovery to delivery
- Demonstrate a quantifiable uplift in user activation metrics (e.g., +10% sign-up completion rate)
- Initiate bi-weekly design critique sessions with product managers to foster continual learning</code></pre><hr><h2 id="notes-memory">Notes &gt; Memory</h2><p>Relying on memory is a recipe for recency bias. Notes, captured in the moment, give you a reliable reference. I use Obsidian for a permanent, linked record:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2025/07/Obsidian-2025-07-14-at-23.08.38@2x.png" class="kg-image" alt="Practical Designer Performance Reviews" loading="lazy" width="2000" height="1317" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2025/07/Obsidian-2025-07-14-at-23.08.38@2x.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2025/07/Obsidian-2025-07-14-at-23.08.38@2x.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1600/2025/07/Obsidian-2025-07-14-at-23.08.38@2x.png 1600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2025/07/Obsidian-2025-07-14-at-23.08.38@2x.png 2308w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Graph view shows the interconnectedness of notes over time</span></figcaption></figure><ol><li><strong>People</strong>: One note per direct report in a folder.</li><li><strong>Date-stamped one-on-ones</strong>: Quick bullet notes with links to project docs.</li><li><strong>Graph links</strong>: Cross-reference mentions of people, projects, and feedback so nothing falls through the cracks.</li></ol><p>When it&#x2019;s review time, I have a searchable history of meetings, project outcomes, and side conversations.</p><hr><h2 id="supercharging-reviews-with-ai">Supercharging Reviews with AI</h2><p>To speed up drafting, I leverage an <a href="https://github.com/MarkusPfundstein/mcp-obsidian?ref=craigmdennis.com">Obsidian &#x2192; MCP &#x2192; Claude plugin</a> that turns my notes into a knowledge-base. This only works if you take good notes of course. The benefit is surfacing my own thoughts and content without having to manually sift through hundreds of files.</p><p><strong>Workflow:</strong></p><ol><li>Prompt Claude:</li></ol><pre><code class="language-text">Based on my Obsidian notes for [Name], identify one behaviour Keep doing, one to Start doing, and one to Stop doing for a mid-level to Senior transition. 

Tie each to real examples from our past six months of projects.

Provide links to the source files for me to review and the reasoning behind your suggestions.</code></pre><ol start="2"><li>Claude returns draft bullets and sources for me to review</li><li>I review, reword, and add to my living document before sharing.</li></ol><p>This hybrid approach saves hours and keeps feedback grounded in my own observations.</p><hr><h2 id="preparation-and-reflection">Preparation and Reflection</h2><p>Great reviews take prep. I block:</p><ul><li><strong>Weekly note sprint (30&#x202F;min):</strong>&#xA0;Update one-on-one notes and link new projects. Reflect on team and individual progress. I find the <a href="https://en.wikipedia.org/wiki/Tuckman%27s_stages_of_group_development?ref=craigmdennis.com">Tuckman model</a> a useful at the team level. </li><li><strong>Review prep (60&#x202F;min):</strong>&#xA0;Skim your feedback doc, adjust bullets, and draft status updates.</li><li><strong>Review 1:1 (60 mins):</strong> Discuss with your direct report. Explain your rationale. Solicit feedback and their thoughts. Do they agree/disagree with your assessment? Do they agree with your goals? Work with them to set new ones and Note it. </li></ul><p>A scheduled deep-dive trumps scrambling the day before. Your future self (and your team) will thank you.</p><hr><h2 id="conclusion">Conclusion</h2><p>When I first used this format not long after becoming a manager myself, <em>my</em> manager at the time said they almost screenshot it and posted it on LinkedIn as an example of how reviews <em>should </em>be done.</p><p>When reviews are authentic, designers grow. A living document, anchored in outcomes, plus a dash of AI, makes feedback fast, fair, and forward-looking.</p>]]></content:encoded></item><item><title><![CDATA[Give The Difficult Feedback]]></title><description><![CDATA[Giving tough feedback can be its own challenge, especially for new managers. Clear, constructive critique builds trust, drives growth, and strengthens teams.]]></description><link>https://craigmdennis.com/give-the-difficult-feedback/</link><guid isPermaLink="false">68679141eae2970001062c3a</guid><category><![CDATA[Leadership]]></category><category><![CDATA[Reflection]]></category><category><![CDATA[Soft Skills]]></category><dc:creator><![CDATA[Craig Dennis]]></dc:creator><pubDate>Fri, 04 Jul 2025 09:19:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1642873965200-4dd3753336b2?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDE5fHxzYWZldHl8ZW58MHx8fHwxNzUxNjIyMjU0fDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1642873965200-4dd3753336b2?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDE5fHxzYWZldHl8ZW58MHx8fHwxNzUxNjIyMjU0fDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" alt="Give The Difficult Feedback"><p>Everyone <a href="https://craigmdennis.com/you-will-screw-up/" rel="noreferrer">screws up</a>. Progress starts the moment you give voice to the problem and <strong>bring it into the light</strong>. </p><h2 id="why-giving-feedback-feels-hard">Why Giving Feedback Feels Hard</h2><p>You are probably a new manager. You have never had to tell someone that something about their work is not meeting expectations. Worse, you still carry a few scars from badly delivered feedback in your own career, so you project that pain and pull your punches.</p><p>Ask yourself how you would want to hear it if these mistakes were yours. You would want to be told, and told straight; with clarity and a plan to fix it. <strong>Feedback feels hard for the giver, yet it is a gift for the receiver.</strong></p><h2 id="why-direct-feedback-matters">Why Direct Feedback Matters</h2><p>Design work is subjective but business outcomes are not. When someone drifts from established patterns, processes, or quality bars; the product suffers, timelines slip, and engineering slows. What you tolerate becomes the culture.</p><p>Clear, directional, actionable feedback protects standards, accelerates iteration, and signals that you care about growth more than comfort.</p><h2 id="prime-the-conversation">Prime the Conversation</h2><p>Open with a straight signal:</p><blockquote>I need to give you some direct feedback.</blockquote><p>One sentence sets expectations and switches the receiver into listening mode. No coffee-chat preamble. Capable people usually sense when they are missing the mark; you are just making the implicit explicit.</p><h2 id="feedback-is-meant-to-help">Feedback Is Meant to Help</h2><p>Feedback that is specific, unemotional, and tied to impact is not a personal attack, (though it can still feel that way). Skip vague phrases like &quot;people have noticed.&quot; State the impact and probe for the thinking that produced it. Never assume you know the reason.<strong> You can never truly improve without understanding the &apos;why&apos;.</strong></p><p><strong>Impact &#x2192;  Behaviour &#x2192;  Curiosity</strong></p><blockquote>&quot;Engineering are having to rework more designs recently because they stray from our patterns. Can you walk me through your choices on the latest release? I&apos;d like to understand this from your perspective.&quot;</blockquote><h2 id="tailor-feedback-to-the-behaviour">Tailor Feedback to the Behaviour</h2><p>Pinpoint the category before you respond.</p><p><strong>Attitude</strong> &#x2013; how someone shows up in meetings<br><strong>Effort</strong> &#x2013; pace and volume of output<br><strong>Quality</strong> &#x2013; whether deliverables meet the bar<br><strong>Process</strong> &#x2013; alignment with systems and timelines</p><p>Whatever the category, run Observation &#x2192; Impact &#x2192; Action and finish with a concrete next step.</p><h2 id="make-it-part-of-the-review-cycle">Make It Part of the Review Cycle</h2><p>Capture each item and an agreed action in a shared doc. Revisit progress in every one-on-one. Quarterly or biannual reviews then become confirmation, not a surprise.</p><p>Focus each one-on-one on one theme until momentum is clear, then move on. You&apos;re not looking for perfection, just progress.</p><h2 id="turning-feedback-into-weekly-habits">Turning Feedback Into Weekly Habits</h2><p>Feedback sticks when it turns into routine.</p><p>Anchor the action step to your weekly one-on-one. &quot;We&apos;ll check in next week so keep a note of ways you think you&apos;ve addressed this and I will as well.&quot;</p><p>Define what better looks like: a behaviour you can see or a deliverable you can inspect. Remember to make it clear and definitive. &quot;Post an in-progress design in Slack every day this week&quot;</p><p>Add a small <a href="https://craigmdennis.com/the-power-of-side-quests-to-level-up-your-team/" rel="noreferrer">side quest</a> that lets them practice the new behavior in a low-stakes context or lean in. This is normally something that might be difficult to observe directly.</p><p>Normalizing this cadence de-stigmatises feedback. It is just how we work.</p><h2 id="handling-pushback-with-safety-and-curiosity">Handling Pushback with Safety and Curiosity</h2><p>Prepare for an emotional response. Reinforce that one-on-ones are a safe space.</p><p><strong>Acknowledge</strong> &#x2013; &quot;It seems that this has caught you off guard.&quot;<br><strong>Probe</strong> &#x2013; &quot;Why do you think people have raised this?&quot;<br><strong>Guide reflection</strong> &#x2013; &quot;How prepared did you feel for last week&apos;s meetings?&quot;<br><strong>Challenge your own assumptions</strong> &#x2013; &quot;Is there something happening that I should be aware of?&quot;</p><p>If insight does not emerge, agree on a visible experiment: &quot;We will debrief for five minutes after each meeting for two weeks.&quot; A persistent lack of self-awareness&#x2014;unfortunately&#x2014;should trigger a formal performance review path.</p><h2 id="translating-feedback-from-others">Translating Feedback From Others</h2><p>If a stakeholder gives feedback in public, address it right after the meeting: &quot;What do you think they meant by that?&quot; If the feedback comes to you privately, translate it through Observation &#x2192; Impact &#x2192; Action before passing it on. Emphasise the business consequence, not the personal critique.</p><h2 id="measuring-and-closing-the-loop">Measuring and Closing the Loop</h2><p>Most signals are qualitative but you can rate them 1 to 5 to track trend. Check with the original observers: &quot;Have you noticed a change?&quot; Look for new blind spots that surface as the old one shrinks. </p><p><strong>Direct feedback is not criticism; it is evidence that you believe improvement is possible and worth your time.</strong></p>]]></content:encoded></item><item><title><![CDATA[You Will Screw Up]]></title><description><![CDATA[Don’t be afraid of making mistakes. Instead, develop the resilience to fail, own it, and respond with clarity. ]]></description><link>https://craigmdennis.com/you-will-screw-up/</link><guid isPermaLink="false">6850a778c949f90001103365</guid><category><![CDATA[Leadership]]></category><category><![CDATA[Soft Skills]]></category><category><![CDATA[Reflection]]></category><dc:creator><![CDATA[Craig Dennis]]></dc:creator><pubDate>Mon, 16 Jun 2025 23:32:43 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1746469535771-71a672e8719f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8YWxsfDF8fHx8fHx8fDE3NTAxMTY3NjZ8&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1746469535771-71a672e8719f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8YWxsfDF8fHx8fHx8fDE3NTAxMTY3NjZ8&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" alt="You Will Screw Up"><p>Mistakes are inevitable. Teams will make them, leaders will make them, and the work will move forward anyway. The question isn&#x2019;t whether something will go wrong - it&#x2019;s how you show up when it does.</p><p><strong>Mistakes are part of the job</strong></p><p>Worrying about making a mistake can be more paralyzing than the mistake itself. It&#x2019;s better to assume that mistakes will happen and focus on how to respond when they do. The ability to recover is what builds resilience.</p><p><strong>The principle</strong></p><p>Here&#x2019;s the guidance I often give:</p><ul><li>Take action rather than trying to avoid failure.</li><li>You will make mistakes. And that&#x2019;s okay.</li><li>Never try and cover up your mistake. Instead, take accountability.</li><li>Lead the effort to recover from it - even if you can&#x2019;t fix it yourself.</li><li>What people will remember is how you responded.</li></ul><p>Mistakes should never be hidden, minimized, or redirected. The best course is to take ownership: &#x201C;That was me. I got it wrong.&#x201D; Then shift into action: gather the right people, ask the right questions, and help coordinate a path forward. You don&#x2019;t need to know the fix yourself, but you do need to lead the effort to get it fixed.</p><p>In the long run, it won&#x2019;t be the misstep that&#x2019;s remembered. It&#x2019;ll be the way it was handled - with honesty, ownership, and a willingness to learn.</p><p><strong>Lessons from experience</strong></p><p>When stepping into a more visible role, the pressure increases. There may be hesitation in making a call, or second-guessing after one is made. That tension is part of growth.</p><p>Mistakes aren&#x2019;t always about the decision itself - sometimes it&#x2019;s about how that decision is delivered. Acting with clarity and conviction is important, but so is leaving room for others to process.</p><p>The balance is difficult. That&#x2019;s what makes it valuable.</p>]]></content:encoded></item><item><title><![CDATA[The Power of Side Quests to Level-up Your Team]]></title><description><![CDATA[Want to grow real leaders? Give them side quests. Small, intentional challenges that build the muscles titles don’t—conflict, boundaries, and trust.]]></description><link>https://craigmdennis.com/the-power-of-side-quests-to-level-up-your-team/</link><guid isPermaLink="false">684c941c83698400019c315b</guid><category><![CDATA[Leadership]]></category><dc:creator><![CDATA[Craig Dennis]]></dc:creator><pubDate>Fri, 13 Jun 2025 21:21:54 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1662072628058-02df9c3a6ac5?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDJ8fFJQRyUyMGRpY2V8ZW58MHx8fHwxNzQ5ODQ5Nzg0fDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1662072628058-02df9c3a6ac5?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDJ8fFJQRyUyMGRpY2V8ZW58MHx8fHwxNzQ5ODQ5Nzg0fDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" alt="The Power of Side Quests to Level-up Your Team"><p>In the world of RPGs, side quests are optional missions that challenge characters to develop new skills, strengthen relationships, and prepare for the main story arc. In the workplace, side quests can serve the same purpose&#x2014;particularly when they focus on building soft skills like boundary setting, conflict resolution, and communication.</p><p>As a leader, you can use side quests to help team members grow beyond their core technical skills and learn how to manage themselves and others more effectively. These aren&#x2019;t just helpful tasks&#x2014;they&#x2019;re transformational.</p><h2 id="what-is-a-side-quest">What Is a Side Quest?</h2><p>A side quest is a deliberate developmental challenge. It&#x2019;s something you <em>assign</em> instead of <em>solving</em>. When a team member brings you a tough interpersonal or emotional issue, instead of taking the lead, you hand them a side quest: a specific, stretch-level task that confronts the problem directly.</p><p>This doesn&#x2019;t mean abandoning them. You guide, model, and support&#x2014;but they <em>own</em> the action.</p><h3 id="the-goal">The Goal:</h3><p>Not just resolution, but growth. Not just comfort, but capability.</p><h2 id="examples-of-side-quests">Examples of Side Quests</h2><p>Let&#x2019;s break down some real side quests:</p><h3 id="1-conflict-resolution">1.&#xA0;Conflict Resolution</h3><blockquote><em>Scenario:</em> &#x201C;Someone on the team said something that really upset me.&#x201D;</blockquote><p><strong>Side Quest Breakdown:</strong></p><ul><li>Ask: <em>What specifically upset you?</em> Help unpack meaning vs. intention.</li><li>Reframe: Could there be another interpretation?</li><li>Equip: Provide a conversation framework&#x2014;like &#x201C;When you said X, I felt Y.&#x201D;</li><li>Assign: Have them speak directly with the other person.</li></ul><p>You&#x2019;re not mediating. You&#x2019;re mentoring.</p><h3 id="2-boundary-setting">2.&#xA0;Boundary Setting</h3><blockquote><em>Scenario:</em> &#x201C;I keep getting pulled into work late at night.&#x201D;</blockquote><p><strong>Side Quest Breakdown:</strong></p><ul><li>Clarify expectations and acceptable boundaries.</li><li>Draft language together for a boundary-setting message.</li><li>Have them send it&#x2014;and reflect afterward.</li></ul><p>The quest builds assertiveness, not just solves the time problem.</p><h3 id="3-feedback-loops">3.&#xA0;Feedback Loops</h3><blockquote><em>Scenario:</em> &#x201C;I feel like my ideas don&#x2019;t get taken seriously.&#x201D;</blockquote><p><strong>Side Quest Breakdown:</strong></p><ul><li>Explore examples together.</li><li>Identify whether it&#x2019;s delivery, timing, or perception.</li><li>Task them with trying a revised approach and reporting back.</li></ul><p>They grow through pattern recognition and adaptation.</p><h2 id="what-happens-over-time">What Happens Over Time</h2><p>When you consistently use side quests, something powerful emerges:</p><h3 id="predictive-self-coaching">Predictive Self-Coaching</h3><p>You&#x2019;ll notice a shift in how team members talk to you:</p><ul><li><em>Before:</em> &#x201C;Here&#x2019;s my issue. What should I do?&#x201D;</li><li><em>Later:</em> &#x201C;Here&#x2019;s my issue. I think I know what you&#x2019;re going to say&#x2026;&#x201D;</li><li><em>Eventually:</em> &#x201C;Here&#x2019;s what happened. Here&#x2019;s how I handled it. What&#x2019;s your take?&#x201D;</li></ul><p>They start anticipating growth-oriented action. They internalize your frameworks. They begin to think like a lead.</p><h2 id="from-side-quests-to-leadership">From Side Quests to Leadership</h2><p>That&#x2019;s your signal.</p><p>When someone:</p><ul><li>Recognizes tough interpersonal challenges,</li><li>Applies structure to navigate them,</li><li>Takes ownership of outcomes,</li><li>Reflects and iterates&#x2014;</li></ul><p>They&#x2019;ve moved from being senior to being a <em>lead</em>. Not because of title or tenure, but because they now elevate others.</p><h2 id="tracking-the-journey">Tracking the Journey</h2><p>Side quests lose their power if they&#x2019;re forgotten. Growth is incremental, and without a way to reflect, measure, and revisit progress, the opportunity to reinforce learning fades.</p><p>That&#x2019;s why tracking matters&#x2014;not in a bureaucratic, performance-review sense, but as an intentional act of leadership.</p><p>When you assign a side quest, treat it as a meaningful developmental step. Note it. Capture the context, the challenge, and the timeframe. Then, create a thread&#x2014;something you can revisit in future one-on-ones.</p><p>It could be as simple as:</p><ul><li>&#x201C;Gave feedback to teammate directly after coaching session.&#x201D;</li><li>&#x201C;Set boundaries with client on after-hours availability.&#x201D;</li><li>&#x201C;Initiated conversation to clarify team expectations.&#x201D;</li></ul><p>By linking conversations over time, patterns emerge: where someone avoids discomfort, where they grow more confident, where they still need nudges.</p><p>This doesn&#x2019;t require a complex system&#x2014;but it does require <em>consistency</em>. Whether you track in a graph-based tool, a shared doc, or a leadership journal, the key is to make development visible. Not just to you, but eventually to the team member as well.</p><p>And during your one-on-ones, revisit those threads. Ask:</p><ul><li>What happened after you took action?</li><li>How did that feel?</li><li>What would you do differently next time?</li></ul><p>That&#x2019;s how you turn moments into momentum. Side quests don&#x2019;t end when the task is done&#x2014;they end when the learning sticks.</p><h2 id="the-conclusion-leadership-is-earned-in-the-side-quests">The Conclusion: Leadership Is Earned in the Side Quests</h2><p>Technical skill may earn someone seniority. But soft skill&#x2014;the ability to handle hard conversations, set boundaries, and model emotional resilience&#x2014;is what earns leadership.</p><p>Side quests are how you build that. Not by solving every problem <em>for</em> your team, but by challenging them to solve problems <em>with</em> your guidance.</p><p>When they start coming to you less for answers and more to share solutions, you&#x2019;ll know: they leveled up.</p>]]></content:encoded></item><item><title><![CDATA[Better Design Outcomes with Figma and AI]]></title><description><![CDATA[Figma’s MCP server, paired with AI tools like Roo Code and Cursor, is transforming how design decisions reach production.]]></description><link>https://craigmdennis.com/better-design-outcomes-with-figma-and-ai/</link><guid isPermaLink="false">6844a3f22abf4600011e3cdd</guid><category><![CDATA[Design Tools]]></category><category><![CDATA[Design Insights]]></category><category><![CDATA[Collaboration]]></category><dc:creator><![CDATA[Craig Dennis]]></dc:creator><pubDate>Sat, 07 Jun 2025 21:09:44 GMT</pubDate><media:content url="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2025/06/Capture-2025-06-07-225010.png" medium="image"/><content:encoded><![CDATA[<h3 id="designers-don%E2%80%99t-need-to-code-but-they-do-need-to-understand-how-design-decisions-reach-production">Designers don&#x2019;t need to code, but they do need to understand how design decisions reach production.</h3><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2025/06/Capture-2025-06-07-225010.png" alt="Better Design Outcomes with Figma and AI"><p>AI tools like <a href="https://github.com/RooCodeInc/Roo-Code?ref=craigmdennis.com">Roo Code</a> and <a href="https://www.cursor.com/?ref=craigmdennis.com">Cursor</a>, combined with <a href="https://www.figma.com/blog/introducing-figmas-dev-mode-mcp-server/?ref=craigmdennis.com">Figma&#x2019;s new MCP server</a>, are making that journey shorter and clearer. These integrations are small but meaningful steps toward tighter collaboration and higher fidelity execution.</p><h3 id="figmas-mcp-server-a-quietly-powerful-feature">Figma&apos;s MCP Server: A Quietly Powerful Feature</h3><p>Figma&#x2019;s Model Context Protocol (MCP) server exposes structured design data&#x2014;like component trees, tokens, and properties&#x2014;through a simple endpoint. This allows external tools to read what&#x2019;s on the canvas in real time. More than that it allows&#xA0;<em>conversations</em>&#xA0;with the canvas and code generation based on its attributes.</p><h3 id="why-more-products-should-offer-an-mcp">Why More Products Should Offer an MCP</h3><p>MCP servers represent a strategic opportunity for SaaS platforms to expose their internal state and data in a structured way. Rather than requiring users to engage through rigid UIs or product-specific chatbots, open protocols like MCP enable flexible, AI-native interactions.</p><p>Imagine asking a bank: &quot;How could I have saved more money this month?&quot; Or querying a project tool: &quot;Which tasks blocked progress last quarter?&quot;. They take the common API and integration mechanic to a whole new level with the conversational and contextual abilities of LLMs. </p><p>They can also expose Tool calls so actions can be performed by the AI Agents so your AI of choice can make suggestions and implement changes as a result.</p><p>Products that offer an MCP interface make themselves not just tools, but intelligent platforms that adapt to user questions and workflows.&#xA0;</p><h3 id="enabling-figmas-mcp-server-in-coding-tools">Enabling Figma&apos;s MCP Server in Coding Tools</h3><p>To connect this to Roo Code or Cursor, add the following configuration:</p><pre><code>{
  &quot;mcpServers&quot;: {
    &quot;Figma&quot;: {
      &quot;url&quot;: &quot;http://127.0.0.1:3845/sse&quot;
    }
  }
}</code></pre><p>This snippet can be added to&#xA0;<code>~/.roo/mcp.json</code>&#xA0;or&#xA0;<code>~/.cursor/config.json</code>, depending on the tool in use. Once active, these environments can surface context-aware information pulled directly from the Figma file.</p><h3 id="why-it-matters-for-designers-and-engineers">Why It Matters for Designers and Engineers</h3><p>With conversational, agentic access to structured data from the MCP server, it becomes feasible to simply ask tools to implement components and know that they will match design specifications&#x2014;including naming conventions, layout rules, and token usage. This kind of automation reduces manual review time improving both accuracy and speed in implementation.</p><h3 id="small-steps-tangible-gains">Small Steps, Tangible Gains</h3><p>Adopting tools like MCP, Roo Code, and Cursor isn&#x2019;t about chasing trends. It&#x2019;s about making good work easier to ship. As the boundary between design and development continues to shrink, lightweight integrations like this help ensure the integrity of both craft and execution.</p><p>Better outcomes start with better connections. And now, those connections are only a config file away.</p>]]></content:encoded></item><item><title><![CDATA[How to Stand Out as a Senior Product Designer Candidate]]></title><description><![CDATA[Searching for your next senior product design role? Find practical advice for how to approach resumes, portfolios, interviews, and walkthroughs.]]></description><link>https://craigmdennis.com/how-to-stand-out-as-a-senior-product-designer-candidate/</link><guid isPermaLink="false">6841536bc49b7d000191cad9</guid><category><![CDATA[Hiring]]></category><dc:creator><![CDATA[Craig Dennis]]></dc:creator><pubDate>Thu, 05 Jun 2025 21:54:35 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1529717730488-7a2492983b2c?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDV8fGhpcmluZ3xlbnwwfHx8fDE3NDkxMTIzNjB8MA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1529717730488-7a2492983b2c?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDV8fGhpcmluZ3xlbnwwfHx8fDE3NDkxMTIzNjB8MA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" alt="How to Stand Out as a Senior Product Designer Candidate"><p>If you&#x2019;re searching for your next senior product design role, you already know the competition is steep. As someone who&#x2019;s hired designers at fast-growing B2B startups, I want to share what I look for in candidates&#x2014;not as universal truths, but as practical advice based on my experience.</p><hr><h3 id="resume-tips">Resume Tips</h3><p><strong>Be ATS-friendly, not buzzword-heavy.</strong> Use clear, scannable formatting, but skip the jargon. Focus on substance over fluff.</p><p><strong>Highlight outcomes, not just outputs.</strong> Instead of saying &#x201C;Designed a new onboarding flow,&#x201D; try: &#x201C;Redesigned onboarding to reduce drop-off, resulting in a 20% increase in conversion.&#x201D;</p><p><strong>Avoid progress bars.</strong> They don&#x2019;t help. If you&#x2019;re rating yourself 5/5 on &#x2018;Figma&#x2019;, what does that really mean?</p><p><strong>Make it look good.</strong> Your resume is a design artefact. A well-structured, readable resume shows that you understand visual hierarchy and communication.</p><hr><h3 id="portfolio-best-practices">Portfolio Best Practices</h3><p><strong>Clarity &gt; polish.</strong> I&#x2019;m not looking for motion graphics. I&#x2019;m looking for how you think and what you shipped.</p><p><strong>Frame your work with a business lens.</strong> Start with the problem, not the UI. For example: &#x201C;Users were abandoning the signup flow, costing the business potential revenue.&#x201D;</p><p><strong>Own your contribution.</strong> Specify your role. &#x201C;I led user research and prototyped solutions&#x201D; is more useful than &#x201C;We designed&#x2026;&#x201D;</p><p><strong>Context matters.</strong> What constraints were you under? What trade-offs did you make? Who did you work with?</p><p><strong>Show impact.</strong> Use metrics if you can. If not, qualitative feedback or process wins still count.</p><p><strong>Structure matters.</strong> A great format:</p><ul><li>Problem</li><li>Role</li><li>Process, constraints, and decisions</li><li>Outcome/Impact</li><li>Timeframe &amp; collaborators</li></ul><hr><h3 id="interview-advice">Interview Advice</h3><p><strong>Tie your answers to stories.</strong> Don&#x2019;t just answer &#x201C;Have you done X?&#x201D; with a yes. Share a relevant example: what you did, why, what happened, and what you learned.</p><p><strong>Tailor to their business.</strong> If you&#x2019;re interviewing at a SaaS company, mention how you improved retention, trust, or onboarding.</p><p><strong>Speak to your impact.</strong> Think of STAR format (Situation, Task, Action, Result) with a design twist.</p><hr><h3 id="design-walkthroughs">Design Walkthroughs</h3><p>It can be intimidating to present your work, especially if you&apos;re unsure whether it&apos;s visually impressive. But remember&#x2014;what matters most is relevance. Focus on showing how your design choices solved similar problems to those the company is facing.</p><p><strong>Bring real files.</strong> I&#x2019;m not judging your presentation skills&#x2014;I want to see your decision-making.</p><p><strong>Talk through constraints.</strong> What made the problem hard? What trade-offs were required?</p><p><strong>Reflect.</strong> What would you do differently now? This shows maturity and a growth mindset.</p><p><strong>A scrappy solution that drives real business results is more compelling than a pixel-perfect interface that fails to deliver value.</strong></p><p>For example, imagine showing a quick internal dashboard that reduced customer support tickets by simplifying a confusing process. It might not be visually impressive, but if you can walk through the problem, your rationale, and the result&#x2014;that&#x2019;s what stands out.</p><hr><h3 id="take-home-exercises">Take-Home Exercises</h3><p><strong>Know what they&#x2019;re really testing.</strong>&#xA0;A good take-home should reflect how the company works and avoid feeling like free work. If it doesn&#x2019;t seem fair, that&#x2019;s worth considering.</p><p><strong>Just do them&#x2014;if you want the job.</strong>&#xA0;Completing the exercise is part of showing your interest. If you&#x2019;re serious about the role, commit to it whether you agree with it or not.</p><p><strong>Record a timelapse.</strong>&#xA0;Regardless of time limits, screen record your process. A timelapse demonstrates your workflow and thought process beyond the final deliverable.</p><p><strong>Explain your thinking.</strong>&#xA0;Add a short video or written summary. Share your assumptions, highlight design decisions, and relate your work to business goals. If goals aren&#x2019;t specified, create plausible ones.</p><p><strong>Consider the broader system.</strong>&#xA0;Don&#x2019;t design in a vacuum. Ensure your solution integrates well within the larger user journey or product ecosystem.</p><p><strong>Tailor your focus.</strong>&#xA0;Align your solution with the role:</p><ul><li>UX-focused? Emphasize research, flow, and clarity.</li><li>Visual-focused? Spend time on layout, interaction, and polish.</li><li>Product-focused? Demonstrate end-to-end thinking, from problem framing to outcome.</li></ul><hr><h3 id="final-thoughts">Final Thoughts</h3><p>Hiring isn&#x2019;t just about talent; it&#x2019;s about fit. Show how you think, how you work with others, and how you solve real problems. That goes further than a flashy mockup ever could.</p><p>Have questions or want help reviewing your portfolio or resume? Reach out!</p>]]></content:encoded></item><item><title><![CDATA[Designing for the empty states (10 years later)]]></title><description><![CDATA[In 2013 I wrote an article outlining an often overlooked part of design; the empty states. A lot has changed in the 10 years since and it's time to revisit the topic.]]></description><link>https://craigmdennis.com/designing-for-the-empty-states/</link><guid isPermaLink="false">67163db3b97bd30001a5ba03</guid><category><![CDATA[Design Insights]]></category><dc:creator><![CDATA[Craig Dennis]]></dc:creator><pubDate>Mon, 21 Oct 2024 19:33:00 GMT</pubDate><media:content url="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/cleanshot-2020-09-28-at-20.34.54.webp" medium="image"/><content:encoded><![CDATA[<h3 id="in-the-absence-of-expected-information-provide-context-and-actions-so-people-understand-what-theyre-seeing-why-and-how-to-fix-it">In the absence of expected information, provide context and actions so people understand what they&apos;re seeing, why, and how to fix it.</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://tympanus.net/codrops/2013/01/09/designing-for-the-empty-states/?ref=craigmdennis.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Designing For The Empty States | Codrops</div><div class="kg-bookmark-description">Empty states are places in apps that have no content or data. They are empty. A blank page. Traditionally empty states a</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://codrops-1f606.kxcdn.com/codrops/wp-content/themes/codropstheme03/favicons/apple-touch-icon.png?x66413&amp;v=2" alt="Designing for the empty states (10 years later)"><span class="kg-bookmark-author">Codrops</span><span class="kg-bookmark-publisher">Craig Dennis</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://codrops-1f606.kxcdn.com/codrops/wp-content/uploads/2013/01/Designingforrmptystates.jpg?x66413" alt="Designing for the empty states (10 years later)" onerror="this.style.display = &apos;none&apos;"></div></a></figure><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/cleanshot-2020-09-28-at-20.34.54.webp" alt="Designing for the empty states (10 years later)"><p>Traditionally empty states were overlooked as most designers focus on how best to display lots of content or data and not the lack of it.</p><p>It&#x2019;s common for empty states to be dealt with by developers because the causes are often exceptions (such as no internet connection, no permissions for location, a failure to connect with a database). Developers often write the copy or it is provided by a backend service to help debug a problem. As a result it can be a little stiff and literal. While this is better than nothing (and functional), empty states should&#xA0;be deliberately considered.</p><p>There are three main empty state types:</p><p><strong>First use </strong>(e.g. creating new data)<br><strong>User cleared </strong>(e.g. deleted data)<br><strong>Errors</strong>&#xA0;(e.g. unable to load data)</p><h2 id="first-use">First use</h2><p>From meeting new people, visiting a new place, or learning a new app, first impressions help us predict what will happen by comparing what we see now to something we have seen previously; an&#xA0;existing&#xA0;<a href="http://www.createadvantage.com/glossary/mental-model?ref=craigmdennis.com">mental model</a>.</p><p>Sometimes there is no basis for comparison (users are presented with a blank canvas). This can often lead to people believing the app is broken because nothing of meaning is loading. A bad first impression is very difficult to overcome.</p><p>When someone signs up for an app, the chances are high that they know what it does. It may not be clear to them <em>how</em>. When you sign up or log in for the first time, there is no data. It is the perfect opportunity to provide some careful&#xA0;hand holding&#xA0;to help users get the best possible experience. If the lack of data is out of their control then tell them; put them at ease and show that your app has some personality. Have a look at the way&#xA0;<a href="https://bufferapp.com/?ref=craigmdennis.com">Buffer</a>, &#xA0;<a href="http://timehop.com/?ref=craigmdennis.com">Timehop</a>&#xA0;and&#xA0;<a href="http://db.tt/h10S47C?ref=craigmdennis.com">Dropbox</a>&#xA0;do this. Buffer uses the same technique on their desktop site showing that it doesn&#x2019;t matter what platform or screen size you&#x2019;re on.</p><figure class="kg-card kg-gallery-card kg-width-wide"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-32.png" width="1680" height="1027" loading="lazy" alt="Designing for the empty states (10 years later)" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2024/10/image-32.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2024/10/image-32.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1600/2024/10/image-32.png 1600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-32.png 1680w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-30.png" width="1680" height="1027" loading="lazy" alt="Designing for the empty states (10 years later)" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2024/10/image-30.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2024/10/image-30.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1600/2024/10/image-30.png 1600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-30.png 1680w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-31.png" width="1280" height="722" loading="lazy" alt="Designing for the empty states (10 years later)" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2024/10/image-31.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2024/10/image-31.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-31.png 1280w" sizes="(min-width: 720px) 720px"></div></div></div></figure><h2 id="user-cleared">User cleared</h2><p>Consider the inbox. Love it or hate it, most of the time it&#x2019;s full. Some people have hundreds of unread emails. Some people have only a handful. Either way everyone is on the quest for &#x2018;Inbox Zero&#x2019; whether they know it or not. This can be a monumental task and as such should be rewarded with more than just relief.</p><figure class="kg-card kg-gallery-card kg-width-wide"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-27.png" width="1080" height="2160" loading="lazy" alt="Designing for the empty states (10 years later)" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2024/10/image-27.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2024/10/image-27.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-27.png 1080w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/11/Spark-Mail-2024-11-03-at-21.05.25@2x-1.png" width="2000" height="1249" loading="lazy" alt="Designing for the empty states (10 years later)" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2024/11/Spark-Mail-2024-11-03-at-21.05.25@2x-1.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2024/11/Spark-Mail-2024-11-03-at-21.05.25@2x-1.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1600/2024/11/Spark-Mail-2024-11-03-at-21.05.25@2x-1.png 1600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w2400/2024/11/Spark-Mail-2024-11-03-at-21.05.25@2x-1.png 2400w" sizes="(min-width: 720px) 720px"></div></div></div></figure><h2 id="errors">Errors</h2><p>Sometimes the people will experience an empty state as part of an error. Most commonly due to lack of an internet connection or declining permissions to location.</p><p>This is another opportunity to make people aware that you&#xA0;<em>know</em>&#xA0;this can happen by having something more than ugly error text. It puts people at ease knowing that it&#x2019;s probably not something they&#x2019;ve done because there is something designed something for that specific case.</p><figure class="kg-card kg-gallery-card kg-width-wide"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/11/IMG_3922.PNG" width="1179" height="2556" loading="lazy" alt="Designing for the empty states (10 years later)" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2024/11/IMG_3922.PNG 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2024/11/IMG_3922.PNG 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/11/IMG_3922.PNG 1179w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/11/IMG_3923.PNG" width="1179" height="2556" loading="lazy" alt="Designing for the empty states (10 years later)" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2024/11/IMG_3923.PNG 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2024/11/IMG_3923.PNG 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/11/IMG_3923.PNG 1179w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-29.png" width="1080" height="1920" loading="lazy" alt="Designing for the empty states (10 years later)" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2024/10/image-29.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2024/10/image-29.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-29.png 1080w" sizes="(min-width: 720px) 720px"></div></div></div></figure><h2 id="democratising-design">Democratising Design</h2><p>One way to ensure that empty states are always covered is by creating a <a href="https://carbondesignsystem.com/patterns/empty-states-pattern/?ref=craigmdennis.com">design system</a> with guidance, examples, and all states of a particular component.</p><p>A design system allows designers to create a set of templates and instructions for when, where, and how empty states should be included. This aids developers who then have a clearer idea of the purpose of an empty state and can use existing designs to implement a better experience.</p><figure class="kg-card kg-gallery-card kg-width-wide"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/Arc-2024-10-21-at-21.31.55@2x.png" width="2000" height="1249" loading="lazy" alt="Designing for the empty states (10 years later)" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2024/10/Arc-2024-10-21-at-21.31.55@2x.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2024/10/Arc-2024-10-21-at-21.31.55@2x.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1600/2024/10/Arc-2024-10-21-at-21.31.55@2x.png 1600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w2400/2024/10/Arc-2024-10-21-at-21.31.55@2x.png 2400w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-34.png" width="2000" height="1007" loading="lazy" alt="Designing for the empty states (10 years later)" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2024/10/image-34.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2024/10/image-34.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1600/2024/10/image-34.png 1600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w2400/2024/10/image-34.png 2400w" sizes="(min-width: 720px) 720px"></div></div></div></figure><p>Just knowing empty state guidance exists ensures that when something <em>doesn&apos;t</em> quite fit the use-case, it&apos;s called out and gets addressed.</p><h2 id="what-next">What next?</h2><p>Pay attention to when users will see nothing, and give them something. An explanation, context, and an action to perform. Create, retry, or wait.</p><p>The important thing to remember is to make sure you add a layer of delight to your apps. Even the boring ones.</p><ol><li><strong>Guide people on how to add data when there is none.</strong>&#xA0;A good idea is to break out of the conventional layout.</li><li><strong>Think about the goals people have when using your app.</strong>&#xA0;Will they clear data a lot or will it be a rarity? Design a nice surprise accordingly. If the state will appear frequently, consider having a few designs and rotate through them randomly for an extra level of delight.</li><li><strong>Provide context and actions along with errors.</strong>&#xA0;Do they make sense to someone who doesn&#x2019;t know what they&#x2019;re doing? Make them plain language with a clear action. Even if the action is to wait.</li></ol><p>The details are what makes any app great. Delight your users and they will be much more forgiving if you make a mistake later on.</p><h3 id="contribute">Contribute</h3><p>If you have examples of well designed empty states, please <a href="mailto://submission@emptystat.es" rel="noreferrer">submit them </a>to&#xA0;<a href="http://emptystat.es/?ref=craigmdennis.com" rel="noreferrer">http://emptystat.es</a>&#xA0;including the app name and URL.</p>]]></content:encoded></item><item><title><![CDATA[Designing and building the official Pexels Figma plugin]]></title><description><![CDATA[While I'm a product designer, I'm also an amateur photographer (and Pexels contributor), and I like to tinker with code on the side. All these worlds collided when I wanted to find some photos to use in a design and discovered that there wasn't a Pexels plugin for the design tool I use; Figma.]]></description><link>https://craigmdennis.com/official-pexels-figma-plugin/</link><guid isPermaLink="false">6716b6f8c32c0a000171cb9a</guid><category><![CDATA[Plugins]]></category><dc:creator><![CDATA[Craig Dennis]]></dc:creator><pubDate>Thu, 09 Apr 2020 22:00:00 GMT</pubDate><media:content url="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/Untitled.webp" medium="image"/><content:encoded><![CDATA[<img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/Untitled.webp" alt="Designing and building the official Pexels Figma plugin"><p>After previously writing a couple of <a href="https://craigmdennis.com/designer-learned-to-make-figma-plugins-in-a-week/" rel="noreferrer">basic Figma plugins</a>, I wondered how much of a stretch it would be to build a Pexels one myself. Notice that I even added an <a href="https://craigmdennis.com/designing-for-the-empty-states/" rel="noreferrer">empty state</a> and skeleton states?</p><figure class="kg-card kg-video-card kg-width-regular" data-kg-thumbnail="https://craigmdennis.com/content/media/2024/10/pexels-figma-plugin-demo_-_01_thumb.jpg" data-kg-custom-thumbnail>
            <div class="kg-video-container">
                <video src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/media/2024/10/pexels-figma-plugin-demo_-_01.mp4" poster="https://img.spacergif.org/v1/1024x640/0a/spacer.png" width="1024" height="640" playsinline preload="metadata" style="background: transparent url(&apos;https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/media/2024/10/pexels-figma-plugin-demo_-_01_thumb.jpg&apos;) 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"/>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"/>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:18</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1&#xD7;</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"/>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"/>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            
        </figure><figure class="kg-card kg-gallery-card kg-width-wide"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-37.png" width="1195" height="881" loading="lazy" alt="Designing and building the official Pexels Figma plugin" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2024/10/image-37.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2024/10/image-37.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-37.png 1195w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-38.png" width="1608" height="586" loading="lazy" alt="Designing and building the official Pexels Figma plugin" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2024/10/image-38.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2024/10/image-38.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1600/2024/10/image-38.png 1600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-38.png 1608w" sizes="(min-width: 720px) 720px"></div></div></div></figure><p> <a href="https://x.com/craigmdennis/status/1248384014395691009?ref=craigmdennis.com">I chronicled my journey in a series of Tweets</a> that, maybe unsurprisingly since I @ mentioned them, Pexels saw and subsequently reached out about.</p><figure class="kg-card kg-image-card"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-36.png" class="kg-image" alt="Designing and building the official Pexels Figma plugin" loading="lazy" width="346" height="220"></figure><p>Curious about my creative journey, <a href="https://www.pexels.com/blog/news/figma-plugin-craig-dennis/?ref=craigmdennis.com">Pexels interviewed me</a> and published the story on their blog and Instagram. It is now recognised as an official Pexels branded plugin.</p><p>I also <a href="https://www.producthunt.com/posts/pexels-for-figma?ref=craigmdennis.com">launched it on Product Hunt</a> to try and gain some additional traction.</p>]]></content:encoded></item><item><title><![CDATA[I learned to make Figma plugins in a week]]></title><description><![CDATA[I wrote two Figma plugins in a week having never created any before.]]></description><link>https://craigmdennis.com/designer-learned-to-make-figma-plugins-in-a-week/</link><guid isPermaLink="false">6715e6ebf717e000087cd856</guid><category><![CDATA[Plugins]]></category><category><![CDATA[Design Tools]]></category><category><![CDATA[Code]]></category><dc:creator><![CDATA[Craig Dennis]]></dc:creator><pubDate>Tue, 31 Mar 2020 05:30:00 GMT</pubDate><media:content url="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-13-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-13-1.png" alt="I learned to make Figma plugins in a week"><p>Recently I had a need to use random colors for a project in Figma. Yes, I could do it manually but instead I turned my hand to plugin development.</p><p>I found a plugin that appeared to do what I wanted and added random colours but it seemed to fail on Frames. It must have been written before Frames could have backgrounds.</p><p>At first I thought I could find its GitHub repo and clone it, poke around in the code, and hopefully understand enough of it to make it do what I wanted.</p><p>There was no repo.</p><h2 id="i-decided-to-make-my-own">I decided to make my own</h2><p>I downloaded Figma&#x2019;s plugin starter then search for and found&#xA0;<a href="https://gka.github.io/chroma.js/?ref=craigmdennis.com">a library that would create a random color</a>.</p><p>There were a few concepts that were foreign to me (from my jQuery days). Certain properties on&#xA0;<code>Node</code>s in Figma are read only. This means you need to clone them, modify the details, and apply them back.</p><p>After initially struggling with Webpack (and Typescript) for a while, I finally created what I needed. A plugin that changed the fill of all selected elements to a random color.&#xA0;<strong>No UI needed. It does one thing and it does it well.</strong></p><figure class="kg-card kg-image-card"><img src="https://craigmdennis.com/0c81994eaa3b352218a9ec4dec9bf666/figma-plugin-random-color-stay-indoors.gif" class="kg-image" alt="I learned to make Figma plugins in a week" loading="lazy" width="1378" height="1054"></figure><p>After creating the collateral to use for publishing the plugin to Figma, I hit &#x2018;publish&#x2019; and sat back; happy with what I had created.</p><figure class="kg-card kg-image-card"><a href="https://www.figma.com/community/plugin/821872387409410776/Random-Color-Generator?ref=craigmdennis.com"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-12.png" class="kg-image" alt="I learned to make Figma plugins in a week" loading="lazy" width="1470" height="735" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2024/10/image-12.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2024/10/image-12.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-12.png 1470w" sizes="(min-width: 720px) 720px"></a></figure><p>It was published a few days later with only minor changes: I needed to notify users when nothing was selected.</p><p>And so, my first Figma plugin was published. I had made a thing. It&#x2019;s during the 2020 Coronavirus pandemic quarantine in the UK so I had some fun with my demo.</p><hr><h1 id="a-plugin-for-one-person">A plugin for one person</h1><p>Soon after the plugin went live I received a notification from GitHub when someone&#xA0;<a href="https://github.com/craigmdennis/figma-random-color-generator/issues/3?ref=craigmdennis.com">submitted a feature request</a>.</p><figure class="kg-card kg-image-card"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/Arc-2024-10-21-at-13.25.54@2x.png" class="kg-image" alt="I learned to make Figma plugins in a week" loading="lazy" width="1864" height="636" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2024/10/Arc-2024-10-21-at-13.25.54@2x.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2024/10/Arc-2024-10-21-at-13.25.54@2x.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1600/2024/10/Arc-2024-10-21-at-13.25.54@2x.png 1600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/Arc-2024-10-21-at-13.25.54@2x.png 1864w" sizes="(min-width: 720px) 720px"></figure><p>Already!? Great! I consider &#x2018;yeah but it would be great if it also did this&#x2026;&#x2019; as one metric for success. It means that what you delivered was needed, obvious, and useful to the point that they want something more on top.</p><p>After some clarification of this issue I resigned myself to not delivering on the idea becuase it was out of scope for that plugin and would result in a breaking change (from a single step to one with a UI and options).</p><h2 id="my-mind-was-already-thinking-how-to-create-the-feature">My mind was already thinking how to create the feature</h2><p>The idea was to take a pre-existing set of colors and randomly fill a selection with only those colors.</p><p>I decided to&#xA0;<a href="https://github.com/craigmdennis/figma-apply-colors-to-selection?ref=craigmdennis.com">start a<u>&#xA0;</u><em>new</em><u>&#xA0;</u>plugin</a>&#xA0;to try a proof-of-concept and quickly had something running using a chunk of the work from the previous plugin.</p><figure class="kg-card kg-image-card"><img src="https://craigmdennis.com/dd878d5b9f4b8fe3a51e2b5348deebfe/figma-apply-colors-to-selection.gif" class="kg-image" alt="I learned to make Figma plugins in a week" loading="lazy" width="856" height="600"></figure><p>This, it turns out, was actually the easiest/quickest part.</p><h2 id="swatches-on-swatches-on-swatches">Swatches on swatches on swatches</h2><p>It&#x2019;s no good having a fixed number of swatches. Everyone has different use cases and being able to add an arbitrary amount seems like a good idea. But it was hard to execute for someone who has only been writing Typescript for ~6 hours total at this point.</p><p>I opted to use Figma&#x2019;s default&#xA0;<code>#C4C4C4</code>&#xA0;for the swatches and it worked well but it didn&#x2019;t really feel that good to use (or look that good) and relied solely on the OS-based color picker. It turns out Figma doesn&#x2019;t give you access to&#xA0;<em>their</em>&#xA0;color picker.</p><figure class="kg-card kg-image-card"><img src="https://craigmdennis.com/4f3e52f2d198ba3acade34f7f571c8a0/figma-add-more-swatches.gif" class="kg-image" alt="I learned to make Figma plugins in a week" loading="lazy" width="614" height="600"></figure><p>It did fulfil the brief though; to use an existing selection to create the swatches.</p><p>There is a lot of complexity in this:</p><ul><li>it reads the fills from the current selection if there is one</li><li>if there isn&#x2019;t it generates two swatches</li><li>it allows people to add an arbitrary number of swatches</li><li>people can change the</li></ul><h2 id="using-random-colors-when-adding-manually">Using random colors when adding manually</h2><p>I decided that, actually, when adding a new swatch it makes sense for it to be a random color rather than always the same. A nice touch that actually brings us full circle.</p><p>In the end, I demoed the plugin to the requester (who seemed happy enough), created some more collateral&#x2014;following the previous style&#x2014;and submitted it to Figma.</p><figure class="kg-card kg-image-card"><a href="https://www.figma.com/community/plugin/825301478840922344?ref=craigmdennis.com"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-13.png" class="kg-image" alt="I learned to make Figma plugins in a week" loading="lazy" width="1470" height="735" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2024/10/image-13.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2024/10/image-13.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-13.png 1470w" sizes="(min-width: 720px) 720px"></a></figure><p>At the time of writing it is still in review but you can&#xA0;<a href="https://www.figma.com/community/plugin/825301478840922344?ref=craigmdennis.com">view it if it&#x2019;s been published</a>.</p><p>And I found a piece of UI that perfectly encapsulates the use case for the plugin. The GitHub contribution heatmap.</p><figure class="kg-card kg-image-card"><img src="https://craigmdennis.com/9d81f5c6384c8c21516b425cc09f2ef8/figma-plugin-github-heatmap-demo.gif" class="kg-image" alt="I learned to make Figma plugins in a week" loading="lazy" width="960" height="680"></figure><h1 id="now-what">Now what?</h1><p>This plugin was made for one person, and I hope it helps them. I hope other people find use in it. I&#x2019;ve learned a lot and now I know (roughly) how to put together a plugin.</p><p>So the next time I need to automate a repetative task, I might end up making another plugin.</p><p>References:</p><ul><li><a href="https://gka.github.io/chroma.js/?ref=craigmdennis.com">Chroma JS</a></li><li><a href="https://www.figma.com/plugin-docs/intro/?ref=craigmdennis.com">Figma Plugin Docs</a></li><li><a href="https://github.com/craigmdennis/figma-random-color-generator?ref=craigmdennis.com">Random Color Generator (Github)</a></li><li><a href="https://github.com/craigmdennis/figma-apply-colors-to-selection?ref=craigmdennis.com">Apply Colors to Selection (Github)</a></li></ul><p></p>]]></content:encoded></item><item><title><![CDATA[Sketch Symbol Override Concept]]></title><description><![CDATA[A design exploration of symbol overrides in Sketch and how they could be improved, with a focus on usability and visual consistency.]]></description><link>https://craigmdennis.com/sketch-symbol-overrides-concept/</link><guid isPermaLink="false">67162df1983fdf00015b25a1</guid><category><![CDATA[Concept]]></category><category><![CDATA[Interfaces]]></category><dc:creator><![CDATA[Craig Dennis]]></dc:creator><pubDate>Sat, 22 Jul 2017 10:00:00 GMT</pubDate><media:content url="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/composite@2x.png" medium="image"/><content:encoded><![CDATA[<h3 id="a-design-exploration-of-symbol-overrides-in-sketch-and-how-they-could-be-improved-with-a-focus-on-usability-and-visual-consistency">A design exploration of symbol overrides in Sketch and how they could be improved, with a focus on usability and visual consistency.</h3><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/composite@2x.png" alt="Sketch Symbol Override Concept"><p>Sketch 45&#xA0;<a href="https://www.sketchapp.com/updates/?ref=craigmdennis.com#version-45">has just launched</a>&#xA0;and some great new features for plugins as well as fixed a bunch of frustrating vector editing bugs. One thing that didn&#x2019;t get any improvements were symbol overrides.</p><p>It was important to identify what was causing friction, and explore how it might be improved. There were a few things that this concept set out to achieve:</p><ol><li>Better visual identification of overrides and their relationship</li><li>The ability to override the border-radius and colour of shapes</li><li>The ability to override the alignment, colour, and underlines of text</li></ol><h2 id="before">Before</h2><p>The current symbol override panel flattens the hierarchy so that all symbols exist on the same level and look identical.</p><figure class="kg-card kg-image-card"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image.png" class="kg-image" alt="Sketch Symbol Override Concept" loading="lazy" width="1470" height="832" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2024/10/image.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2024/10/image.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image.png 1470w" sizes="(min-width: 720px) 720px"></figure><p>This leads to confusion and a non-intuitive search through the labels (which can be truncated) to find the correct &#x2018;top level&#x2019; symbol. And&#xA0;<em>then</em>&#xA0;search the symbols that follow those, to identify which nested symbol is needed, and override it.</p><h2 id="after">After</h2><p>Comparing the concept, in its collapsed state, with the existing symbol overrides panel shows that it still uses a similar amount of space.</p><figure class="kg-card kg-image-card"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-1.png" class="kg-image" alt="Sketch Symbol Override Concept" loading="lazy" width="1470" height="832" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2024/10/image-1.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2024/10/image-1.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-1.png 1470w" sizes="(min-width: 720px) 720px"></figure><p>Using a button with nested symbols as an example, the proposed solution uses an accordion mechanism to re-introduce levels of hierarchy back to the symbols.</p><figure class="kg-card kg-image-card"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-2.png" class="kg-image" alt="Sketch Symbol Override Concept" loading="lazy" width="1470" height="1158" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2024/10/image-2.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2024/10/image-2.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-2.png 1470w" sizes="(min-width: 720px) 720px"></figure><ul><li>Easier to see the&#xA0;<em>type</em>&#xA0;of override, by using icons to represent them.</li><li>Text is kept editable instead of using a placeholder (easier to identify).</li><li>Direct access to colour overrides without having to create more symbols.</li><li>Clear separation of top-level symbols.</li></ul><h2 id="alignment">Alignment</h2><p>The whole design conforms to an 8px grid.</p><figure class="kg-card kg-image-card"><img src="https://craigmdennis.com/7777161dd1decca20b78647bf051e9c5/grid@2x.gif" class="kg-image" alt="Sketch Symbol Override Concept" loading="lazy" width="1470" height="624"></figure><p>The grid makes alignment easy and the overall look more consistent than the current override panel.</p><h2 id="caveats">Caveats</h2><p>This design does not account for deeply nested symbols. The pattern&#xA0;<em>could</em>&#xA0;work with a little modification, so that would be an interesting avenue to explore further.</p><p>It could be problematic to show every shape or text layer within a symbol. One idea is to have a checkbox that designates whether a layer&#xA0;<em>can</em>&#xA0;be overridden; potentially extending to allow only specific properties. It&#x2019;s likely the override will need to be checked by default, so as not to break existing files.</p><p>The proposed design is slightly wider than the current sidebar. It can be made narrower to fit but the sub-controls (text alignment for example) would need to be adjusted to survive in the smaller space.</p><h2 id="next-steps">Next Steps</h2><p>The next thing to try and improve would be the way in which overrides are selected. They&#x2019;re currently in a simple dropdown, with poor visibility of the content; relying mostly on the name of the layer.</p><h2 id="aside">Aside</h2><p>The project was designed using the&#xA0;<a href="https://abstractapp.com/?ref=craigmdennis.com">Abstract</a>&#xA0;alpha which offers a way to track file changes in a similar way to GIT. The ability to visualise the history of an artboard or symbol is incredibly useful and allows an easy timeline of progress.</p><figure class="kg-card kg-image-card"><img src="https://craigmdennis.com/d42af2f3cd1c29a8455fe34e4f9ee436/abstract-visual-history@2x.gif" class="kg-image" alt="Sketch Symbol Override Concept" loading="lazy" width="1484" height="898"></figure><p>You can download the Sketch file and play around yourself. It&#x2019;s an export from Abstract so should contain all commits if you use the app.</p><div class="kg-card kg-file-card"><a class="kg-file-card-container" href="https://craigmdennis.com/content/files/2024/10/sketch-symbol-overrides.sketch" title="Download" download><div class="kg-file-card-contents"><div class="kg-file-card-title">Sketch Symbol Overrides</div><div class="kg-file-card-caption">Download the sketch file used in this post.</div><div class="kg-file-card-metadata"><div class="kg-file-card-filename">sketch-symbol-overrides.sketch</div><div class="kg-file-card-filesize">256 KB</div></div></div><div class="kg-file-card-icon"><svg viewbox="0 0 24 24"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>download-circle</title><polyline class="a" points="8.25 14.25 12 18 15.75 14.25"/><line class="a" x1="12" y1="6.75" x2="12" y2="18"/><circle class="a" cx="12" cy="12" r="11.25"/></svg></div></a></div>]]></content:encoded></item><item><title><![CDATA[The best UI is no UI]]></title><description><![CDATA[<p>Great interface design is making sure your users complete tasks easily and efficiently. &#x2018;Distraction free&#x2019; modes remove the UI but what if that&#x2019;s the default?</p><p>Users should never be thinking about an interface while they&#x2019;re using it; instead the interface should be unobtrusive and</p>]]></description><link>https://craigmdennis.com/the-best-ui-is-no-ui/</link><guid isPermaLink="false">6716302d983fdf00015b25c3</guid><category><![CDATA[Interfaces]]></category><dc:creator><![CDATA[Craig Dennis]]></dc:creator><pubDate>Mon, 19 Jan 2015 23:00:00 GMT</pubDate><media:content url="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-8-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-8-1.png" alt="The best UI is no UI"><p>Great interface design is making sure your users complete tasks easily and efficiently. &#x2018;Distraction free&#x2019; modes remove the UI but what if that&#x2019;s the default?</p><p>Users should never be thinking about an interface while they&#x2019;re using it; instead the interface should be unobtrusive and functional. There shouldn&#x2019;t be any decoration when efficiency is the focus.</p><blockquote>&#x201C;Good design is invisible. Minimum input, maximum output, with minimal conscious thought.&#x201D; &#x2014;&#xA0;<a href="https://www.theverge.com/2012/7/24/3177332/ia-oliver-reichenstein-writer-interview-good-design-is-invisible?ref=craigmdennis.com">Oliver Reichenstein</a></blockquote><h3 id="forms">Forms</h3><p>Everyone is familiar with a web form. Login, register, update status, comment &#x2014; all of them follow a similar pattern which is usually a label, an input, a placeholder and a button.</p><p>There has been a shift away from labels in favour of using placeholders for the same purpose, but this&#xA0;<em>can</em>&#xA0;lead to some usability issues because the placeholder disappears when you start typing. It may also affect accessibility if the label isn&#x2019;t even in the markup.</p><p>There are some&#xA0;<a href="https://tympanus.net/Development/TextInputEffects/?ref=craigmdennis.com">clever ideas</a>&#xA0;to get around the issue.</p><h3 id="in-the-wild">In The Wild</h3><p>The &#x2018;new email&#x2019; form for Inbox by Google shows how typography, visual hierarchy and colour can combine to create a fantastic interface design pattern without an explicit UI for content. It plays on our innate sense of writing; start with a title and then add some copy.</p><figure class="kg-card kg-image-card"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-3.png" class="kg-image" alt="The best UI is no UI" loading="lazy" width="1012" height="1020" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2024/10/image-3.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2024/10/image-3.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-3.png 1012w" sizes="(min-width: 720px) 720px"></figure><p>It is clear from the size, weight and position of the text at the top that it is the title (Subject in the case of email). It&#x2019;s also clear that the subsequent text is secondary and relates directly to the title;&#xA0;<strong>even when the placeholders are removed when typing</strong>. The placeholders serve to reinforce what content is expected.</p><figure class="kg-card kg-image-card"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-4.png" class="kg-image" alt="The best UI is no UI" loading="lazy" width="1984" height="1270" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2024/10/image-4.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2024/10/image-4.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1600/2024/10/image-4.png 1600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-4.png 1984w" sizes="(min-width: 720px) 720px"></figure><p>The main difference is that there are no separate fields for title and content. It doesn&#x2019;t care as notes are &#x2014; by their very nature &#x2014; freeform.</p><p>There is an easy way to tell if you&#x2019;ve been successful in removing a form field interface:&#xA0;<strong>Can you still understand the field&#x2019;s purpose when it&#x2019;s populated by user content</strong>. Without a persistent label, content is all anyone has to go on.</p><p>It&#x2019;s a little like skeuomorphism in that design elements are used to&#xA0;<strong>reinforce the real-world instances of their digital counterparts</strong>, allowing them to be easily understood.</p><p>Visual grouping plays a very important part in forming relationships between content, thereby giving it added context.</p><h4 id="more-examples">More examples</h4><figure class="kg-card kg-image-card"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-5.png" class="kg-image" alt="The best UI is no UI" loading="lazy" width="1262" height="824" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2024/10/image-5.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2024/10/image-5.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-5.png 1262w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-6.png" class="kg-image" alt="The best UI is no UI" loading="lazy" width="1924" height="1446" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2024/10/image-6.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2024/10/image-6.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1600/2024/10/image-6.png 1600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-6.png 1924w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Medium&apos;s new post page</span></figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-10.png" class="kg-image" alt="The best UI is no UI" loading="lazy" width="1694" height="1454" srcset="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w600/2024/10/image-10.png 600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1000/2024/10/image-10.png 1000w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/size/w1600/2024/10/image-10.png 1600w, https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-10.png 1694w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">A terminal window with only a blinking cursor</span></figcaption></figure><h3 id="in-practice">In Practice</h3><p>I&#x2019;ve applied these design principles to a &#x2018;new event&#x2019; in a fake calendar app.</p><figure class="kg-card kg-image-card kg-card-hascaption"><a href="https://dribbble.com/shots/1890001-New-Event-Empty?ref=craigmdennis.com"><img src="https://storage.ghost.io/c/49/2f/492fbf44-885c-4ec9-901a-4d4c88d93787/content/images/2024/10/image-8.png" class="kg-image" alt="The best UI is no UI" loading="lazy" width="480" height="599"></a><figcaption><span style="white-space: pre-wrap;">A blank calendar event form</span></figcaption></figure><p>The placeholders serve to&#xA0;<em>initially</em>&#xA0;explain what content is required in each field. The visual hierarchy helps explain the context of each item when the fields have been filled.</p><ul><li><strong>Untitled Event</strong>&#xA0;shows that the event needs a name. It&#x2019;s at the very top and is the largest element indicating that it&#x2019;s the most important.</li><li><strong>Location</strong>&#xA0;auto expands to take a full / partial address or just a meeting room. Easily recognisable content once filled.</li><li><strong>Date and time</strong>&#xA0;would prompt a picker of some description or take any form of date / time combo written</li><li><strong>Description</strong>&#xA0;is bold to indicate it too is a title of sorts. This could be used for an agenda or general overview of the event. More detail would go in the &#x2018;notes&#x2019; section.</li><li><strong>Guest</strong>&#xA0;would trigger an autocomplete dropdown to select contacts (with avatars if present) but will also just accept a comma separated list of email addresses.</li><li><strong>Attachments</strong>&#xA0;would show a list of files once attached but having a drop-zone and a browse link easily indicate the purpose.</li><li><strong>Notifications</strong>&#xA0;might be better called &#x2018;reminders&#x2019; as date and time by itself has no discernible meaning in this context. &#x2019;Remind me X hours/days/weeks before&#x2019; would be a good option.</li><li><strong>Notes</strong>&#xA0;is a dumping ground for any freeform content. It could be the entire agenda, cliff notes or anything not included in an attached document.</li></ul><p>The important thing to note is that most of the inputs can be&#xA0;<strong>easily understood</strong>&#xA0;once they are filled because their&#xA0;<strong>content types</strong>&#xA0;are different.</p><p>Where the content types are&#xA0;<strong>the same</strong>&#xA0;(as with the title, description and notes) visual hierarchy, layout, typography, and user content, all go towards showing the context.</p><h2 id="how-far-can-this-go">How far can this go?</h2><p>This&#xA0;<em>isn&#x2019;t</em>&#xA0;something that should be applied in a blanket fashion to all forms. For example: a long, detailed car insurance quote form wouldn&#x2019;t work because&#xA0;<strong>the content can&#x2019;t be understood without a label</strong>; it&#x2019;s too detailed.</p><p>However the registration plate, make, model, and colour&#xA0;<em>could</em>&#xA0;be addressed with invisible UI if designed correctly.</p><p>Another approach is&#xA0;<a href="https://layervault.tumblr.com/post/42361566927/progressive-reduction?ref=craigmdennis.com">Progressive Reduction</a>&#xA0;which starts with a full interface (including more verbose wording and help) but&#xA0;<strong>gradually reduces the amount of interface</strong>&#xA0;the more you complete specific tasks.</p><h2 id="tldr">TL;DR</h2><p>An interface typically includes icons, buttons, toolbars etc. but not all of those elements may be needed.</p><p>We&#x2019;re good at reducing unnecessary tasks by asking:</p><blockquote>&#x201C;What is the minimum information we need from a user?&#x201D;</blockquote><p>Now we should be asking:</p><blockquote>&#x201C;What is the minimum interface the user needs?&#x201D;</blockquote>]]></content:encoded></item><item><title><![CDATA[:hover is Dead]]></title><description><![CDATA[<p>How many times have you tried to access a menu or some form of navigation on a touch enabled device, only to find that the it&apos;s based on :hover events and doesn&apos;t behave quite as you&apos;d expect.</p><p>When designing interactions for menus and other</p>]]></description><link>https://craigmdennis.com/hover-is-dead/</link><guid isPermaLink="false">67163176983fdf00015b25e2</guid><dc:creator><![CDATA[Craig Dennis]]></dc:creator><pubDate>Sun, 24 Jun 2012 22:00:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1501757275-33022c3e8a72?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDQ1fHxpcGFkfGVufDB8fHx8MTcyOTUxNTk4NXww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1501757275-33022c3e8a72?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDQ1fHxpcGFkfGVufDB8fHx8MTcyOTUxNTk4NXww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt=":hover is Dead"><p>How many times have you tried to access a menu or some form of navigation on a touch enabled device, only to find that the it&apos;s based on :hover events and doesn&apos;t behave quite as you&apos;d expect.</p><p>When designing interactions for menus and other complex flyouts such as help tips, how they will respond on touch devices needs to be considered. The simplest option is to convert hover to click (or tap in the case of touch devices) and be done with it. For the most part this is an acceptable solution which covers the aforementioned most scenarios.&#xA0;<strong>This will also benefit non-touch enabled users at the same time</strong>&#xA0;by preventing accidentally triggering the menus.</p><p>This presents new challenges though; how do you close the flyout? It depends on the context in question and what feels right. For example with a main navigation you could close the menu when the mouse leaves it or (the preferred method) when the mouse clicks somewhere else in the document. Sometimes a close button may be appropriate for help text.</p><h3 id="if-hover-is-a-key-interaction-another-approach-is-to-degrade-to-a-more-basic-interaction">If hover is a key interaction, another approach is to degrade to a more basic interaction.</h3><p>This is where questions need to be asked of the user; &#x2018;what are the most important tasks?&#x2019;. If a key task can&#x2019;t be completed on a touch device because it user a hover event and the predicted traffic from touch devices is high enough, then either change the interaction globally or target touch devices specifically.</p><p>Modernizr provides feature detection for many things including the presence of touch events. Use this to target touch enabled devices and tailor an experience for them. Swipe gestures could be a suitable replacement.</p><h2 id="more-complex-apps-are-more-complex">More complex apps are more complex</h2><p>Think of Google Docs using right click events, something traditionally only seen on desktop applications. This adds another layer of complexity to the design process when thinking about how people will interact with those features on touch devices. The interactions for a document are ok but&#xA0;<strong>trying to edit a spreadsheet on a touch device is just about impossible</strong>.</p><h4 id="enhance-progressively-don%E2%80%99t-degrade-gracefully">Enhance progressively, don&#x2019;t degrade gracefully</h4><p>The best advice is to make sure that hover and right click events are enhancements. Ensure that the tasks that enabled by those interactions can still be completed through other (probably longer) means. While not ideal, nothing breaks. This allows you to only enable those events when the device detects no touch events.</p><p>With so many touch enabled devices connected to the web these days, you just can&#x2019;t ignore them when considering interactions for your design.</p>]]></content:encoded></item></channel></rss>