<?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"><channel><title><![CDATA[The Hux Design]]></title><description><![CDATA[The Hux Design]]></description><link>https://blog.thehuxdesign.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1754576174970/9f0f4466-e4b3-46d2-934f-7fb28b6c18df.png</url><title>The Hux Design</title><link>https://blog.thehuxdesign.com</link></image><generator>RSS for Node</generator><lastBuildDate>Tue, 07 Apr 2026 23:33:18 GMT</lastBuildDate><atom:link href="https://blog.thehuxdesign.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Small yet non-negotiable: Essential accessibility practices every designer and developer must know]]></title><description><![CDATA[A designer's journey into code taught me that true accessibility isn't about grand gestures, it's about the details that matter most.
Four years ago, I started my deep dive into digital accessibility as a designer. Recently, I've begun coding my own ...]]></description><link>https://blog.thehuxdesign.com/essential-accessibility-practices-every-designer-and-developer-must-know</link><guid isPermaLink="true">https://blog.thehuxdesign.com/essential-accessibility-practices-every-designer-and-developer-must-know</guid><category><![CDATA[Accessibility]]></category><category><![CDATA[#WCAG]]></category><category><![CDATA[Design]]></category><category><![CDATA[Frontend Development]]></category><dc:creator><![CDATA[Zoey]]></dc:creator><pubDate>Wed, 06 Aug 2025 17:10:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1754576940670/f89df93b-3f19-4f83-a73d-e4d366ae915d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>A designer's journey into code taught me that true accessibility isn't about grand gestures, it's about the details that matter most.</em></p>
<p>Four years ago, I started my deep dive into digital accessibility as a designer. Recently, I've begun coding my own projects, and this dual perspective has shown me something crucial: the most impactful accessibility improvements aren't always the most obvious ones. They're often small, seemingly minor details that make the difference between a website that works for everyone and one that excludes millions.</p>
<p>If you're a designer who codes, a developer learning design, or anyone building for the web, these "small yet non-negotiable" practices will transform how your users experience your work.</p>
<h2 id="heading-why-small-details-have-massive-impact">Why "Small" details have massive impact</h2>
<p>Here's what surprised me most about accessibility: a single missing focus state can make an entire website unusable for keyboard users. One poorly structured heading can leave screen reader users completely lost. A color choice that looks sophisticated can render critical information invisible to users with color vision differences.</p>
<p>The math is sobering: <strong>over 1 billion people worldwide live with some form of disability.</strong> That's not a niche market, that's a fundamental part of your audience.</p>
<p>But here's what really changed my perspective: accessible design isn't just better for users with disabilities. It's better for everyone.</p>
<p>The curb cut effect is real: when you design for accessibility, you create experiences that work better in bright sunlight, on slow connections, with broken mice, during multitasking, and in countless other everyday scenarios.</p>
<h2 id="heading-the-foundation-understanding-wcag-without-the-overwhelm">The Foundation: Understanding WCAG without the overwhelm</h2>
<p>The Web Content Accessibility Guidelines (WCAG) can feel daunting at first: 168 success criteria across three conformance levels. But here's what four years of study taught me: focus on the patterns, not the individual rules.</p>
<p>WCAG is built on four principles, remembered by the acronym <strong>POUR</strong>:</p>
<ul>
<li><p><strong>Perceivable</strong>: Information must be presentable in ways users can perceive</p>
</li>
<li><p><strong>Operable</strong>: Interface components must be operable</p>
</li>
<li><p><strong>Understandable</strong>: Information and UI operation must be understandable</p>
</li>
<li><p><strong>Robust</strong>: Content must be robust enough for various assistive technologies</p>
</li>
</ul>
<p>Most accessibility wins come from mastering a handful of Level A and AA criteria that address these principles directly.</p>
<h2 id="heading-the-non-negotiables-design-perspective">The non-negotiables: Design perspective</h2>
<h3 id="heading-color-contrast-isnt-optional">Color contrast isn't optional</h3>
<p><strong>WCAG 2.1 AA requires 4.5:1 contrast ratio for normal text, 3:1 for large text.</strong></p>
<p>As designers, we love subtle grays and elegant low-contrast palettes. But here's the reality: insufficient contrast doesn't just fail automated tests, it makes content unreadable for users with visual impairments, color vision differences, and anyone using their device in bright sunlight.</p>
<p><strong>Tools that changed my workflow:</strong></p>
<ul>
<li><p><strong>Figma plugins</strong>: Contrast, Stark - Color Contrast Checker</p>
</li>
<li><p><strong>Browser extensions, websites</strong>: WAVE, Accessibility Checker</p>
</li>
<li><p><strong>Design system integration</strong>: Build contrast checking into your component library. (I actually built a UI library for Flutter with built-in contrast checking, <a target="_blank" href="https://hashnode.com/post/cmcqrlxmh000002jl8p6m1nx7">The Hux UI</a>, if you want to check it out).</p>
</li>
</ul>
<p><strong>Pro tip</strong>: Don't just check your primary color palette. Test hover states, disabled buttons, and placeholder text. These often slip through the cracks.</p>
<h3 id="heading-typography-hierarchy-that-actually-works">Typography hierarchy that actually works</h3>
<p>Good information hierarchy isn't just visually pleasing, it's assistive technology's roadmap through your content.</p>
<p><strong>The non-negotiables:</strong></p>
<ul>
<li><p>Use actual heading tags (H1, H2, H3) in logical order, not just styled divs</p>
</li>
<li><p>Ensure headings describe the content that follows</p>
</li>
<li><p>Maintain consistent heading hierarchy across pages</p>
</li>
<li><p>Design with 16px minimum font size for body text</p>
</li>
</ul>
<h3 id="heading-focus-states-the-most-overlooked-ux-element">Focus States: The most overlooked UX element</h3>
<p>Every interactive element needs a visible focus indicator. Yet I see beautiful designs ship with <code>outline: none</code> and no replacement focus state.</p>
<p><strong>Design focus states that:</strong></p>
<ul>
<li><p>Have sufficient contrast (3:1 minimum against adjacent colors)</p>
</li>
<li><p>Are clearly distinguishable from hover states</p>
</li>
<li><p>Work across all interactive elements consistently</p>
</li>
<li><p>Don't rely solely on color changes</p>
</li>
</ul>
<h2 id="heading-the-non-negotiables-development-perspective">The non-negotiables: Development perspective</h2>
<h3 id="heading-semantic-html-is-your-superpower">Semantic HTML is your superpower</h3>
<p>Moving from design to code taught me that semantic HTML isn't just "best practice", it's the foundation of accessibility.</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- Instead of this --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"button"</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">"submitForm()"</span>&gt;</span>Submit<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-comment">&lt;!-- Write this --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Submit<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<p><strong>Why this matters:</strong></p>
<ul>
<li><p>Screen readers understand the purpose immediately</p>
</li>
<li><p>Keyboard navigation works by default</p>
</li>
<li><p>Mobile assistive technologies recognize interactive elements</p>
</li>
<li><p>No JavaScript? The button still works.</p>
</li>
</ul>
<h3 id="heading-alt-text-quality-over-compliance">Alt Text: Quality over compliance</h3>
<p>Every image needs alt text, but not all alt text is helpful. Here's the difference between compliance and good UX:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- Compliance but not helpful --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"chart.jpg"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"chart"</span>&gt;</span>

