<?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: chrisfrank</title>
    <description>The latest articles on Forem by chrisfrank (@chrisfrank).</description>
    <link>https://forem.com/chrisfrank</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%2F60470%2F3f87ce27-d41e-4229-824e-33713946008d.jpg</url>
      <title>Forem: chrisfrank</title>
      <link>https://forem.com/chrisfrank</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/chrisfrank"/>
    <language>en</language>
    <item>
      <title>Uninformed: nostalgically simple forms for React &amp; Preact</title>
      <dc:creator>chrisfrank</dc:creator>
      <pubDate>Mon, 10 Jun 2019 11:57:08 +0000</pubDate>
      <link>https://forem.com/chrisfrank/uninformed-nostalgically-simple-forms-for-react-preact-4mgb</link>
      <guid>https://forem.com/chrisfrank/uninformed-nostalgically-simple-forms-for-react-preact-4mgb</guid>
      <description>&lt;p&gt;Forms in Rails do two useful things automatically that I miss when I'm working in other frameworks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;They submit data without reloading the page.&lt;/li&gt;
&lt;li&gt;They disable themselves on submit, so that you can't accidentally submit data twice by double-clicking.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These are great defaults! In a web app in 2019, I should have to write code to &lt;em&gt;disable&lt;/em&gt; this behavior -- but I've found myself re-implementing it from scratch in several React projects.&lt;/p&gt;

&lt;p&gt;I wrote &lt;a href="https://github.com/chrisfrank/uninformed"&gt;Uninformed&lt;/a&gt; to bring these defaults to the React ecosystem. Here's how to use Uninformed in an app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Form&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uninformed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SignupForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Form&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/api/signups"&lt;/span&gt; &lt;span class="na"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handleSuccess&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Sign Up"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That’s it! No &lt;code&gt;onChange&lt;/code&gt; handlers, no &lt;code&gt;Input&lt;/code&gt; components, just a lightly-enhanced HTML form that disables itself on submit, sends data to a server via an &lt;code&gt;XMLHttpRequest&lt;/code&gt;, and re-enables itself after the server responds. When you need more power -- for setting request headers, running input validation, etc -- Uninformed lets you customize its behavior by passing functions as props. See the &lt;a href="https://github.com/chrisfrank/uninformed"&gt;README&lt;/a&gt; for more info.&lt;/p&gt;

&lt;p&gt;Uninformed is brand new, and I'd love to hear your ideas for how to improve it! Please feel free to file &lt;a href="https://github.com/chrisfrank/uninformed/issues"&gt;issues&lt;/a&gt;, &lt;a href="https://github.com/chrisfrank/uninformed/pulls"&gt;pull requests&lt;/a&gt;, or ask questions in the comments below.&lt;/p&gt;

&lt;p&gt;(Cover image by &lt;a href="https://unsplash.com/photos/tQQ4BwN_UFs"&gt;Kelly Sikkema&lt;/a&gt; via Unsplash)&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>rails</category>
    </item>
    <item>
      <title>Introducing nanostyled: CSS-in-JS without CSS-in-JS</title>
      <dc:creator>chrisfrank</dc:creator>
      <pubDate>Mon, 01 Oct 2018 20:01:29 +0000</pubDate>
      <link>https://forem.com/chrisfrank/introducing-nanostyled-2p6k</link>
      <guid>https://forem.com/chrisfrank/introducing-nanostyled-2p6k</guid>
      <description>

&lt;p&gt;Nanostyled is a tiny library (&amp;lt; 1 Kb unminified) for building styled React components. It tries to combine the flexible, component-based API of CSS-in-JS libraries with the extremely low overhead of plain CSS:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Low overhead&lt;/th&gt;
&lt;th&gt;Flexible, component-based API&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Plain CSS&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CSS-in-JS&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;nanostyled&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Like the CSS-in-JS libraries that inspired it -- 💕 to &lt;a href="https://www.styled-components.com"&gt;styled-components&lt;/a&gt; -- nanostyled lets you build UI elements with complex default styles, then tweak those styles throughout your app via props:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Button&amp;gt;&lt;/span&gt;A nice-looking button&lt;span class="nt"&gt;&amp;lt;/Button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;Button&lt;/span&gt; &lt;span class="na"&gt;color=&lt;/span&gt;&lt;span class="s"&gt;"blue"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;A nice-looking button that is blue.&lt;span class="nt"&gt;&amp;lt;/Button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Unlike&lt;/em&gt; a CSS-in-JS library, nanostyled doesn't use any CSS-in-JS. Instead, it's designed to accompany a &lt;strong&gt;functional CSS framework&lt;/strong&gt; like &lt;a href="http://tachyons.io/"&gt;Tachyons&lt;/a&gt; or &lt;a href="https://tailwindcss.com/"&gt;Tailwind&lt;/a&gt;. Nanostyled makes functional CSS less verbose, and easier to extract into props-controlled components.&lt;/p&gt;

