<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Ghofrane Baaziz</title>
    <description>The latest articles on Forem by Ghofrane Baaziz (@ghofrane_baaziz_aea1d4056).</description>
    <link>https://forem.com/ghofrane_baaziz_aea1d4056</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3597051%2F7f2a7127-8972-4166-b034-78780ed99179.png</url>
      <title>Forem: Ghofrane Baaziz</title>
      <link>https://forem.com/ghofrane_baaziz_aea1d4056</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ghofrane_baaziz_aea1d4056"/>
    <language>en</language>
    <item>
      <title>I built a custom range slider for Retool with a histogram built in</title>
      <dc:creator>Ghofrane Baaziz</dc:creator>
      <pubDate>Mon, 24 Nov 2025 13:24:21 +0000</pubDate>
      <link>https://forem.com/ghofrane_baaziz_aea1d4056/i-built-a-custom-range-slider-for-retool-with-a-histogram-built-in-5491</link>
      <guid>https://forem.com/ghofrane_baaziz_aea1d4056/i-built-a-custom-range-slider-for-retool-with-a-histogram-built-in-5491</guid>
      <description>&lt;h2&gt;
  
  
  I built a custom range slider for Retool with a histogram built in
&lt;/h2&gt;

&lt;p&gt;Range sliders in Retool are great until you need to understand your data. They let you pick min and max values, but they don’t tell you anything about the distribution itself.&lt;/p&gt;

&lt;p&gt;I kept running into this when building internal tools, so I built a custom range slider that includes a histogram, handles uneven distributions and exposes clean values. It’s written in TypeScript and works as a native Retool component.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;GitHub repo:&lt;/strong&gt; &lt;a href="https://github.com/StackdropCO/custom-range-slider-retool-component" rel="noopener noreferrer"&gt;https://github.com/StackdropCO/custom-range-slider-retool-component&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;More Awesome Retool components here:&lt;/strong&gt; &lt;a href="https://github.com/StackdropCO/awesome-retool-components" rel="noopener noreferrer"&gt;https://github.com/StackdropCO/awesome-retool-components&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here’s why I built it and how to use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I built this
&lt;/h2&gt;

&lt;p&gt;A real example that pushed me to do this:&lt;/p&gt;

&lt;p&gt;I needed a filter for “years of experience” inside a Retool app. Most candidates had between 0 and 20 years, but a few outliers had 45 years. With the standard slider, you get min and max, but no clue whether the middle ranges are empty or dense.&lt;/p&gt;

&lt;p&gt;It forces you to guess, or worse, manually inspect the dataset.&lt;/p&gt;

&lt;p&gt;To show what I mean:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Retool’s default slider (no visibility):&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo3gg22k2ksgnkcyq5xoi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo3gg22k2ksgnkcyq5xoi.png" alt="Retool's default range slider without distribution visibility" width="688" height="152"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Custom Range Slider with distribution visible:&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi0jnvm8ckrfh1c64o5n1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi0jnvm8ckrfh1c64o5n1.png" alt="Custom range slider component with histogram showing data distribution overlay" width="634" height="294"&gt;&lt;/a&gt;&lt;br&gt;
The histogram makes it obvious where your data actually sits. In my case, the “20 to 45 years” range was basically empty. With a logarithmic scale, even large skewed values become readable.&lt;/p&gt;

&lt;p&gt;This small change makes filtering more honest and more useful.&lt;/p&gt;
&lt;h2&gt;
  
  
  What I focused on while building it
&lt;/h2&gt;

&lt;p&gt;Here are the engineering decisions that mattered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Histogram built in&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Shows distribution directly on the slider.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multiple scales&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Linear, logarithmic and square root for different distribution shapes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clean values&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Access the selected range through &lt;code&gt;selectedRange.start&lt;/code&gt; and &lt;code&gt;selectedRange.end&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flexible inputs&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Arrays, number lists, query outputs — anything numeric.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Click-to-select&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Click any histogram bar to jump to that range.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Custom colors&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Fully themeable inside Retool.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Negative values supported&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Useful for datasets that include offsets or deltas.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;Clone the repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/StackdropCO/custom-range-slider-retool-component.git

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Install dependencies
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;custom-range-slider
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Log in to Retool and initialize
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx retool-ccl login
npx retool-ccl init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Start development mode
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx retool-ccl dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Deploy the component
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx retool-ccl deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Using it in Retool
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Drag&lt;/strong&gt; the Range Slider component onto the canvas.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Define start and end values:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;start: 0&lt;/code&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;end: 50&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Custom formatting:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1 year&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; years`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bind distribution data:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;{{ query2.dataArray }}&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Access the selected range:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;customRangeSlider1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectedRange&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Switch scales if your data is skewed:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Linear (default)&lt;/li&gt;
&lt;li&gt;Logarithmic&lt;/li&gt;
&lt;li&gt;Square root&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Quick checklist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use a &lt;strong&gt;published version&lt;/strong&gt; for production&lt;/li&gt;
&lt;li&gt;Test locally with &lt;code&gt;npx retool-ccl dev&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Deploy and &lt;strong&gt;pin the version&lt;/strong&gt; in your Retool app&lt;/li&gt;
&lt;li&gt;For multi-instance setups, use &lt;code&gt;npx retool-ccl sync&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;A few improvements I'm exploring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auto-generated histograms from simple arrays&lt;/li&gt;
&lt;li&gt;More control over spacing and styling&lt;/li&gt;
&lt;li&gt;Optional statistics like mean and median&lt;/li&gt;
&lt;li&gt;Additional scale types&lt;/li&gt;
&lt;li&gt;General cleanup and refinements&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Get involved
&lt;/h2&gt;

&lt;p&gt;I built this to make filtering inside Retool more &lt;strong&gt;accurate&lt;/strong&gt;, especially with uneven distributions. It's fully &lt;strong&gt;open source&lt;/strong&gt;, and I'd love feedback, ideas or pull requests.&lt;/p&gt;

&lt;p&gt;If you try it, let me know how it works for you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy building!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;Interested in learning more about this component? Check out the &lt;a href="https://stackdrop.com/components/range-slider?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=component_library" rel="noopener noreferrer"&gt;full component library and documentation&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>opensource</category>
      <category>lowcode</category>
    </item>
  </channel>
</rss>