<span class="hljs-comment">&lt;!-- Actually useful --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"chart.jpg"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Bar chart showing 40% increase in mobile users from 2022 to 2023"</span>&gt;</span>

<span class="hljs-comment">&lt;!-- Decorative images --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"decorative-line.svg"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"presentation"</span>&gt;</span>
</code></pre>
<p><strong>The test</strong>: Could someone understand your content if they couldn't see your images?</p>
<h3 id="heading-form-accessibility-that-actually-works">Form accessibility that actually works</h3>
<p>Forms are where accessibility often breaks down. Here's your checklist:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- Proper form structure --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"email"</span>&gt;</span>Email Address *<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> 
    <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span> 
    <span class="hljs-attr">id</span>=<span class="hljs-string">"email"</span> 
    <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span> 
    <span class="hljs-attr">required</span> 
    <span class="hljs-attr">aria-describedby</span>=<span class="hljs-string">"email-error"</span>
    <span class="hljs-attr">aria-invalid</span>=<span class="hljs-string">"false"</span>
  &gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"email-error"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"error-message"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"alert"</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- Error message appears here --&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p><strong>Non-negotiable form practices:</strong></p>
<ul>
<li><p>Every input has a proper label (not just placeholder text)</p>
</li>
<li><p>Error messages are programmatically associated with inputs</p>
</li>
<li><p>Required fields are clearly marked</p>
</li>
<li><p>Success and error states are announced to screen readers</p>
</li>
</ul>
<h2 id="heading-tools-that-transformed-my-workflow">Tools that transformed my workflow</h2>
<h3 id="heading-design-phase">Design Phase</h3>
<ul>
<li><p><strong>Figma plugins</strong>: Contrast or Stark for contrast checking, Include for accessibility annotations</p>
</li>
<li><p><strong>Color tools</strong>: WebAIM Contrast Checker, Colour Contrast Analyser</p>
</li>
<li><p><strong>Typography</strong>: Check line spacing (1.5x minimum) and paragraph spacing</p>
</li>
</ul>
<h3 id="heading-development-phase">Development Phase</h3>
<ul>
<li><p><strong>Browser extensions</strong>: axe DevTools (the gold standard), WAVE</p>
</li>
<li><p><strong>Automated testing</strong>: Pa11y, axe-core for CI/CD integration</p>
</li>
<li><p><strong>Manual testing</strong>: Navigate your site using only the keyboard, test with screen readers</p>
</li>
</ul>
<h3 id="heading-the-plugin-reality-check">The Plugin reality check</h3>
<p>Accessibility plugins are incredibly useful, but they catch maybe 30% of accessibility issues. The other 70%? That requires understanding your users and testing with real people.</p>
<p><strong>Use plugins for:</strong></p>
<ul>
<li><p>Color contrast validation</p>
</li>
<li><p>Missing alt text detection</p>
</li>
<li><p>Heading structure analysis</p>
</li>
<li><p>Basic ARIA errors</p>
</li>
</ul>
<p><strong>Don't rely on plugins for:</strong></p>
<ul>
<li><p>Alt text quality</p>
</li>
<li><p>Logical reading order</p>
</li>
<li><p>Content comprehensibility</p>
</li>
<li><p>User experience flow</p>
</li>
</ul>
<h2 id="heading-beyond-compliance-building-inclusive-experiences">Beyond compliance: Building inclusive experiences</h2>
<p>After four years studying accessibility and transitioning into code, I've learned that the goal isn't WCAG compliance, it's creating genuinely inclusive experiences.</p>
<p><strong>This means:</strong></p>
<ul>
<li><p>Testing with actual assistive technology users</p>
</li>
<li><p>Considering cognitive accessibility, not just screen reader compatibility</p>
</li>
<li><p>Building flexible interfaces that work across different abilities and contexts</p>
</li>
<li><p>Making accessibility part of your design system, not an afterthought</p>
</li>
</ul>
<h2 id="heading-start-small-impact-big">Start small, impact big</h2>
<p>You don't need to revolutionize your entire workflow overnight. Study those three things and implement them in your next project:</p>
<ol>
<li><p><strong>Check color contrast</strong> for all text elements</p>
</li>
<li><p><strong>Add proper focus states</strong> to all interactive elements</p>
</li>
<li><p><strong>Use semantic HTML</strong> instead of generic divs and spans</p>
</li>
</ol>
<p>These small changes will improve the experience for millions of users while making your code more maintainable and your designs more robust.</p>
<h2 id="heading-the-path-forward">The path forward</h2>
<p>Accessibility isn't a checklist to complete but more a practice to cultivate. As designers and developers, we have the power to decide who gets to participate in the digital world we're creating.</p>
<p>The techniques I've shared aren't just nice-to-haves or legal requirements. They're the foundation of inclusive design and development. They're non-negotiable because the alternative (excluding users based on ability) simply isn't acceptable.</p>
<p>Your next project is an opportunity to get this right from the start. Your users (all of them) are counting on it.</p>
<hr />
<p><em>What accessibility practices have transformed your design or development workflow? Share your experiences in the comments below.</em></p>
<hr />
<p><strong>Resources mentioned in this article:</strong></p>
<ul>
<li><p><a target="_blank" href="https://www.w3.org/WAI/WCAG21/quickref/">WCAG 2.1 Guidelines</a></p>
</li>
<li><p><a target="_blank" href="https://webaim.org/resources/contrastchecker/">WebAIM Contrast Checker</a></p>
</li>
<li><p><a target="_blank" href="https://www.deque.com/axe/browser-extensions/">axe DevTools Browser Extension</a></p>
</li>
<li><p><a target="_blank" href="https://wave.webaim.org/">WAVE Web Accessibility Evaluation Tool</a></p>
</li>
<li><p><a target="_blank" href="https://pa11y.org/">Pa11y Command Line Accessibility Tester</a></p>
</li>
<li><p><a target="_blank" href="https://hashnode.com/post/cmcqrlxmh000002jl8p6m1nx7">The Hux UI</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Building WCAG-Compliant Flutter Components: Automating Contrast Calculations]]></title><description><![CDATA[While building Hux UI, I kept running into the same accessibility problem: buttons with custom colors that had terrible text contrast. You'd pick a nice brand color, slap white text on it, and suddenly your button was unreadable.
Instead of manually ...]]></description><link>https://blog.thehuxdesign.com/building-wcag-compliant-flutter-components-automating-contrast-calculations</link><guid isPermaLink="true">https://blog.thehuxdesign.com/building-wcag-compliant-flutter-components-automating-contrast-calculations</guid><category><![CDATA[Flutter]]></category><category><![CDATA[a11y]]></category><category><![CDATA[#WCAG]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[UI]]></category><category><![CDATA[Frontend Development]]></category><dc:creator><![CDATA[Zoey]]></dc:creator><pubDate>Tue, 05 Aug 2025 10:44:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1754390665060/fd29df4d-d361-4520-bd6d-ccc95d5933a3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>While building Hux UI, I kept running into the same accessibility problem: buttons with custom colors that had terrible text contrast. You'd pick a nice brand color, slap white text on it, and suddenly your button was unreadable.</p>
<p>Instead of manually checking contrast ratios every time, I decided to build a system that handles this automatically. Here's how I implemented WCAG-compliant contrast calculations in Flutter.</p>
<h2 id="heading-the-problem-with-manual-contrast-checking"><strong>The Problem with Manual Contrast Checking</strong></h2>
<p>Most design systems punt on this problem. They give you preset color combinations that work, but the moment you use a custom brand color, you're on your own.</p>
<pre><code class="lang-plaintext">// This could be completely unreadable
Container(
  color: myBrandColor, // Could be any color
  child: Text('Button Text', style: TextStyle(color: Colors.white)),
)
</code></pre>
<h2 id="heading-the-wcag-algorithm"><strong>The WCAG Algorithm</strong></h2>
<p>WCAG defines contrast ratio as the luminance difference between two colors. The formula is:</p>
<pre><code class="lang-plaintext">contrast = (lighter + 0.05) / (darker + 0.05)
</code></pre>
<p>Where luminance is calculated using the sRGB color space with gamma correction. For normal text, you need at least 4.5:1 contrast ratio for AA compliance.</p>
<h2 id="heading-implementation-in-flutter"><strong>Implementation in Flutter</strong></h2>
<p>Here's how I implemented the contrast calculation system:</p>
<pre><code class="lang-plaintext">/// Calculates the relative luminance of a color according to WCAG guidelines
double _getRelativeLuminance(Color color) {
  // Convert RGB values to 0-1 range
  final r = color.r / 255.0;
  final g = color.g / 255.0;
  final b = color.b / 255.0;

  // Apply gamma correction
  final rLinear = r &lt;= 0.03928 ? r / 12.92 : pow((r + 0.055) / 1.055, 2.4);
  final gLinear = g &lt;= 0.03928 ? g / 12.92 : pow((g + 0.055) / 1.055, 2.4);
  final bLinear = b &lt;= 0.03928 ? b / 12.92 : pow((b + 0.055) / 1.055, 2.4);

  // Calculate relative luminance using ITU-R BT.709 coefficients
  return 0.2126 * rLinear + 0.7152 * gLinear + 0.0722 * bLinear;
}