&lt;p&gt;Check out &lt;a href="https://www.npmjs.com/package/nanostyled"&gt;nanostyled on npm&lt;/a&gt; for installation and usage instructions, or read on for more context.&lt;/p&gt;




&lt;h2&gt;
  
  
  Functional CSS?
&lt;/h2&gt;

&lt;p&gt;The basic premise of a functional CSS framework is that you can build complex styles by composing tiny CSS utility classes.&lt;/p&gt;

&lt;p&gt;A button styled with Tachyons might look like this in markup:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bg-blue white br2 pa2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Button&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That's a button with a blue background, white text, rounded corners (&lt;code&gt;br2&lt;/code&gt;), and some padding on all sides (&lt;code&gt;pa2&lt;/code&gt;).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;holy hell this is the worst thing I've ever seen&lt;br&gt;
-Adam Wathan, author of &lt;a href="https://tailwindcss.com/"&gt;Tailwind.css&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's true. Functional CSS is ugly, and defies decades-old best practices re: separating content from styling.&lt;/p&gt;

&lt;p&gt;On the other hand, styling with functional CSS scales well across large projects, enforces visual consistency, and makes it easy to build new UI elements without writing any new CSS. Adam Wathan, creator of, Tailwind, &lt;a href="https://adamwathan.me/css-utility-classes-and-separation-of-concerns/"&gt;defends the approach elegantly here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Nanostyled makes functional CSS easier to abstract into components, without giving up any of its strengths.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why building flexible components with functional CSS in React is hard
&lt;/h2&gt;

&lt;p&gt;To make working with functional CSS less verbose, you can extract long class strings into self-contained React components:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;className=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`bg-blue white br3 pa2 fw7 ${className}`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nt"&gt;rest&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The problem, in this case, is that there's no good way to render our &lt;code&gt;&amp;lt;Button&amp;gt;&lt;/code&gt; with a different background color. Even though it accepts a &lt;code&gt;className&lt;/code&gt; prop, writing &lt;code&gt;&amp;lt;Button className="bg-red" /&amp;gt;&lt;/code&gt; &lt;em&gt;won't necessarily render a red button.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Max Stoiber's recent &lt;a href="https://mobile.twitter.com/mxstbr/status/1038073603311448064"&gt;Twitter poll&lt;/a&gt; is a good illustration of why:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How well do you know CSS? Given these classes:&lt;br&gt;
&lt;code&gt;.red { color: red; }&lt;/code&gt;&lt;br&gt;
&lt;code&gt;.blue { color: blue; }&lt;/code&gt;&lt;br&gt;
Which color would these divs be?&lt;br&gt;
&lt;code&gt;&amp;lt;div class="red blue"&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;code&gt;&amp;lt;div class="blue red"&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The correct answer, which 57% of respondents got wrong, is that both divs would be blue.&lt;/p&gt;

&lt;p&gt;You can't know the answer by looking at just the HTML. You need to look at the CSS, because when two conflicting CSS classes have the same specificity, their order &lt;em&gt;in the markup&lt;/em&gt; is irrelevant. Which class wins depends on which one is defined last &lt;em&gt;in the stylesheet&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So to build a robust &lt;code&gt;&amp;lt;Button&amp;gt;&lt;/code&gt; with functional CSS, we need to be able to&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Declare some stock CSS classes that style it&lt;/li&gt;
&lt;li&gt;Expose a convenient API for &lt;em&gt;replacing&lt;/em&gt; some of the stock classes with alternatives&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This second requirement is key for avoiding counterintuitive class collisions like in Max's poll, and it's the thing nanostyled makes easy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building flexible components with nanostyled and style props
&lt;/h2&gt;

&lt;p&gt;Nanostyled works by mapping &lt;strong&gt;style props&lt;/strong&gt; onto class names from your functional CSS framework of choice. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Style props&lt;/strong&gt; can be named whatever you like, and can each hold any number of CSS classes:&lt;/p&gt;

