<?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:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Ali Gök on Medium]]></title>
        <description><![CDATA[Stories by Ali Gök on Medium]]></description>
        <link>https://medium.com/@aligok.nl?source=rss-4e468372f61------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*W6e-HkgazDaJJ2Cv5ezmtw.jpeg</url>
            <title>Stories by Ali Gök on Medium</title>
            <link>https://medium.com/@aligok.nl?source=rss-4e468372f61------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 24 May 2026 02:24:52 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@aligok.nl/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Pressed, Focused, Active: Why Naming UI States Correctly Matters]]></title>
            <link>https://medium.com/@aligok.nl/pressed-focused-active-why-naming-ui-states-correctly-matters-0f9d9136c1a8?source=rss-4e468372f61------2</link>
            <guid isPermaLink="false">https://medium.com/p/0f9d9136c1a8</guid>
            <category><![CDATA[design-systems]]></category>
            <dc:creator><![CDATA[Ali Gök]]></dc:creator>
            <pubDate>Sat, 02 May 2026 12:32:47 GMT</pubDate>
            <atom:updated>2026-05-02T12:41:58.764Z</atom:updated>
            <content:encoded><![CDATA[<p>Most people think design systems are about colors, spacing, buttons, and other reusable components. They are, indeed!</p><p>But after working closely with component libraries and accessibility, I learned something else:</p><p><strong><em>A lot of design system quality lives inside naming decisions.</em></strong></p><p>And one of the most underestimated examples is this simple word: <strong><em>Active</em></strong></p><p>It sounds okay, harmless. However, it often becomes chaos.</p><h3>The problem with “Active”</h3><p>In many teams, “Active” gets used to describe completely different states.</p><p>For example: <strong>Button</strong></p><p>Designer says: Show the <em>Active</em> state when the user clicks on the button.</p><p>Developer thinks: Sure, here is the implementation:</p><pre>button:active</pre><p>That means the button is being pressed right now. Not a real state that the designer wants.</p><p>Another example: <strong>Input</strong></p><p>Designer says: Show the <em>Active</em> state when the user is typing.</p><p>Developer thinks: Sure, here is the implementation:</p><pre>input:active</pre><p>But this solution only applies while the mouse button is held down for a moment. However, the designer really meant that the field is focused and ready for input.</p><p>One more example: <strong>Tabs</strong></p><p>Product owner says: Always show the second tab as “active.”</p><p>And now, “Active” means the currently selected tab.</p><p>So, the same word, but three meanings. That is where confusion starts.</p><h3>Real Design System Evolution</h3><p>A smarter approach is to replace vague state names with precise ones.</p><p>Instead of:</p><ul><li>Idle</li><li>Hover</li><li>Active</li><li>Disabled</li></ul><p>Use:</p><ul><li>Idle</li><li>Hover</li><li>Pressed</li><li>Focused</li><li>Selected</li><li>Disabled</li></ul><p>Now the meaning is clear immediately.</p><p><strong>Pressed: </strong>For buttons, toggles, chips, radios</p><p><strong>Focused: </strong>For inputs, selects, textareas, search fields</p><p><strong>Selected:</strong> For tabs, menus, navigation items</p><p>So, each word maps to real behavior.</p><h3>Accessibility Perspective</h3><p>Focus is not a visual detail.</p><p>It is critical for:</p><ul><li>keyboard users</li><li>screen reader users</li><li>WCAG compliance</li><li>clear navigation</li></ul><p>If your system calls everything “Active”, teams may miss the difference between:</p><ul><li>pressed state</li><li>focus state</li><li>focus-visible state</li><li>selected state</li></ul><p>That’s where accessibility debt begins.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tOZNkt2pE_8mDNzb2mED0g.png" /><figcaption>“Active” state says too much. “Pressed”, “Focused”, “Selected” say it clearly.</figcaption></figure><h3>My Rule of Thumb</h3><p>If a state name can mean multiple things, it probably needs to change.</p><p>Ask those:</p><ul><li>Is this a temporary interaction? -&gt; Pressed</li><li>Is this keyboard/input focus? -&gt; Focused</li><li>Is this a current choice? -&gt; Selected</li><li>Is this unavailable? -&gt; Disabled</li></ul><p>Simple clarity beats clever labels!</p><h3>Final Thought</h3><p>Many teams obsess over spacing tokens or color palettes. Yes, those matter.</p><p>But sometimes the biggest improvement in a design system starts with replacing one confusing word.</p><p><strong><em>In a design system, naming is architecture.</em></strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=0f9d9136c1a8" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why Design Tokens Should Speak Every Language]]></title>
            <link>https://medium.com/@aligok.nl/why-design-tokens-should-speak-every-language-047af4487f47?source=rss-4e468372f61------2</link>
            <guid isPermaLink="false">https://medium.com/p/047af4487f47</guid>
            <category><![CDATA[design-systems]]></category>
            <category><![CDATA[tokenization]]></category>
            <dc:creator><![CDATA[Ali Gök]]></dc:creator>
            <pubDate>Sat, 11 Apr 2026 19:58:14 GMT</pubDate>
            <atom:updated>2026-04-11T19:58:14.291Z</atom:updated>
            <content:encoded><![CDATA[<p>We had design tokens in our system.</p><p>But at some point, we started working with other teams and subsidiaries that were not using Vue.</p><p>That’s when we asked ourselves a simple question:</p><p>Is our design system really framework-agnostic?</p><p>The answer was partly yes. We had tokens, and they were reusable to some extent. But at the same time, we realized that some decisions were still too close to our implementation, which made adoption in other frameworks like React more difficult.</p><p>That moment changed how we thought about tokens.</p><h4>Tokens Are Not the System</h4><p>It’s easy to think that once you have tokens, you’re done.</p><p>You define colors, spacing, and typography, and it feels like you have a solid foundation.</p><p>But tokens alone don’t make a system portable.</p><p>If they are mixed with framework-specific decisions or tightly coupled to how components are built, they lose their value. They stop being a shared language and become just another layer of implementation.</p><p>We saw this when another team tried to use our system. Even though the values were there, the way they were structured made it harder to adopt outside our environment.</p><h4>Breaking the Dependency</h4><p>Originally, many of our design decisions were directly reflected in our components and styling approach. It worked well for us, but it assumed that everyone would use the same stack.</p><p>Once we stepped outside that assumption, the limitations became clear.</p><p>So I started to separate things more clearly:</p><ul><li>Tokens should define <strong>design decisions</strong></li><li>Components should define <strong>implementation</strong></li></ul><p>This meant revisiting how we structured tokens, how we named them, and how they were consumed.</p><p>Instead of thinking in terms of “Vue components with styles,” we started thinking in terms of a system that could be used anywhere.</p><h4>A Neutral Layer</h4><p>The key shift was treating tokens as a neutral layer.</p><p>Not tied to Vue, React, or any specific tool.</p><p>Just <strong>a source of truth</strong>.</p><p>In practice, this meant defining tokens in a format that could be shared and transformed; for example, into CSS variables or into formats usable by other platforms.</p><p>The goal was simple:</p><p>Define once; use everywhere</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JfjDt-bVPjCVaTFjd6_kfw.png" /><figcaption>Design Tokens-One source of truth, used across web, iOS, and Android</figcaption></figure><h4>Naming Matters More Than You Think</h4><p>Another thing I realized was how important naming is.</p><p>If a token is called <em>blue-500</em>, it’s already tied to a specific value.</p><p>But if it’s called <em>interactive-accent</em>, it describes a role. That small difference makes the system much more flexible.</p><p>It allows the same token to evolve, or adapt to different themes, without changing how it’s used.</p><p>The real test came when we started discussing dark mode.</p><p>If a token is named white, it becomes useless in a dark theme. But if it’s named surface-primary, it adapts naturally.</p><p>That’s when the idea of “agnostic” really clicked for us.</p><h4>The Real Lesson</h4><p>For me, the biggest takeaway was this:</p><p>Tokens are not just variables.</p><p>They are a contract between design and engineering.</p><p>If they are designed well, your system can survive changes in frameworks, platforms, and teams.</p><p>If not, you end up rebuilding the same system over and over again.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=047af4487f47" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Green Checkmarks, Broken Experience: Why Automated Accessibility Tools Are Not Enough]]></title>
            <link>https://medium.com/@aligok.nl/green-checkmarks-broken-experience-why-automated-accessibility-tools-are-not-enough-795230b02f85?source=rss-4e468372f61------2</link>
            <guid isPermaLink="false">https://medium.com/p/795230b02f85</guid>
            <category><![CDATA[automated-tools]]></category>
            <category><![CDATA[assistive-technology]]></category>
            <category><![CDATA[accessibility]]></category>
            <category><![CDATA[ux]]></category>
            <category><![CDATA[testing]]></category>
            <dc:creator><![CDATA[Ali Gök]]></dc:creator>
            <pubDate>Sun, 05 Apr 2026 13:30:44 GMT</pubDate>
            <atom:updated>2026-04-05T13:30:44.446Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/376/1*c5OS2NIfgZ8IPgVGA4fFTA.png" /><figcaption><em>Lighthouse score 100, Axe reports 0 issues, but users are still blocked</em></figcaption></figure><p>I love automated accessibility tools. I regularly use tools like <em>Axe</em> and recently started using <em>Evinced</em> before auditing a component. They catch many issues, but they miss problems that only appear during real user interactions.</p><p>For example, consider an input field with validation. When a user enters an invalid value, we often display an error message like:</p><p>“<em>The phone number is invalid. Please enter your phone number in the format 123–456–7890.</em>”</p><p>This works well for sighted users because the message is visible and easy to understand.</p><p>But for screen reader users, nothing may be announced at all. The error appears visually, but without proper ARIA live regions or focus management, it is never communicated.</p><p>Automated accessibility tools cannot detect this kind of issue. They can verify the presence of attributes in the DOM, but they cannot determine whether a message is actually announced to the user at the right time.</p><p>Let’s look at how this problem appears in a real implementation:</p><pre>&lt;div class=&quot;field&quot;&gt;<br>  &lt;label for=&quot;phone&quot;&gt;Phone number&lt;/label&gt;<br>  &lt;input id=&quot;phone&quot; type=&quot;text&quot; /&gt;<br>  &lt;p id=&quot;error&quot; style=&quot;display: none;&quot;&gt;<br>    The phone number is invalid. Please enter your phone number in the format 123–456–7890.<br>  &lt;/p&gt;<br>  &lt;button onclick=&quot;submitForm()&quot;&gt;Submit&lt;/button&gt;<br>&lt;/div&gt;<br><br>&lt;script&gt;<br>  function submitForm() {<br>    const input = document.getElementById(&quot;phone&quot;);<br>    const error = document.getElementById(&quot;error&quot;);<br><br>    if (!input.value) {<br>      error.style.display = &quot;block&quot;;<br>    }<br>  }<br>&lt;/script&gt;</pre><p>However, when the error message appears, nothing is announced by the screen reader. As a result, a screen reader user may not realize what went wrong or how to fix it.</p><p>The problem is not the presence of the error message; it’s <em>the lack of communication</em>.</p><p>The message is visually rendered, but it is not programmatically associated with the input, nor is it announced at the right moment.</p><p>Here is the solution:</p><pre>&lt;div class=&quot;field&quot;&gt;<br>  &lt;label for=&quot;phone&quot;&gt;Phone number&lt;/label&gt;<br>  &lt;input<br>    id=&quot;phone&quot;<br>    type=&quot;text&quot;<br>    required<br>    aria-describedby=&quot;phone-error&quot;<br>  /&gt;<br>  &lt;p<br>    id=&quot;phone-error&quot;<br>    role=&quot;alert&quot;<br>    hidden<br>  &gt;<br>    The phone number is invalid. Please enter your phone number in the format 123–456–7890.<br>  &lt;/p&gt;<br>  &lt;button onclick=&quot;submitForm()&quot;&gt;Submit&lt;/button&gt;<br>&lt;/div&gt;<br><br>&lt;script&gt;<br>  function submitForm() {<br>    const input = document.getElementById(&quot;phone&quot;);<br>    const error = document.getElementById(&quot;phone-error&quot;);<br><br>    if (!input.value) {<br>      input.setAttribute(&quot;aria-invalid&quot;, &quot;true&quot;);<br>      error.hidden = false;<br>    }<br>  }<br>&lt;/script&gt;</pre><p>In this version:</p><ul><li><em>aria-invalid</em> communicates the validation state to assistive technology</li><li><em>aria-describedby</em> links the input to the error message</li><li><em>role=”alert”</em> ensures the message is announced immediately when it appears</li></ul><p>These changes make the error not just visible, but perceivable and actionable for screen reader users.</p><p>Automated tools can verify that attributes like <em>aria-invalid</em> exist.</p><p>But they cannot determine whether a user actually hears the message at the right time, and that’s where real accessibility issues often hide.</p><p>Let’s continue with another common issue that automated accessibility tools often fail to detect: <em>accordion behavior</em>.</p><pre>&lt;div class=&quot;accordion&quot;&gt;<br>  &lt;div onclick=&quot;toggleAccordion()&quot;&gt;<br>    &lt;span&gt;How do I get a discount?&lt;/span&gt;<br>  &lt;/div&gt;<br>  &lt;div id=&quot;content&quot; style=&quot;display: none;&quot;&gt;<br>    Open a savings account to get an extra 0.5% discount.<br>  &lt;/div&gt;<br>&lt;/div&gt;<br><br>&lt;script&gt;<br>  function toggleAccordion() {<br>    const content = document.getElementById(&quot;content&quot;);<br>    content.style.display =<br>      content.style.display === &quot;none&quot; ? &quot;block&quot; : &quot;none&quot;;<br>  }<br>&lt;/script&gt;</pre><p>This implementation works visually: users can click and reveal the content.</p><p>However, it introduces several accessibility issues:</p><ul><li>The clickable element is a <em>&lt;div&gt;</em>, which is not keyboard-accessible</li><li>There is no semantic role indicating that this is a button</li><li>The expanded/collapsed state is not communicated</li><li>Screen reader users receive no indication that the content has changed</li></ul><p>Despite these issues, many automated tools will not flag this as a critical failure.</p><p>Let’s fix this:</p><pre>&lt;div class=&quot;accordion&quot;&gt;<br>  &lt;button<br>    id=&quot;accordion-button&quot;<br>    aria-expanded=&quot;false&quot;<br>    aria-controls=&quot;accordion-content&quot;<br>    onclick=&quot;toggleAccordion()&quot;<br>  &gt;<br>    How do I get a discount?<br>  &lt;/button&gt;<br><br>  &lt;div<br>    id=&quot;accordion-content&quot;<br>    hidden<br>  &gt;<br>    Open a savings account to get an extra 0.5% discount.<br>  &lt;/div&gt;<br>&lt;/div&gt;<br><br>&lt;script&gt;<br>  function toggleAccordion() {<br>    const button = document.getElementById(&quot;accordion-button&quot;);<br>    const content = document.getElementById(&quot;accordion-content&quot;);<br><br>    const isExpanded = button.getAttribute(&quot;aria-expanded&quot;) === &quot;true&quot;;<br><br>    button.setAttribute(&quot;aria-expanded&quot;, String(!isExpanded));<br>    content.hidden = isExpanded;<br>  }<br>&lt;/script&gt;</pre><p>In this version:</p><ul><li>A<em> &lt;button&gt;</em> provides native keyboard interaction</li><li><em>aria-expanded</em> communicates state changes</li><li><em>aria-controls</em> links the trigger to the content</li><li>The <em>hidden</em> attribute ensures proper visibility for assistive technologies</li></ul><p>The component is now both operable and understandable.</p><p>Automated accessibility tools are an essential part of modern frontend development, but they are not enough.</p><p>They can validate structure, detect missing attributes, and catch common issues. But they operate on a static view of the DOM, while real user experience is dynamic, interactive, and time-dependent.</p><p>As we’ve seen, many critical accessibility issues, from missing announcements to broken keyboard interactions, only appear during real user flows.</p><p>A passing report does not guarantee a usable experience.</p><p>Accessibility is not just about what exists in the DOM; it is about how the interface behaves.</p><p><strong>A simple manual testing checklist you can apply immediately:</strong></p><ul><li>Navigate your interface using only the keyboard (Tab, Shift+Tab, Enter, Escape)</li><li>Trigger validation errors and confirm they are announced</li><li>Interact with dynamic components (modals, accordions, dropdowns) and verify state changes are communicated</li><li>Check focus behavior after updates (does it move, stay, or get lost?)</li><li>Test with a screen reader (VoiceOver, NVDA, etc.) for critical flows</li></ul><p>These steps take only a few minutes, but they reveal issues no automated tool can catch.</p><p>Automation gives you confidence, but only manual testing gives you the truth.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=795230b02f85" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>