/// Calculates contrast ratio between two colors
double _calculateContrastRatio(Color color1, Color color2) {
  final luminance1 = _getRelativeLuminance(color1);
  final luminance2 = _getRelativeLuminance(color2);

  final lighter = luminance1 &gt; luminance2 ? luminance1 : luminance2;
  final darker = luminance1 &gt; luminance2 ? luminance2 : luminance1;

  return (lighter + 0.05) / (darker + 0.05);
}
</code></pre>
<p>The tricky part is the gamma correction. sRGB colors aren't linear - they use a gamma curve to match how displays work. You have to convert to linear RGB before calculating luminance.</p>
<h2 id="heading-automatic-text-color-selection"><strong>Automatic Text Color Selection</strong></h2>
<p>Now I can automatically pick the best text color:</p>
<pre><code class="lang-plaintext">Color _getContrastingTextColor(Color backgroundColor, BuildContext context) {
  final whiteContrast = _calculateContrastRatio(
    backgroundColor, 
    HuxTokens.textInvert(context)
  );
  final blackContrast = _calculateContrastRatio(
    backgroundColor, 
    HuxTokens.textPrimary(context)
  );

  // Choose the color with better contrast
  return whiteContrast &gt; blackContrast
      ? HuxTokens.textInvert(context)
      : HuxTokens.textPrimary(context);
}
</code></pre>
<p>This runs every time a button renders, automatically ensuring WCAG AA compliance regardless of the background color.</p>
<h2 id="heading-semantic-design-tokens"><strong>Semantic Design Tokens</strong></h2>
<p>The other technical challenge was building a theme system that works in both light and dark mode. Instead of hardcoding colors, I built semantic tokens:</p>
<pre><code class="lang-plaintext">class HuxTokens {
  /// Primary text color that adapts to light/dark theme
  static Color textPrimary(BuildContext context) {
    final isDark = Theme.of(context).brightness == Brightness.dark;
    return isDark ? HuxColors.white : HuxColors.black;
  }

  /// Surface color for elevated components
  static Color surfaceElevated(BuildContext context) {
    final isDark = Theme.of(context).brightness == Brightness.dark;
    return isDark ? HuxColors.black70 : HuxColors.white;
  }
}
</code></pre>
<p>Every component uses these tokens instead of raw colors. When you switch themes, everything adapts automatically without any component-level changes.</p>
<h2 id="heading-performance-considerations"><strong>Performance Considerations</strong></h2>
<p>You might worry about calculating contrast ratios on every render, but:</p>
<ol>
<li><p><strong>It's fast</strong>: The math is just basic arithmetic, no expensive operations</p>
</li>
<li><p><strong>It's necessary</strong>: The alternative is manually checking every color combination</p>
</li>
<li><p><strong>It's cached</strong>: Flutter's widget rebuilding is smart about when this actually runs</p>
</li>
</ol>
<h2 id="heading-real-world-usage"><strong>Real-World Usage</strong></h2>
<p>In the actual component, it looks like this:</p>
<pre><code class="lang-plaintext">ButtonStyle _getButtonStyle(BuildContext context) {
  final effectivePrimaryColor = primaryColor ?? HuxTokens.primary(context);
  final foregroundColor = _getContrastingTextColor(effectivePrimaryColor, context);

  return ButtonStyle(
    backgroundColor: WidgetStateProperty.all(effectivePrimaryColor),
    foregroundColor: WidgetStateProperty.all(foregroundColor),
    // ... other styles
  );
}
</code></pre>
<p>No matter what color you pass in, the text will be readable.</p>
<h2 id="heading-testing-the-algorithm"><strong>Testing the Algorithm</strong></h2>
<p>I tested this against the <a target="_blank" href="https://webaim.org/resources/contrastchecker/">WebAIM contrast checker</a> to make sure my implementation matches the WCAG spec. The results are identical.</p>
<p>You can test it yourself:</p>
<pre><code class="lang-plaintext">HuxButton(
  primaryColor: Color(0xFF6366F1), // Any color
  child: Text('Always Readable'),
  onPressed: () {},
)
</code></pre>
<h2 id="heading-why-this-matters"><strong>Why This Matters</strong></h2>
<p>Accessibility shouldn't be an afterthought. By building it into the component layer, developers get WCAG compliance without having to think about it.</p>
<p>The contrast calculation runs automatically, the semantic tokens handle theme switching, and your app stays accessible regardless of design changes.</p>
<h2 id="heading-the-trade-offs"><strong>The Trade-offs</strong></h2>
<p><strong>Pros:</strong></p>
<ul>
<li><p>Zero cognitive overhead for developers</p>
</li>
<li><p>Guaranteed WCAG AA compliance</p>
</li>
<li><p>Works with any color combination</p>
</li>
<li><p>Adapts to theme changes automatically</p>
</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li><p>Slight computation cost (negligible in practice)</p>
</li>
<li><p>Less control over exact text colors (though you probably don't want that control)</p>
</li>
</ul>
<h2 id="heading-try-it-out"><strong>Try It Out</strong></h2>
<p>The system is part of <a target="_blank" href="https://pub.dev/packages/hux">Hux UI</a>, but the algorithms are standalone. You could implement this in any Flutter project:</p>
<pre><code class="lang-plaintext">flutter pub add hux
</code></pre>
<p>Have you implemented accessibility features in your component libraries? I'm curious about other approaches to this problem!</p>
<hr />
<p>🔗 <strong>Links:</strong></p>
<ul>
<li><p><a target="_blank" href="https://pub.dev/packages/hux">Hux UI on pub.dev</a></p>
</li>
<li><p><a target="_blank" href="https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html">WCAG Contrast Guidelines</a></p>
</li>
<li><p><a target="_blank" href="https://webaim.org/resources/contrastchecker/">WebAIM Contrast Checker</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Meet Hux UI: The Flutter library I wish I had a year ago]]></title><description><![CDATA[You know that feeling when you're building something and you keep thinking "there has to be a better way to do this"? That's exactly how Hux UI was born.
After spending way too much time recreating the same buttons, cards, and input fields across dif...]]></description><link>https://blog.thehuxdesign.com/meet-hux-ui-open-source-ui-library-for-flutter</link><guid isPermaLink="true">https://blog.thehuxdesign.com/meet-hux-ui-open-source-ui-library-for-flutter</guid><category><![CDATA[UI]]></category><category><![CDATA[Flutter]]></category><category><![CDATA[library]]></category><category><![CDATA[widgets]]></category><category><![CDATA[Design Systems]]></category><category><![CDATA[Frontend Development]]></category><dc:creator><![CDATA[Zoey]]></dc:creator><pubDate>Sat, 05 Jul 2025 21:38:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1751749772272/d5f14884-fdc8-4e8d-9970-d1a21ffdfd04.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You know that feeling when you're building something and you keep thinking "there has to be a better way to do this"? That's exactly how Hux UI was born.</p>
<p>After spending way too much time recreating the same buttons, cards, and input fields across different projects (and watching them get implemented differently each time), I decided to build the component library I actually wanted to use.</p>
<h2 id="heading-whats-inside">What's Inside</h2>
<p>Hux UI isn't trying to be everything to everyone. It's a focused set of components that cover the stuff you use every day, but done really well.</p>
<h3 id="heading-huxbuttons">HuxButtons</h3>
<p>I got tired of recreating the same button variations everywhere, so I built four that cover most use cases: primary, secondary, outline, and ghost. Three sizes that actually make sense together.</p>
<p>The thing I'm proudest of is the loading state handling. Instead of having to conditionally render spinners and disable buttons manually, you just flip the <code>isLoading</code> parameter and it handles everything. And when you use custom colors, the contrast calculation system I built automatically figures out whether to use white or black text so your buttons stay readable.</p>
<h3 id="heading-huxcards">HuxCards</h3>
<p>I built these because I was constantly rebuilding the same container pattern. Clean borders, consistent padding, optional headers and subtitles. If you need an action button in the corner, there's a spot for it. You can make them tappable or just use them as containers. The styling stays consistent whether you're in light or dark mode.</p>
<h3 id="heading-huxtextfield">HuxTextField</h3>
<p>I got tired of shipping text fields and then realizing during testing that we forgot to add hints or proper error states. Now they're built in by default, so you won't forget them. Labels, validation, icons, different sizes - all the stuff you end up needing anyway, but available from the start. The whole thing adapts to your theme automatically.</p>
<h3 id="heading-huxloading">HuxLoading</h3>
<p>Loading states are one of those things that seem simple until you have to implement them everywhere. I built a few different options: small spinners for inline use, and a full overlay component for when you need to block the whole screen. They all use the same design language and handle the edge cases properly.</p>
<h3 id="heading-huxchart">HuxChart</h3>
<p>Built on <a target="_blank" href="https://cristalyse.com/">cristalyse</a> for the heavy lifting, but wrapped in Hux styling. Line charts, bar charts, with titles and proper theming. Your data should look as good as the rest of your app.</p>
<h3 id="heading-huxcontextmenu">HuxContextMenu</h3>
<p>I added these because proper right-click interactions make apps feel more professional. The positioning is smart enough to avoid going off-screen, and I made sure they work properly on web (disabling the browser's default context menu). It's one of those details that users notice when it's missing.</p>
<h2 id="heading-the-theme-system">The Theme System</h2>
<p>This is where I got a bit obsessed. Every component uses semantic design tokens that adapt to light and dark mode. No hardcoded colors, no "oops this looks terrible in dark mode" surprises.</p>
<p>The color system follows design best practices: primitive colors separate from semantic tokens. Your primary brand color can be anything, and everything else adjusts accordingly.</p>
<h2 id="heading-why-i-built-it-this-way">Why I built it this way</h2>
<p>I wanted components that are:</p>
<ul>
<li><p><strong>Consistent</strong>: They all feel like they belong together</p>
</li>
<li><p><strong>Accessible</strong>: WCAG AA compliance isn't optional</p>
</li>
<li><p><strong>Themeable</strong>: Light and dark mode should just work</p>
</li>
<li><p><strong>Practical</strong>: Built for real projects, not just demos</p>
</li>
</ul>
<h2 id="heading-getting-started">Getting Started</h2>
<pre><code class="lang-bash">flutter pub add hux
</code></pre>
<p>Then wrap your app with the theme:</p>
<pre><code class="lang-dart">MaterialApp(
  theme: HuxTheme.lightTheme,
  darkTheme: HuxTheme.darkTheme,
  <span class="hljs-comment">// your app here</span>
)
</code></pre>
<p>And start using components:</p>
<pre><code class="lang-dart">HuxButton(
  onPressed: () =&gt; <span class="hljs-built_in">print</span>(<span class="hljs-string">'Hello'</span>),
  child: Text(<span class="hljs-string">'Click me'</span>),
)
</code></pre>
<h2 id="heading-the-real-talk">The Real Talk</h2>
<p>This isn't a massive design system with 47 different button variants and components for every edge case. It's the components you actually use, built really well.</p>
<p>I'm using it in my own projects, which means it has to work in the real world, not just in demos. Every component gets battle-tested, and accessibility isn't something I tacked on at the end.</p>
<p>If you're tired of rebuilding the same components over and over, or if you just want something that looks good out of the box, give it a shot.</p>
<p>It's <a target="_blank" href="https://github.com/zoeglbrt/hux">open source</a>, available on <a target="_blank" href="http://pub.dev">pub.dev</a>, and hopefully saves you some time so you can focus on the stuff that actually makes your app unique.</p>
<hr />
<p><em>Check out Hux UI on</em> <a target="_blank" href="https://pub.dev/packages/hux"><em>pub.dev</em></a> <em>or the</em> <a target="_blank" href="https://github.com/zoeglbrt/hux"><em>GitHub repo</em></a> <em>to get started.</em></p>
]]></content:encoded></item></channel></rss>