&lt;h3&gt;
  
  
  A nanostyled Button
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;nanostyled&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'nanostyled'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// This example uses CSS classes from Tachyons&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s1"&gt;'tachyons/css/tachyons.css'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// A Button with three style props:&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nanostyled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'button'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'white'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'bg-blue'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'fw7 br3 pa2 sans-serif f4 bn input-reset'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Base Button&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;bg=&lt;/span&gt;&lt;span class="s2"&gt;"bg-yellow"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Yellow Button&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cm"&gt;/* rendering &amp;lt;App /&amp;gt; produces this markup:
&amp;lt;div&amp;gt;
  &amp;lt;button class="white bg-blue fw7 br3 pa2 sans-serif f4 bn input-reset"&amp;gt;Base Button&amp;lt;/button&amp;gt;
  &amp;lt;button class="white bg-yellow fw7 br3 pa2 sans-serif f4 bn input-reset"&amp;gt;Yellow Button&amp;lt;/button&amp;gt;
&amp;lt;/div&amp;gt;
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When a &lt;code&gt;nanostyled(element)&lt;/code&gt; renders, it consumes its style props and merges them into an HTML class string, as per above.&lt;/p&gt;

&lt;p&gt;It's totally to you which style props to use. The &lt;code&gt;&amp;lt;Button&amp;gt;&lt;/code&gt; above has an API that would make it easy to restyle color or background-color via the &lt;code&gt;color&lt;/code&gt; and &lt;code&gt;bg&lt;/code&gt; props, but hard to change other styles without totally rewriting the &lt;code&gt;base&lt;/code&gt; prop.&lt;/p&gt;

&lt;h3&gt;
  
  
  A more flexible nanostyled Button
&lt;/h3&gt;

&lt;p&gt;By using more style props, we can make a more flexible button:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;nanostyled&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'nanostyled'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s1"&gt;'tachyons/css/tachyons.css'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FlexibleButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nanostyled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'button'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'white'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// white text&lt;/span&gt;
  &lt;span class="na"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'bg-blue'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// blue background&lt;/span&gt;
  &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'fw7'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// bold font&lt;/span&gt;
  &lt;span class="na"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'br3'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// round corners&lt;/span&gt;
  &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'pa2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// some padding&lt;/span&gt;
  &lt;span class="na"&gt;typeface&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'sans-serif'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// sans-serif font&lt;/span&gt;
  &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'f4'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// font size #4 in the Tachyons font scale&lt;/span&gt;
  &lt;span class="na"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'bn input-reset'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// remove border and appearance artifacts&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Rendering a stock &lt;code&gt;&amp;lt;FlexibleButton /&amp;gt;&lt;/code&gt; will produce the same markup as its simpler relative. But it's much easier to render alternate styles:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FlexibleButton&lt;/span&gt;
  &lt;span class="nx"&gt;bg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"bg-light-green"&lt;/span&gt;
  &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"black"&lt;/span&gt;
  &lt;span class="nx"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"fw9"&lt;/span&gt;
  &lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"br4"&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;green&lt;/span&gt; &lt;span class="nx"&gt;background&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;black&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;heavier&lt;/span&gt; &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;rounder&lt;/span&gt; &lt;span class="nx"&gt;corners&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/FlexibleButton&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When you need a variation that you didn't plan for in your style props, you can still use the &lt;code&gt;className&lt;/code&gt; prop:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FlexibleButton&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"dim pointer"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;that&lt;/span&gt; &lt;span class="nx"&gt;dims&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="nx"&gt;hover&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;sets&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;cursor&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="s1"&gt;'pointer'&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/FlexibleButton&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Sharing style props across multiple components
&lt;/h2&gt;

&lt;p&gt;If you're building multi-component UI kits with nanostyled, I recommend sharing at least a few basic style props across all your components. Otherwise it gets hard to remember which components support, say, a &lt;code&gt;color&lt;/code&gt; prop, and which ones don't.&lt;/p&gt;

&lt;p&gt;I usually start here:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;"react"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;"react-dom"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;nanostyled&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;"nanostyled"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s2"&gt;"tachyons/css/tachyons.css"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// The keys in this styleProps will determine which style props&lt;/span&gt;
&lt;span class="c1"&gt;// our nanostyled elements will accept:&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;styleProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;font&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;css&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="cm"&gt;/* 
Why choose those keys, in particular? For everything except `css`, 
it's because the elements in the UI kit probably will have some default 
bg, color, margin, padding, or font we'll want to be able to easily override via props.

