<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged ui</title>
<link>https://coderlegion.com/tag/ui</link>
<description>Powered by Question2Answer</description>
<item>
<title>Kavro.Pro Stop writing your UI by hand.</title>
<link>https://coderlegion.com/31729/kavro-pro-stop-writing-your-ui-by-hand</link>
<description>&lt;h3 id=&quot;design-dear-imgui-menus-visually-then-build-a-real-exe&quot;&gt;Design Dear ImGui menus visually, then build a real .exe&lt;/h3&gt;
&lt;p&gt;Kavro is a drag-and-drop designer for &lt;strong&gt;Dear ImGui&lt;/strong&gt; windows, tool menus and launchers. Stop nudging SetCursorPos values and recompiling: drop widgets on a canvas, style them, test the window, and export clean code in C++, C# or Rust.&lt;/p&gt;
&lt;h3 id=&quot;what-you-can-do&quot;&gt;What you can do&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Drag &amp;amp; drop 23 widgets: text, buttons, checkboxes, switches, sliders,&lt;br&gt;
dropdowns, color pickers, hotkeys, tabs, lists, progress bars,&lt;br&gt;
spinners and more &lt;/li&gt;
&lt;li&gt;Themes &amp;amp; styles: one-click presets (Kavro Dark,&lt;br&gt;
Midnight Violet, Ocean, Sakura, Ember…) or per-widget colors, fonts&lt;br&gt;
and rounding &lt;/li&gt;
&lt;li&gt;13 animated backgrounds and 12 built-in actions (switch&lt;br&gt;
pages, toasts, loading screens…) &lt;/li&gt;
&lt;li&gt;Test mode (F6): use your window right inside the editor &lt;/li&gt;
&lt;li&gt;Live code: your UI is plain kv::Button(...) /&lt;br&gt;
kv::Slider(...) calls.  Edit the code and the canvas updates, or the&lt;br&gt;
other way round &lt;/li&gt;
&lt;li&gt;Build &amp;amp; Run (F5): compiles a native Windows .exe in&lt;br&gt;
seconds C++: Dear ImGui + DX11/Vulkan/DX9/DX12/OpenGL (MSVC) Rust: imgui-rs + glium&lt;br&gt;
(Cargo) C#: ImGui.NET + Silk.NET (.NET 8) &lt;/li&gt;
&lt;li&gt;Kavro AI tab: describe a&lt;br&gt;
change and let the AI edit your menu&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;free-and-pro&quot;&gt;Free and Pro&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Free: design and test everything. &lt;/li&gt;
&lt;li&gt;Pro ($10/month or $108/year): Build &amp;amp; Run, source export, all languages, all templates and the AI tab.&lt;/li&gt;
&lt;li&gt;Get Pro at &lt;a rel=&quot;nofollow&quot; href=&quot;https://kavro.pro&quot;&gt;https://kavro.pro&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;requirements&quot;&gt;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Windows 10 or 11 (64-bit)&lt;/li&gt;
&lt;li&gt;A free kavro.pro account (you sign in when Kavro starts)&lt;/li&gt;
&lt;li&gt;To build: Visual Studio with the C++ workload (C++), Rust/Cargo (Rust) or the .NET 8 SDK (C#)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;links&quot;&gt;Links&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Website: &lt;a rel=&quot;nofollow&quot; href=&quot;https://kavro.pro&quot;&gt;https://kavro.pro&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Discord, for help and updates: &lt;a rel=&quot;nofollow&quot; href=&quot;https://discord.gg/GeFa4vdTD&quot;&gt;https://discord.gg/GeFa4vdTD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;YouTube tutorials: &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.youtube.com/@kavropro&quot;&gt;https://www.youtube.com/@kavropro&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Itch.io link: &lt;a rel=&quot;nofollow&quot; href=&quot;https://kavro-pro.itch.io/kavro&quot;&gt;https://kavro-pro.itch.io/kavro&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Kavro updates itself when a new version is out.&lt;/strong&gt;&lt;/p&gt;
</description>
<category>Launches</category>
<guid isPermaLink="true">https://coderlegion.com/31729/kavro-pro-stop-writing-your-ui-by-hand</guid>
<pubDate>Mon, 19 Oct 2026 21:28:35 +0000</pubDate>
</item>
<item>
<title>Designing overlapped / cascaded UI with overlapui</title>
<link>https://coderlegion.com/29968/designing-overlapped-cascaded-ui-with-overlapui</link>
<description>&lt;p&gt;Build avatar stacks, notification piles, image strips, and radial menus with a token-driven CSS architecture—rest vs open states, no JavaScript for the interaction—using the overlapui FSCSS module.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reference:&lt;/strong&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/fscss-ttr/overlapui.fscss&quot;&gt;overlapui.fscss&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Stacked faces in a members column, cards that peek under each other, photos that share one edge, or a center control that fans into actions: that look is usually a pile of one-off rules. &lt;strong&gt;overlapui&lt;/strong&gt; treats it as a small architecture—shared &lt;code&gt;--ou-*&lt;/code&gt; tokens, four cascade patterns, hover and focus-within open states—and compiles to plain CSS.&lt;/p&gt;
&lt;p&gt;This article is description- and code-based: how the layers fit, with copy-paste examples. The only project reference is the module itself.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;what-cascaded-ui-means-here&quot;&gt;What “cascaded UI” means here&lt;/h3&gt;
&lt;p&gt;A cascade has two densities:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rest&lt;/strong&gt; — children share space (negative margin, peek, or stacked under a hub).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Open&lt;/strong&gt; — &lt;code&gt;:hover&lt;/code&gt; or &lt;code&gt;:focus-within&lt;/code&gt; restores gap, full card height, or a radial orbit.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Tokens describe density and chrome. Mixins encode the rest/open contract. Markup stays light lists, card roots, or a center-plus-satellites control.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Pattern &lt;/th&gt;&lt;th&gt;Rest &lt;/th&gt;&lt;th&gt;Open&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Avatar &lt;/td&gt;&lt;td&gt;horizontal pull-in &lt;/td&gt;&lt;td&gt;sibling gap&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Card &lt;/td&gt;&lt;td&gt;vertical peek &lt;/td&gt;&lt;td&gt;expanded margins&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Image &lt;/td&gt;&lt;td&gt;overlap + tilt &lt;/td&gt;&lt;td&gt;align + gap&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Circle &lt;/td&gt;&lt;td&gt;satellites hidden under center &lt;/td&gt;&lt;td&gt;polar fan-out&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h3 id=&quot;setup&quot;&gt;Setup&lt;/h3&gt;
&lt;p&gt;Use FSCSS &lt;strong&gt;1.2.3+&lt;/strong&gt; (1.2.5+ recommended). Load the runtime with &lt;code&gt;defer&lt;/code&gt; or &lt;code&gt;async&lt;/code&gt; when prototyping.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;script src=&quot;https://cdn.jsdelivr.net/npm/fscss@1.2.5/runtime.min.js&quot; defer&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-css&quot;&gt;@import((*) from overlapui)

@ou-root()
@avatar-overlap(.avatar-overlap)
@card-overlap(.card-overlap)
@img-overlap(.img-overlap)
@circle-overlap(.circle-overlap)
@ou-reduced-motion()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One-shot install (default class names):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-css&quot;&gt;@import((*) from overlapui)
@overlapui()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Selective import:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-css&quot;&gt;@import((ou-root, ou-avatar-colors avatar-overlap, circle-overlap, ou-reduced-motion) from overlapui)

@ou-root()
@avatar-overlap(.team)
@circle-overlap(.fab)
@ou-reduced-motion()
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;layer-1-tokens---ou--&quot;&gt;Layer 1 — tokens (&lt;code&gt;--ou-*&lt;/code&gt;)&lt;/h3&gt;
&lt;p&gt;Theme the product by overriding tokens after &lt;code&gt;@ou-root()&lt;/code&gt;, not by forking mixin internals.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-css&quot;&gt;@ou-root()

:root {
  --ou-ring: #0f172a;
  --ou-time: 0.35s;
  --ou-ease: cubic-bezier(0.3, 1.3, 0.5, 1);
  --ou-center-bg: #6366f1;

  @ou-avatar-size(44px, -14px)
  @ou-card-size(34px, 76px)
  @ou-img-size(96px, -52px)
  @ou-circle-size(48px, 80px)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Token area &lt;/th&gt;&lt;th&gt;Variables (examples)&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Motion / chrome &lt;/td&gt;&lt;td&gt;&lt;code&gt;--ou-time&lt;/code&gt;, &lt;code&gt;--ou-ease&lt;/code&gt;, &lt;code&gt;--ou-ring&lt;/code&gt;, &lt;code&gt;--ou-ring-width&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Avatar &lt;/td&gt;&lt;td&gt;&lt;code&gt;--ou-size&lt;/code&gt;, &lt;code&gt;--ou-overlap&lt;/code&gt;, &lt;code&gt;--ou-gap&lt;/code&gt;, &lt;code&gt;--ou-c&lt;/code&gt;, &lt;code&gt;--ou-letter&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Card &lt;/td&gt;&lt;td&gt;&lt;code&gt;--ou-peek&lt;/code&gt;, &lt;code&gt;--ou-card-h&lt;/code&gt;, &lt;code&gt;--ou-card-gap&lt;/code&gt;, &lt;code&gt;--ou-card-bg&lt;/code&gt;, &lt;code&gt;--ou-card-title&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Image &lt;/td&gt;&lt;td&gt;&lt;code&gt;--ou-img&lt;/code&gt;, &lt;code&gt;--ou-img-overlap&lt;/code&gt;, &lt;code&gt;--ou-img-gap&lt;/code&gt;, &lt;code&gt;--ou-img-tilt&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Circle &lt;/td&gt;&lt;td&gt;&lt;code&gt;--ou-item&lt;/code&gt;, &lt;code&gt;--ou-r&lt;/code&gt;, &lt;code&gt;--ou-center-bg&lt;/code&gt;, &lt;code&gt;--n&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Dense UI (tables, toolbars): smaller size, stronger overlap.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-css&quot;&gt;:root {
  @ou-avatar-size(28px, -10px)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;layer-2-avatar-cascade&quot;&gt;Layer 2 — avatar cascade&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Role:&lt;/strong&gt; presence clusters—members, assignees, “also on this thread.”&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;ul class=&quot;avatar-overlap&quot; tabindex=&quot;0&quot;&amp;gt;
  &amp;lt;li data-alph=&quot;g&quot;&amp;gt;Gina Park&amp;lt;/li&amp;gt;
  &amp;lt;li data-alph=&quot;h&quot;&amp;gt;
    &amp;lt;img src=&quot;https://i.pravatar.cc/80?img=12&quot; alt=&quot;&quot;&amp;gt;
    Hank Lee
  &amp;lt;/li&amp;gt;
  &amp;lt;li data-alph=&quot;5&quot;&amp;gt;5001&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-css&quot;&gt;@ou-root()
@avatar-overlap(.avatar-overlap)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Behavior encoded by the module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Rest: each face after the first uses &lt;code&gt;margin-left: var(--ou-overlap)&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open: &lt;code&gt;li + li&lt;/code&gt; uses &lt;code&gt;var(--ou-gap)&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Letter from &lt;code&gt;data-alph&lt;/code&gt; via &lt;code&gt;::before&lt;/code&gt;; &lt;code&gt;font-size: 0&lt;/code&gt; on the face keeps names in the DOM for assistive tech.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Optional &lt;code&gt;img&lt;/code&gt; covers the letter; letter remains fallback.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A–Z / 0–9 map to a palette through FSCSS arrays at compile time.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Custom selector:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-css&quot;&gt;@avatar-overlap(.members)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;ul class=&quot;members&quot; tabindex=&quot;0&quot;&amp;gt;
  &amp;lt;li data-alph=&quot;a&quot;&amp;gt;Ada&amp;lt;/li&amp;gt;
  &amp;lt;li data-alph=&quot;n&quot;&amp;gt;Nia&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;layer-3-card-cascade&quot;&gt;Layer 3 — card cascade&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Role:&lt;/strong&gt; notification piles, activity stacks, ticket previews without a drawer component.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;div class=&quot;card-overlap&quot; tabindex=&quot;0&quot;&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;img src=&quot;https://picsum.photos/96?random=1&quot; alt=&quot;&quot;&amp;gt;
    &amp;lt;h3&amp;gt;Invoice paid&amp;lt;/h3&amp;gt;
    Acme Corp · $2,400
  &amp;lt;/div&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;img src=&quot;https://picsum.photos/96?random=2&quot; alt=&quot;&quot;&amp;gt;
    &amp;lt;h3&amp;gt;Seat added&amp;lt;/h3&amp;gt;
    workspace update
  &amp;lt;/div&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;img src=&quot;https://picsum.photos/96?random=3&quot; alt=&quot;&quot;&amp;gt;
    &amp;lt;h3&amp;gt;Comment&amp;lt;/h3&amp;gt;
    “Ship the cascade”
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-css&quot;&gt;@card-overlap(.card-overlap)

:root {
  --ou-peek: 34px;
  --ou-card-h: 76px;
  --ou-card-gap: 10px;
  --ou-card-bg: #1f2a48;
  --ou-card-title: #fff;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Rest uses a negative top margin derived from peek and card height so only a band of each card shows. Open restores &lt;code&gt;var(--ou-card-gap)&lt;/code&gt; between siblings. Prefer animating margin/transform over toggling &lt;code&gt;display&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;layer-4-image-cascade&quot;&gt;Layer 4 — image cascade&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Role:&lt;/strong&gt; editorial strips, gallery teasers, “recent media.”&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;div class=&quot;img-overlap&quot; tabindex=&quot;0&quot;&amp;gt;
  &amp;lt;img src=&quot;https://picsum.photos/120?random=4&quot; alt=&quot;&quot;&amp;gt;
  &amp;lt;img src=&quot;https://picsum.photos/120?random=5&quot; alt=&quot;&quot;&amp;gt;
  &amp;lt;img src=&quot;https://picsum.photos/120?random=6&quot; alt=&quot;&quot;&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-css&quot;&gt;@img-overlap(.img-overlap)

:root {
  @ou-img-size(96px, -48px)
  --ou-img-tilt: -5deg;
  --ou-img-tilt-even: 4deg;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Rest: overlap plus alternating tilt. Open: &lt;code&gt;rotate(0)&lt;/code&gt; and gap between images.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;layer-5-circle-cascade&quot;&gt;Layer 5 — circle cascade&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Role:&lt;/strong&gt; settings hub, FAB-style actions, compact toolbars.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;div class=&quot;circle-overlap&quot; style=&quot;--n:5&quot; tabindex=&quot;0&quot;&amp;gt;
  &amp;lt;button type=&quot;button&quot; aria-label=&quot;Settings menu&quot;&amp;gt;+&amp;lt;/button&amp;gt;
  &amp;lt;a href=&quot;#profile&quot; aria-label=&quot;Profile&quot;&amp;gt;P&amp;lt;/a&amp;gt;
  &amp;lt;a href=&quot;#billing&quot; aria-label=&quot;Billing&quot;&amp;gt;B&amp;lt;/a&amp;gt;
  &amp;lt;a href=&quot;#team&quot; aria-label=&quot;Team&quot;&amp;gt;T&amp;lt;/a&amp;gt;
  &amp;lt;a href=&quot;#api&quot; aria-label=&quot;API keys&quot;&amp;gt;K&amp;lt;/a&amp;gt;
  &amp;lt;a href=&quot;#logout&quot; aria-label=&quot;Sign out&quot;&amp;gt;×&amp;lt;/a&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-css&quot;&gt;@circle-overlap(.circle-overlap)

:root {
  @ou-circle-size(48px, 80px)
  --ou-center-bg: #6366f1;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Rules of the pattern:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;First child&lt;/strong&gt; is the center control (background &lt;code&gt;--ou-center-bg&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;--n&lt;/code&gt; is the number of satellites (exclude the center).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Satellites sit under the center at rest (&lt;code&gt;opacity: 0&lt;/code&gt;, scaled down), then fan with angle &lt;code&gt;360deg / var(--n) * var(--i)&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Built-in &lt;code&gt;--i&lt;/code&gt; / &lt;code&gt;--c&lt;/code&gt; defaults apply per &lt;code&gt;:nth-child&lt;/code&gt;; override &lt;code&gt;--c&lt;/code&gt; when needed.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Topbar-friendly footprint:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-css&quot;&gt;.settings-wrap {
  position: relative;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.settings-orbit {
  --n: 5;
  --ou-item: 40px;
  --ou-r: 70px;
  margin: 0;
  width: var(--ou-item);
  height: var(--ou-item);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;div class=&quot;settings-wrap&quot;&amp;gt;
  &amp;lt;div class=&quot;settings-orbit circle-overlap&quot; style=&quot;--n:5&quot; tabindex=&quot;0&quot;&amp;gt;
    &amp;lt;button type=&quot;button&quot; aria-label=&quot;Settings&quot;&amp;gt;+&amp;lt;/button&amp;gt;
    &amp;lt;a href=&quot;#profile&quot; aria-label=&quot;Profile&quot;&amp;gt;P&amp;lt;/a&amp;gt;
    &amp;lt;a href=&quot;#billing&quot; aria-label=&quot;Billing&quot;&amp;gt;B&amp;lt;/a&amp;gt;
    &amp;lt;a href=&quot;#team&quot; aria-label=&quot;Team&quot;&amp;gt;T&amp;lt;/a&amp;gt;
    &amp;lt;a href=&quot;#api&quot; aria-label=&quot;API&quot;&amp;gt;K&amp;lt;/a&amp;gt;
    &amp;lt;a href=&quot;#out&quot; aria-label=&quot;Sign out&quot;&amp;gt;×&amp;lt;/a&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;minimal-full-page-all-four-patterns-&quot;&gt;Minimal full page (all four patterns)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&quot;en&quot;&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
  &amp;lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&amp;gt;
  &amp;lt;title&amp;gt;overlapui cascades&amp;lt;/title&amp;gt;
  &amp;lt;script src=&quot;https://cdn.jsdelivr.net/npm/fscss@1.2.5/runtime.min.js&quot; defer&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;style&amp;gt;
    @import((*) from overlapui)

    @ou-root()
    @avatar-overlap(.avatar-overlap)
    @card-overlap(.card-overlap)
    @img-overlap(.img-overlap)
    @circle-overlap(.circle-overlap)
    @ou-reduced-motion()

    :root {
      --ou-ring: #0f172a;
      --ou-center-bg: #6366f1;
      @ou-avatar-size(44px, -14px)
      @ou-circle-size(48px, 80px)
    }

    body {
      margin: 0;
      min-height: 100vh;
      display: grid;
      gap: 48px;
      place-content: center;
      padding: 32px 16px;
      background: #0b1220;
      font-family: system-ui, sans-serif;
      color: #e2e8f0;
    }
  &amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;ul class=&quot;avatar-overlap&quot; tabindex=&quot;0&quot;&amp;gt;
    &amp;lt;li data-alph=&quot;g&quot;&amp;gt;G&amp;lt;/li&amp;gt;
    &amp;lt;li data-alph=&quot;h&quot;&amp;gt;H&amp;lt;/li&amp;gt;
    &amp;lt;li data-alph=&quot;i&quot;&amp;gt;I&amp;lt;/li&amp;gt;
    &amp;lt;li data-alph=&quot;j&quot;&amp;gt;J&amp;lt;/li&amp;gt;
  &amp;lt;/ul&amp;gt;

  &amp;lt;div class=&quot;card-overlap&quot; tabindex=&quot;0&quot;&amp;gt;
    &amp;lt;div&amp;gt;
      &amp;lt;img src=&quot;https://picsum.photos/96?random=1&quot; alt=&quot;&quot;&amp;gt;
      &amp;lt;h3&amp;gt;Title&amp;lt;/h3&amp;gt;
      subtitle
    &amp;lt;/div&amp;gt;
    &amp;lt;div&amp;gt;
      &amp;lt;img src=&quot;https://picsum.photos/96?random=2&quot; alt=&quot;&quot;&amp;gt;
      &amp;lt;h3&amp;gt;Title&amp;lt;/h3&amp;gt;
      subtitle
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;

  &amp;lt;div class=&quot;img-overlap&quot; tabindex=&quot;0&quot;&amp;gt;
    &amp;lt;img src=&quot;https://picsum.photos/96?random=4&quot; alt=&quot;&quot;&amp;gt;
    &amp;lt;img src=&quot;https://picsum.photos/96?random=5&quot; alt=&quot;&quot;&amp;gt;
    &amp;lt;img src=&quot;https://picsum.photos/96?random=6&quot; alt=&quot;&quot;&amp;gt;
  &amp;lt;/div&amp;gt;

  &amp;lt;div class=&quot;circle-overlap&quot; style=&quot;--n:4&quot; tabindex=&quot;0&quot;&amp;gt;
    &amp;lt;button type=&quot;button&quot; aria-label=&quot;Menu&quot;&amp;gt;+&amp;lt;/button&amp;gt;
    &amp;lt;a href=&quot;#a&quot; aria-label=&quot;A&quot;&amp;gt;A&amp;lt;/a&amp;gt;
    &amp;lt;a href=&quot;#b&quot; aria-label=&quot;B&quot;&amp;gt;B&amp;lt;/a&amp;gt;
    &amp;lt;a href=&quot;#c&quot; aria-label=&quot;C&quot;&amp;gt;C&amp;lt;/a&amp;gt;
    &amp;lt;a href=&quot;#d&quot; aria-label=&quot;D&quot;&amp;gt;D&amp;lt;/a&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;responsive-behavior-tokens-not-new-markup-&quot;&gt;Responsive behavior (tokens, not new markup)&lt;/h3&gt;
&lt;p&gt;Scale density at breakpoints:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-css&quot;&gt;@media (max-width: 520px) {
  :root {
    @ou-avatar-size(36px, -11px)
    @ou-img-size(72px, -36px)
    @ou-circle-size(40px, 64px)
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Keep horizontal stacks from breaking the page:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-css&quot;&gt;body { overflow-x: hidden; }

.center-block {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  max-width: 100%;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;accessibility-part-of-the-contract-&quot;&gt;Accessibility (part of the contract)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Keep &lt;strong&gt;real labels or names&lt;/strong&gt; in the DOM for avatars; faces may hide the decorative letter with &lt;code&gt;font-size: 0&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Put &lt;code&gt;aria-label&lt;/code&gt; on the circle center and on each satellite control.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add &lt;code&gt;tabindex=&quot;0&quot;&lt;/code&gt; on stack roots so &lt;code&gt;:focus-within&lt;/code&gt; matches hover.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Call &lt;code&gt;@ou-reduced-motion()&lt;/code&gt; so transitions drop out when the user prefers reduced motion.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;how-the-pieces-fit-checklist-&quot;&gt;How the pieces fit (checklist)&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Choose a cascade: avatar, card, image, or circle.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set density with &lt;code&gt;--ou-*&lt;/code&gt; / size helpers.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mark the stack root for keyboard open when needed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Theme only through tokens.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Compile with FSCSS or use the runtime; the browser runs CSS.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Overlapped UI is a &lt;strong&gt;rest/open contract&lt;/strong&gt; plus a &lt;strong&gt;token layer&lt;/strong&gt;. overlapui is that contract as an FSCSS module.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;reference&quot;&gt;Reference&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/fscss-ttr/overlapui.fscss&quot;&gt;overlapui.fscss&lt;/a&gt; — module source, mixins, and tokens&lt;/li&gt;
&lt;/ul&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/29968/designing-overlapped-cascaded-ui-with-overlapui</guid>
<pubDate>Tue, 06 Oct 2026 09:44:22 +0000</pubDate>
</item>
<item>
<title>Guys I need your feedback for logo</title>
<link>https://coderlegion.com/29045/guys-i-need-your-feedback-for-logo</link>
<description>&lt;p&gt;Hey guys ;)&lt;br&gt;
This post is a bit unusual, but I really need your help and opinion. So right now I’m working on a new logo for Aster. And I really need to know is it good? And if it isn’t, then what’s wrong with it? I'll be glad to hear from all of you, thanks.&lt;br&gt;
Here it is&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo28il51h0e1q7xh0p1eh.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;More about idea of logo and other I'll tell in next post. So, yep bye bye and thanks for all of you.&lt;br&gt;
Oops, here is second version of logo. So, which is better?&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=12372411446401770292&quot; alt=&quot;Version 2&quot;&gt;&lt;/p&gt;
</description>
<category>Discussions</category>
<guid isPermaLink="true">https://coderlegion.com/29045/guys-i-need-your-feedback-for-logo</guid>
<pubDate>Tue, 29 Sep 2026 11:45:22 +0000</pubDate>
</item>
<item>
<title>Smart multifacet filters in JS using Bitmaps</title>
<link>https://coderlegion.com/20151/smart-multifacet-filters-in-js-using-bitmaps</link>
<description>&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Modern frontend applications are starting to look less like simple view layers and more like small databases running directly in the browser.&lt;/p&gt;
&lt;p&gt;Think about an e-commerce catalog, an analytics dashboard, or an admin panel. In all of these cases, the UI isn’t just rendering data—it’s constantly slicing it, recombining it, and reacting to user input in real time. Filtering becomes one of the most common operations, and the most natural way to express it in JavaScript is still the familiar chain of &lt;code&gt;Array.filter()&lt;/code&gt; calls:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const filtered = products  
 .filter(p =&amp;gt; p.category === selectedCategory)  
 .filter(p =&amp;gt; p.inStock)  
 .filter(p =&amp;gt; p.price &amp;lt; maxPrice);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It reads well and does exactly what you expect: take a list, narrow it down step by step. For small datasets, there’s nothing wrong with this approach. The problem starts when the data grows or when filtering becomes part of a tight interaction loop—every checkbox toggle, every slider movement, every keystroke.&lt;/p&gt;
&lt;p&gt;The point is that filters are rarely applied once: they are run over and over again, often across tens or hundreds of thousands of items, and each step in that chain quietly walks the entire array again.&lt;/p&gt;
&lt;p&gt;This is not a new problem on the backend: databases ran into it decades ago and solved it with a different mental model by replacing scanning records with precomputed indexes, turning the filtering into fast set operations. One of the most effective techniques they use is bitmap indexing, where filters become simple bitwise combinations rather than repeated object traversal.&lt;/p&gt;
&lt;p&gt;In this article, we’ll bring that idea into JavaScript and see what happens when you treat your frontend data layer a bit more like a database engine. You can find the fully working code on the &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/rosdec/bitmap_filters&quot;&gt;GitHub repository&lt;/a&gt;. The interactive example on the repository contains a time comparison of traditional array filtering and the techniques described here.&lt;/p&gt;
&lt;h3 id=&quot;the-core-idea-behind-bitmap-indexes&quot;&gt;The core idea behind bitmap indexes&lt;/h3&gt;
&lt;p&gt;Bitmap indexes work by precomputing binary representations for attributes.&lt;/p&gt;
&lt;p&gt;Imagine this dataset:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th align=&quot;center&quot;&gt;Product &lt;/th&gt;&lt;th align=&quot;center&quot;&gt;Red &lt;/th&gt;&lt;th align=&quot;center&quot;&gt;Blue &lt;/th&gt;&lt;th align=&quot;center&quot;&gt;Size M &lt;/th&gt;&lt;th align=&quot;center&quot;&gt;In Stock &lt;/th&gt;&lt;th align=&quot;center&quot;&gt;Description&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;P1 &lt;/td&gt;&lt;td align=&quot;center&quot;&gt;1 &lt;/td&gt;&lt;td align=&quot;center&quot;&gt;0 &lt;/td&gt;&lt;td align=&quot;center&quot;&gt;1 &lt;/td&gt;&lt;td align=&quot;center&quot;&gt;1 &lt;/td&gt;&lt;td align=&quot;center&quot;&gt;P1 is Red, Size M and in stock&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;P2 &lt;/td&gt;&lt;td align=&quot;center&quot;&gt;0 &lt;/td&gt;&lt;td align=&quot;center&quot;&gt;1 &lt;/td&gt;&lt;td align=&quot;center&quot;&gt;1 &lt;/td&gt;&lt;td align=&quot;center&quot;&gt;0 &lt;/td&gt;&lt;td align=&quot;center&quot;&gt;P2 is Blue, Size M and is not in stock&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;P3 &lt;/td&gt;&lt;td align=&quot;center&quot;&gt;1 &lt;/td&gt;&lt;td align=&quot;center&quot;&gt;0 &lt;/td&gt;&lt;td align=&quot;center&quot;&gt;0 &lt;/td&gt;&lt;td align=&quot;center&quot;&gt;1 &lt;/td&gt;&lt;td align=&quot;center&quot;&gt;P3 is Red, and is in stock&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;P4 &lt;/td&gt;&lt;td align=&quot;center&quot;&gt;1 &lt;/td&gt;&lt;td align=&quot;center&quot;&gt;0 &lt;/td&gt;&lt;td align=&quot;center&quot;&gt;1 &lt;/td&gt;&lt;td align=&quot;center&quot;&gt;0 &lt;/td&gt;&lt;td align=&quot;center&quot;&gt;P4 is Red, Size M and is not in stock&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Each attribute becomes a bitmap:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;red      = 1000  
blue     = 0100  
sizeM    = 0010  
inStock  = 0001
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Filtering becomes a bitwise operation:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;red AND sizeM AND inStock

1000  
0010  
0001  
----  
1011
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Only the first product matches all filters.&lt;/p&gt;
&lt;p&gt;Instead of repeatedly scanning arrays, we combine compact binary structures using highly optimized CPU operations.&lt;/p&gt;
&lt;p&gt;This is one of the reasons bitmap indexes are widely used in analytical databases and search engines.&lt;/p&gt;
&lt;h2 id=&quot;example-of-use&quot;&gt;Example of use&lt;/h2&gt;
&lt;h3 id=&quot;generating-a-realistic-dataset&quot;&gt;Generating a realistic dataset&lt;/h3&gt;
&lt;p&gt;The demo starts by constructing a synthetic—but stable—product catalog. Instead of hardcoding data or relying on an API, the implementation uses a seeded pseudo-random generator to ensure reproducibility across page loads:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let _seed = 42;

function rng() {  
 _seed = (_seed * 9301 + 49297) % 233280;  
 return _seed / 233280;  
} 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This small detail matters more than it seems. Because the dataset is deterministic, performance comparisons between runs are consistent—something you don’t get with Math.random(). &lt;/p&gt;
&lt;p&gt;The dataset itself is built via &lt;code&gt;Array.from&lt;/code&gt;, producing &lt;code&gt;10,000&lt;/code&gt; products (you can vary this by modifying the &lt;code&gt;PRODUCT_COUNT&lt;/code&gt; constant) with attributes like color, size, inStock, and price:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const products = Array.from({ length: PRODUCT\_COUNT }, (\_, i) \=\&amp;gt; ({  
 id:      i,  
 name:    `${pick(ADJS)} ${pick(NOUNS)}`,  
 color:   pick(COLORS),  
 size:    pick(SIZES),  
 inStock: rng() &amp;gt; 0.38,  
 price:   Math.floor(rng() * 90) + 9,  
}));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each product is intentionally simple and categorical. That’s not a limitation—it’s exactly what makes this dataset ideal for bitmap indexing. Faceted search systems (like e-commerce filters) are dominated by discrete attributes, and this structure mirrors that reality.&lt;/p&gt;
&lt;h3 id=&quot;from-array-filter-to-bitmap-filtering&quot;&gt;From &lt;code&gt;Array.filter&lt;/code&gt; to bitmap filtering&lt;/h3&gt;
&lt;p&gt;At a glance, the traditional approach uses chained &lt;code&gt;Array.filter&lt;/code&gt; calls:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let arr = products;  
if (colors.length &amp;gt; 0) arr = arr.filter(p =&amp;gt; colors.includes(p.color));  
if (sizes.length &amp;gt; 0) arr = arr.filter(p =&amp;gt; sizes.includes(p.size));  
if (inStockOnly) arr = arr.filter(p =&amp;gt; p.inStock); 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is intuitive and expressive: each filter step narrows down the dataset. But under the hood, it repeatedly scans the array—O(n) per filter—leading to cumulative cost as filters stack.&lt;/p&gt;
&lt;p&gt;The bitmap approach flips the perspective entirely. Instead of filtering objects, it filters indices using precomputed bitsets.&lt;/p&gt;
&lt;p&gt;First, we build indexes:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const idx = {  
 color: Object.fromEntries(COLORS.map(c =&amp;gt; [c, new FastBitSet()])),  
 size: Object.fromEntries(SIZES.map(s =&amp;gt; [s, new FastBitSet()])),  
 inStock: new FastBitSet(),  
};

products.forEach((p, i) =&amp;gt; {  
 idx.color[p.color].add(i);  
 idx.size[p.size].add(i);  
 if (p.inStock) idx.inStock.add(i);  
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each bitset represents a subset of product indices. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;idx.color.red&lt;/code&gt; → all indices of red products&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;idx.size.M&lt;/code&gt; → all medium-sized products&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;idx.inStock&lt;/code&gt; → all available products&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This transforms filtering into set algebra.&lt;/p&gt;
&lt;p&gt;The core logic starts from a “universe” of all indices and then refines it by applying intersection and union operations:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let result = universe.clone();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then applies constraints using bitwise operations. In the following code, we map the logical “or” operator by using the .union operation:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const colorSet = new FastBitSet();  
colors.forEach(c =&amp;gt; colorSet.union(idx.color[c]));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This corresponds to:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;color = red OR blue OR green
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the same way multiple selections within the same facet are merged via union, we map the logical “and” operator by using the .intersection operation:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;result.intersection(colorSet);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This corresponds to:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(color condition) AND (size condition) AND (stock condition)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each additional filter reduces the result set via intersection.&lt;/p&gt;
&lt;p&gt;Putting it together:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if (sizes.length \&amp;gt; 0\) {  
 const sizeSet = new FastBitSet();  
 sizes.forEach(s =&amp;gt; sizeSet.union(idx.size[s]));  
 result.intersection(sizeSet);  
}

if (inStockOnly) {  
 result.intersection(idx.inStock);  
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Conceptually, this translates the array pipeline:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;products  
 .filter(color condition)  
 .filter(size condition)  
 .filter(stock condition)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;into:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;universe  
 ∩ (color.red ∪ color.blue)  
 ∩ (size.M ∪ size.L)  
 ∩ inStock
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The key shift is that instead of iterating over objects repeatedly (this happens with the filter function on arrays), we manipulate compact bitmaps where each operation is vectorized and CPU-efficient.&lt;/p&gt;
&lt;p&gt;Finally, the matching indices are materialized:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const matchedIds = result.array();

and mapped back to actual product objects only at the end:

matchedIds.map(i =&amp;gt; products[i])
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This last operation maps the remaining &lt;code&gt;matchedIds&lt;/code&gt; to the products to update the UI, and that is another subtle but important optimization by pushing back this operation just on the final set of matched identifiers. &lt;/p&gt;
&lt;h2 id=&quot;production-considerations&quot;&gt;Production considerations&lt;/h2&gt;
&lt;p&gt;In production, bitmap-based filtering is typically implemented as an index-first strategy: instead of repeatedly scanning objects, you precompute compact index structures and combine them efficiently at query time. On the server, this pattern is often handled by specialized libraries or search engines—using structures like compressed bitmaps (e.g., &lt;a rel=&quot;nofollow&quot; href=&quot;https://roaringbitmap.org/&quot;&gt;RoaringBitmap&lt;/a&gt;) that allow fast unions and intersections at scale, even across millions of records. On the client, the same idea can be applied to moderate in-memory datasets to deliver instant, zero-latency filtering for common facets, while delegating heavier or high-cardinality queries back to the backend. The main tradeoffs to manage are index maintenance (keeping bitmaps in sync with data updates) and memory usage, but when filters are frequent and latency matters, this approach provides a significant and predictable performance advantage.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Bitmap indexes are a good example of how ideas traditionally associated with database engines are increasingly relevant in frontend engineering.&lt;/p&gt;
&lt;p&gt;Instead of repeatedly scanning arrays of objects, we can transform filtering operations into compact bitwise computations that scale much more efficiently as datasets grow.&lt;/p&gt;
&lt;p&gt;For small applications, standard filtering techniques are usually simpler and perfectly sufficient. But for large client-side datasets, analytics dashboards, faceted search interfaces, and local-first applications, bitmap indexes can dramatically improve responsiveness while keeping implementation complexity relatively manageable.&lt;/p&gt;
&lt;p&gt;Modern frontend applications increasingly resemble miniature data systems running directly in the browser. Techniques like bitmap indexing show that many optimizations once reserved for databases can now directly improve frontend user experiences as well.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/20151/smart-multifacet-filters-in-js-using-bitmaps</guid>
<pubDate>Wed, 10 Jun 2026 09:18:41 +0000</pubDate>
</item>
<item>
<title>⚡ Creating Custom Functions in FSCSS (Yes, CSS Can Do This)</title>
<link>https://coderlegion.com/13593/creating-custom-functions-in-fscss-yes-css-can-do-this</link>
<description>&lt;p&gt;One thing about FSCSS is that you can define your own functions… inside your styles. Here’s a simple example of how that works. &lt;/p&gt;
&lt;h3 id=&quot;custom-randint-function&quot;&gt;Custom randint Function&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-scss&quot;&gt;@define randint(array){
@random(@use(array)) 
} 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;What this function does:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Takes an array as an argument.&lt;/li&gt;
&lt;li&gt;Returns a random value directly from that array.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Defining Arrays&lt;br&gt;
First, we set up our possible values:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scss&quot;&gt;@arr sizes[ 100px, 150px, 200px ] 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Using the Function&lt;br&gt;
We call our custom function and assign it to a variable:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scss&quot;&gt;$height: @randint(@arr.sizes); 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now &lt;code&gt;$height&lt;/code&gt; dynamically becomes either &lt;code&gt;100px&lt;/code&gt;, &lt;code&gt;150px&lt;/code&gt;, or &lt;code&gt;200px&lt;/code&gt; (randomly selected at compile).&lt;/p&gt;
&lt;h3 id=&quot;why-this-is-interesting&quot;&gt;Why This Is Interesting&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Reusable Logic: You can create complex logic once and use it across your entire design system.&lt;/li&gt;
&lt;li&gt;Dynamic Design Systems: Build layouts that feel organic and varied rather than static and repetitive.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;example-usage&quot;&gt;Example Usage&lt;/h3&gt;
&lt;p&gt;Applying that logic to a class is straightforward:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scss&quot;&gt;.box { 
  height: $height; 
  width: $height; 
  background: #2c5364; 
} 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Every compile can produce a slightly different UI!&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.npmjs.com/package/fscss&quot;&gt;https://www.npmjs.com/package/fscss&lt;/a&gt; &lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/13593/creating-custom-functions-in-fscss-yes-css-can-do-this</guid>
<pubDate>Sat, 28 Mar 2026 11:33:44 +0000</pubDate>
</item>
<item>
<title>Agents Aren't Apps: Why Your UI Strategy Just Changed</title>
<link>https://coderlegion.com/9145/agents-arent-apps-why-your-ui-strategy-just-changed</link>
<description>&lt;p&gt;You've spent years building interfaces. Forms with validation. Dashboards with charts. Navigation menus that make sense. Responsive layouts that work on every device.&lt;/p&gt;
&lt;p&gt;That skillset is becoming less relevant.&lt;/p&gt;
&lt;p&gt;Not because the work wasn't good. But because the fundamental assumption behind it just changed.&lt;/p&gt;
&lt;p&gt;The assumption was this: humans navigate software by clicking through menus, filling out forms, and reading screens.&lt;/p&gt;
&lt;p&gt;That assumption is breaking down fast.&lt;/p&gt;
&lt;h3 id=&quot;the-interface-is-moving&quot;&gt;The Interface Is Moving&lt;/h3&gt;
&lt;p&gt;Traditional applications put a user interface between humans and business logic. You open the CRM. You navigate to the customer record. You click edit. You change a field. You save.&lt;/p&gt;
&lt;p&gt;Every action requires you to know where things are and how to get there.&lt;/p&gt;
&lt;p&gt;Agents eliminate most of that. You tell the agent what you want. It figures out where to find the information, what to change, and how to execute the task.&lt;/p&gt;
&lt;p&gt;The interface isn't a collection of screens anymore. It's a conversation.&lt;/p&gt;
&lt;p&gt;This changes what developers build.&lt;/p&gt;
&lt;h3 id=&quot;dynamic-interfaces-generated-at-runtime&quot;&gt;Dynamic Interfaces Generated at Runtime&lt;/h3&gt;
&lt;p&gt;Some agents still need visual interfaces. But these interfaces don't look like traditional applications.&lt;/p&gt;
&lt;p&gt;Instead of pre-built forms with fixed fields, agents generate interfaces on demand based on what's needed for the specific task.&lt;/p&gt;
&lt;p&gt;Need to approve a purchase order? The agent creates a form showing relevant vendor history, budget impact, and comparison to similar purchases. Different context, different form. Same agent.&lt;/p&gt;
&lt;p&gt;Traditional development means building every possible screen in advance. Agent-based development means building systems that can generate appropriate interfaces based on context.&lt;/p&gt;
&lt;p&gt;The shift is fundamental. You're not designing screens anymore. You're designing the logic that determines what interfaces should exist.&lt;/p&gt;
&lt;h3 id=&quot;headless-agents-no-ui-at-all&quot;&gt;Headless Agents: No UI at All&lt;/h3&gt;
&lt;p&gt;Some agents don't need interfaces. They just make decisions and take actions.&lt;/p&gt;
&lt;p&gt;A fraud detection agent monitors transactions, applies rules, and flags suspicious activity. No one interacts with it directly. No dashboard. No forms. Just decisions happening in the background.&lt;/p&gt;
&lt;p&gt;An inventory management agent tracks stock levels, predicts demand, and triggers reorders when thresholds are hit. It doesn't need a UI. It needs good decision logic and reliable integrations.&lt;/p&gt;
&lt;p&gt;This pattern is spreading. Agents handle routine decisions autonomously. Humans only get involved when something requires judgment that the agent can't provide.&lt;/p&gt;
&lt;p&gt;For developers, this means building systems where the primary user is another system, not a person.&lt;/p&gt;
&lt;h3 id=&quot;why-crm-and-erp-interfaces-are-becoming-obsolete&quot;&gt;Why CRM and ERP Interfaces Are Becoming Obsolete&lt;/h3&gt;
&lt;p&gt;Consider how people actually use CRM systems today. They don't enjoy navigating through Salesforce. They do it because that's where the customer data lives.&lt;/p&gt;
&lt;p&gt;Agents change this. Instead of opening Salesforce, finding the account, and reading through notes, you ask: &quot;What's the status of the Acme deal?&quot;&lt;/p&gt;
&lt;p&gt;The agent accesses Salesforce, finds the account, reads the notes, checks recent emails, reviews the opportunity stage, and tells you what you need to know.&lt;/p&gt;
&lt;p&gt;The Salesforce interface still exists. But you're not using it. The agent is.&lt;/p&gt;
&lt;p&gt;This pattern applies across enterprise applications. ERP systems. HR platforms. Project management tools. The interfaces were built for human navigation. But humans increasingly interact through agents instead.&lt;/p&gt;
&lt;p&gt;The underlying systems still matter. The data models matter. The business logic matters. But the interfaces? They're becoming legacy artifacts.&lt;/p&gt;
&lt;h3 id=&quot;what-this-means-for-frontend-developers&quot;&gt;What This Means for Frontend Developers&lt;/h3&gt;
&lt;p&gt;If you build user interfaces, this creates an uncomfortable question: what do you build now?&lt;/p&gt;
&lt;p&gt;The answer isn't that frontend development disappears. It's that it changes focus.&lt;/p&gt;
&lt;p&gt;Instead of building comprehensive interfaces that expose every feature, you build targeted interfaces for specific contexts where visual interaction adds value.&lt;/p&gt;
&lt;p&gt;Instead of designing navigation systems, you design conversation flows.&lt;/p&gt;
&lt;p&gt;Instead of optimizing for ease of finding features, you optimize for clarity when agents need human input.&lt;/p&gt;
&lt;p&gt;The skills that matter shift from information architecture and navigation design to conversation design and context-aware interface generation.&lt;/p&gt;
&lt;h3 id=&quot;building-for-agent-consumption&quot;&gt;Building for Agent Consumption&lt;/h3&gt;
&lt;p&gt;When agents become the primary consumers of your APIs and data, different things matter.&lt;/p&gt;
&lt;p&gt;Traditional APIs often assume a human will interpret the response. Documentation explains what fields mean. Error messages describe what went wrong. The API design prioritizes flexibility for different human use cases.&lt;/p&gt;
&lt;p&gt;Agent-first APIs need different characteristics. Clear, consistent structure. Predictable error handling. Good semantic descriptions that agents can parse. Support for bulk operations and batch processing.&lt;/p&gt;
&lt;p&gt;The difference shows up in details. A human-focused API might return a customer record with 50 fields. An agent-focused API returns the same data but includes metadata describing what each field represents, its valid values, and its business meaning.&lt;/p&gt;
&lt;p&gt;Agents can work with either. But they work better with APIs designed for programmatic consumption at scale.&lt;/p&gt;
&lt;h3 id=&quot;the-new-skill-designing-conversations&quot;&gt;The New Skill: Designing Conversations&lt;/h3&gt;
&lt;p&gt;The interface design skill that matters now is conversation design.&lt;/p&gt;
&lt;p&gt;How do you structure a conversation between a human and an agent to accomplish a goal? What information needs to be exchanged? When should the agent ask for clarification versus making assumptions? How do you handle ambiguity?&lt;/p&gt;
&lt;p&gt;These questions aren't new. But they're becoming central to interface design in ways they weren't before.&lt;/p&gt;
&lt;p&gt;A good form makes data entry clear and prevents errors. A good conversation does the same thing but through natural language exchange instead of structured fields.&lt;/p&gt;
&lt;p&gt;The underlying principles transfer. But the implementation is completely different.&lt;/p&gt;
&lt;h3 id=&quot;what-still-needs-traditional-interfaces&quot;&gt;What Still Needs Traditional Interfaces&lt;/h3&gt;
&lt;p&gt;Some things still work better with traditional interfaces. Data visualization. Complex spatial relationships. Reviewing large amounts of information quickly. Creative work that benefits from direct manipulation.&lt;/p&gt;
&lt;p&gt;Agents handle extraction, summarization, and decision-making well. They don't handle visual pattern recognition or creative layout well.&lt;/p&gt;
&lt;p&gt;The future probably isn't all-agent or all-traditional. It's knowing which interface makes sense for which task.&lt;/p&gt;
&lt;p&gt;But the default is shifting. Ten years ago, the default was &quot;build an interface for it.&quot; Now the default is becoming &quot;let the agent handle it, unless there's a specific reason humans need direct visual access.&quot;&lt;/p&gt;
&lt;h3 id=&quot;the-purchase-order-example&quot;&gt;The Purchase Order Example&lt;/h3&gt;
&lt;p&gt;Here's how this plays out in practice.&lt;/p&gt;
&lt;p&gt;Traditional system: You log into the procurement platform. Navigate to purchase orders. Click &quot;create new.&quot; Fill out vendor, items, quantities, delivery date, budget code. Click through approval workflow. Submit.&lt;/p&gt;
&lt;p&gt;Agent-based system: You tell the agent &quot;Order 50 laptops from Dell, standard spec, for the Q1 new hires.&quot; The agent finds the standard spec, gets Dell pricing, checks budget availability, generates the PO, routes it to the right approver, and confirms when it's done.&lt;/p&gt;
&lt;p&gt;No interface. No navigation. No form filling.&lt;/p&gt;
&lt;p&gt;The agent might generate a visual summary for the approver showing cost comparison and delivery timeline. But that's dynamic, context-specific, and temporary. Not a permanent interface someone had to build.&lt;/p&gt;
&lt;h3 id=&quot;the-transition-challenge&quot;&gt;The Transition Challenge&lt;/h3&gt;
&lt;p&gt;The difficult part isn't technical. It's organizational.&lt;/p&gt;
&lt;p&gt;Your company has invested years building comprehensive interfaces. Those interfaces represent thousands of hours of design, development, and refinement. They work. People know how to use them.&lt;/p&gt;
&lt;p&gt;Now agents are making those interfaces less necessary. But you can't just shut them down. People still use them. Some tasks still need them. And building the agent layer takes time.&lt;/p&gt;
&lt;p&gt;The transition period is messy. You're maintaining legacy interfaces while building agent capabilities. You're supporting both patterns simultaneously. And you're trying to figure out which features need interface rebuilds versus agent implementations.&lt;/p&gt;
&lt;p&gt;There's no clean answer. But the direction is clear.&lt;/p&gt;
&lt;h3 id=&quot;stop-building-forms&quot;&gt;Stop Building Forms&lt;/h3&gt;
&lt;p&gt;The provocative version of this argument: if you're still building forms, you're building the wrong thing.&lt;/p&gt;
&lt;p&gt;The nuanced version: forms made sense when humans needed to navigate complex data entry. But if an agent can gather the information through conversation and validation logic, the form is unnecessary overhead.&lt;/p&gt;
&lt;p&gt;Not every form disappears overnight. But the default assumption should shift from &quot;we need a form for this&quot; to &quot;can an agent handle this workflow?&quot;&lt;/p&gt;
&lt;p&gt;That shift changes what developers build and how they think about interface design.&lt;/p&gt;
&lt;h3 id=&quot;the-skills-that-transfer&quot;&gt;The Skills That Transfer&lt;/h3&gt;
&lt;p&gt;Good interface design was always about understanding user goals and removing friction. That principle doesn't change.&lt;/p&gt;
&lt;p&gt;What changes is the implementation. You're removing friction through conversation instead of navigation. You're designing for context-aware generation instead of comprehensive coverage. You're building for agent interpretation instead of human comprehension.&lt;/p&gt;
&lt;p&gt;The core skill, understanding what users need and making it easy to accomplish, transfers directly.&lt;/p&gt;
&lt;p&gt;The implementation techniques? Those need updating.&lt;/p&gt;
&lt;h3 id=&quot;what-developers-should-do-now&quot;&gt;What Developers Should Do Now&lt;/h3&gt;
&lt;p&gt;Start building for agent consumption. Even if your organization isn't deploying agents yet, your APIs and data structures should work well for programmatic access at scale.&lt;/p&gt;
&lt;p&gt;Learn conversation design. Understand how to structure natural language interactions that accomplish goals efficiently.&lt;/p&gt;
&lt;p&gt;Experiment with agent-based interfaces. Build a simple agent that handles a workflow your team currently does through forms. See where it works well and where it breaks down.&lt;/p&gt;
&lt;p&gt;Pay attention to which interfaces in your applications are becoming less used because people found agent-based alternatives. That tells you where the shift is happening.&lt;/p&gt;
&lt;p&gt;The interface revolution isn't coming. It's here. And it's changing what developers build, how they build it, and what skills matter.&lt;/p&gt;
&lt;p&gt;If you're still thinking in terms of screens and navigation, you're already behind.&lt;/p&gt;
</description>
<category>Data Science</category>
<guid isPermaLink="true">https://coderlegion.com/9145/agents-arent-apps-why-your-ui-strategy-just-changed</guid>
<pubDate>Wed, 31 Dec 2025 16:22:53 +0000</pubDate>
</item>
</channel>
</rss>