The `css` prop is an exception. I just like being able to use it instead of `className`.
*/&lt;/span&gt;

&lt;span class="c1"&gt;// Box will support all styleProps, but only use them when we explicitly pass values&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Box&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nanostyled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"div"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;styleProps&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="cm"&gt;/*
&amp;lt;Box&amp;gt;Hi!&amp;lt;/Box&amp;gt;
renders &amp;lt;div&amp;gt;Hi!&amp;lt;/div&amp;gt;

&amp;lt;Box color="red"&amp;gt;Hi!&amp;lt;/Box&amp;gt;
renders &amp;lt;div class="red"&amp;gt;Hi!&amp;lt;/div&amp;gt;
*/&lt;/span&gt;

&lt;span class="c1"&gt;// Button will also support all styleProps, and will use some of them by default&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nanostyled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"button"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;styleProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"bg-blue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"white"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pa2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;font&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"fw7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// I use a 'base' prop to declare essential component styles that I'm unlikely to override&lt;/span&gt;
  &lt;span class="na"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"input-reset br3 dim pointer bn"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="cm"&gt;/*
&amp;lt;Button&amp;gt;Hi!&amp;lt;/Button&amp;gt;
renders
&amp;lt;button class="bg-blue white pa2 dim pointer bn input-reset&amp;gt;Hi!&amp;lt;/button&amp;gt;
*/&lt;/span&gt;

&lt;span class="c1"&gt;// Heading uses styleProps, plus some extra props for fine-grained control over typography&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Heading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nanostyled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"h1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;styleProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"f1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"fw7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;tracking&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"tracked-tight"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;leading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"lh-title"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Putting them all together....&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Box&lt;/span&gt; &lt;span class="na"&gt;padding=&lt;/span&gt;&lt;span class="s2"&gt;"pa3"&lt;/span&gt; &lt;span class="na"&gt;font=&lt;/span&gt;&lt;span class="s2"&gt;"sans-serif"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Heading&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Styling with Nanostyled&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Heading&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Heading&lt;/span&gt; &lt;span class="na"&gt;tracking=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;tag=&lt;/span&gt;&lt;span class="s2"&gt;"h2"&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s2"&gt;"f3"&lt;/span&gt; &lt;span class="na"&gt;weight=&lt;/span&gt;&lt;span class="s2"&gt;"fw6"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      A brief overview
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Heading&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Heading&lt;/span&gt; &lt;span class="na"&gt;tag=&lt;/span&gt;&lt;span class="s2"&gt;"h3"&lt;/span&gt; &lt;span class="na"&gt;weight=&lt;/span&gt;&lt;span class="s2"&gt;"fw4"&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s2"&gt;"f5"&lt;/span&gt; &lt;span class="na"&gt;tracking=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;css=&lt;/span&gt;&lt;span class="s2"&gt;"bt pv3 b--light-gray"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Here are some buttons:
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Heading&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Base Button&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;css=&lt;/span&gt;&lt;span class="s2"&gt;"w-100 mv3"&lt;/span&gt; &lt;span class="na"&gt;padding=&lt;/span&gt;&lt;span class="s2"&gt;"pa3"&lt;/span&gt; &lt;span class="na"&gt;bg=&lt;/span&gt;&lt;span class="s2"&gt;"bg-green"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Wide Green Padded Button
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Box&lt;/span&gt; &lt;span class="na"&gt;css=&lt;/span&gt;&lt;span class="s2"&gt;"flex"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;css=&lt;/span&gt;&lt;span class="s2"&gt;"w-50"&lt;/span&gt; &lt;span class="na"&gt;margin=&lt;/span&gt;&lt;span class="s2"&gt;"mr2"&lt;/span&gt; &lt;span class="na"&gt;bg=&lt;/span&gt;&lt;span class="s2"&gt;"bg-gold"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        50% Wide, Gold
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;css=&lt;/span&gt;&lt;span class="s2"&gt;"w-50"&lt;/span&gt; &lt;span class="na"&gt;margin=&lt;/span&gt;&lt;span class="s2"&gt;"ml2"&lt;/span&gt; &lt;span class="na"&gt;bg=&lt;/span&gt;&lt;span class="s2"&gt;"bg-red"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        50% wide, Red
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rootElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"root"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt; &lt;span class="nx"&gt;rootElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This full example is &lt;a href="https://codesandbox.io/s/3r8l4rr8p1"&gt;available on CodeSandbox&lt;/a&gt; for you to experiment with.&lt;/p&gt;

&lt;p&gt;Nanostyled is available &lt;a href="https://www.npmjs.com/package/nanostyled"&gt;on npm&lt;/a&gt;, and you can contribute to the library on &lt;a href="https://www.github.com/chrisfrank/nanostyled"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;


</description>
      <category>react</category>
      <category>css</category>
      <category>cssinjs</category>
      <category>styledcomponents</category>
    </item>
    <item>
      <title>Dynamically filter data via URL params with Rack::Reducer</title>
      <dc:creator>chrisfrank</dc:creator>
      <pubDate>Thu, 29 Mar 2018 17:48:26 +0000</pubDate>
      <link>https://forem.com/chrisfrank/dynamically-filter-data-via-url-params-with-rackreducer-9p6</link>
      <guid>https://forem.com/chrisfrank/dynamically-filter-data-via-url-params-with-rackreducer-9p6</guid>
      <description>&lt;p&gt;Whether you're building a tiny API or a giant monolith, your app probably needs to render a list of database records somewhere. And you probably want those records to be filterable via URL params, like so:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GET /artists?genre=electronic&amp;amp;sort=name&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It'd be nice to sort or filter when the relevant params are present, and return a sensible default dataset otherwise.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /artists?name=blake` =&amp;gt; artists named 'blake'
GET /artists?genre=electronic&amp;amp;sort=name =&amp;gt; electronic artists, sorted by name
GET /artists =&amp;gt; all artists
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You &lt;em&gt;could&lt;/em&gt; conditionally apply filters with hand-written &lt;code&gt;if&lt;/code&gt; statements, but that approach gets uglier the more filters you add.&lt;/p&gt;

&lt;p&gt;In Rails, you could use Plataformatec's venerable &lt;a href="https://github.com/plataformatec/has_scope"&gt;HasScope&lt;/a&gt; gem.&lt;/p&gt;

&lt;p&gt;But what if you're working in Roda, Sinatra, or Hanami? Even in Rails, what if you'd rather write dedicated query objects than pollute your models and controllers with filtering code?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/chrisfrank/rack-reducer"&gt;Rack::Reducer&lt;/a&gt; can help. It's a gem that maps incoming URL params to an array of filter functions you define, applies only the applicable filters, and returns your filtered data. It can make your controller logic as minimal as...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="vi"&gt;@artists&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Artist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;...or, if magical, implicit code isn't your thing, you can call Rack::Reducer as a function to build more explicit queries -- maybe right in your controllers, maybe in dedicated &lt;a href="https://robots.thoughtbot.com/using-yieldself-for-composable-activerecord-relations"&gt;query objects&lt;/a&gt;, or really anywhere you like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/controllers/artists_controller.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArtistsController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;
    &lt;span class="vi"&gt;@artists&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Rack&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Reducer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;dataset: &lt;/span&gt;&lt;span class="no"&gt;Artist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;filters: &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="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'lower(name) like ?'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"%&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;downcase&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;%"&lt;/span&gt;&lt;span class="p"&gt;)&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="n"&gt;genre&lt;/span&gt;&lt;span class="p"&gt;:)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;genre: &lt;/span&gt;&lt;span class="n"&gt;genre&lt;/span&gt;&lt;span class="p"&gt;)&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="n"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;:)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_sym&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="vi"&gt;@artists&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rack::Reducer works in any Rack-compatible app, with any ORM, and has no dependencies beyond Rack itself. Full documentation is &lt;a href="https://github.com/chrisfrank/rack-reducer"&gt;on GitHub&lt;/a&gt;. Whether you work in Rails, &lt;a href="http://sinatrarb.com"&gt;Sinatra&lt;/a&gt;, &lt;a href="http://roda.jeremyevans.net"&gt;Roda&lt;/a&gt;, &lt;a href="http://hanamirb.org"&gt;Hanami&lt;/a&gt;, or raw Rack, I hope it can be of use to you.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>rack</category>
      <category>filtering</category>
    </item>
  </channel>
</rss>
