<h2 dir="auto">[SIP-37] Proposal to implement CSS-in-JS using Emotion <g-emoji class="g-emoji" alias="woman_singer" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f469-1f3a4.png">👩‍🎤</g-emoji></h2>
<h3 dir="auto">Motivation</h3>
<p dir="auto">Superset has been built with React components utilizing a few layers of styling. Most components are build using React-Bootstrap (v0.31), which is in turn built on Bootstrap 3. Bootstrap 3 is built using LESS, and is themed/overridden in Superset with Bootswatch and a Bootswatch theme called Cosmo, also built with LESS. At this point, efforts have been made to consolidate styling with LESS variables, and cleaning up use of LESS styles throughout the codebase, but some key problems remain:</p>
<ol dir="auto">
<li>Upgrading to newer versions of Bootstrap and/or React-Bootstrap are non-trivial, as they require migration to SASS from LESS.</li>
<li>Current Cosmo/Bootswatch themes, and indeed many of the custom styles elsewhere, will not be compatible with upgraded Bootstrap/React-Bootstrap</li>
<li><strong>Most importantly,</strong> the development experience in customizing and styling components is difficult.  Changing existing styles can have unexpected fallout in unintended views/components. It's also difficult to track down all the existing styles affecting any given component, which may be scattered in a number of different LESS files.</li>
</ol>
<p dir="auto">Migrating to CSS-in-JS accomplishes a few goals:</p>
<ul dir="auto">
<li>Organizes code's separation of concerns by component, rather than by language</li>
<li>Allows simpler and cleaner implementation of an <a href="https://atomicdesign.bradfrost.com/chapter-2/" rel="nofollow">atomic design system</a></li>
<li>Allows variants triggered by props (e.g. <code class="notranslate">&lt;Button primary&gt;</code> or <code class="notranslate">&lt;Card small&gt;</code>)</li>
<li>Simplifying, segmenting, or removing LESS usage over time, simplifying the codebase (particularly in deprecating Bootswatch/Cosmo)</li>
<li>More robust theming capabilities</li>
<li>Component library agnostic</li>
<li>Snapshot serializers for CSS testing</li>
<li>Typescript support</li>
<li>Provides an easier path to restyle React-Bootstrap, and/or upgrade it!</li>
</ul>
<h3 dir="auto">Proposed Change</h3>
<p dir="auto">In short, the plan is to implement components using <a href="https://emotion.sh/docs/introduction" rel="nofollow">Emotion</a>. This can be done immediately for new components with no fallout to the existing codebase, but can also be extended to wrap or rewrite existing components in the interest of modernizing old code and libraries.</p>
<p dir="auto">Further implementation details below.</p>
<h3 dir="auto">New or Changed Public Interfaces</h3>
<p dir="auto">N/A</p>
<h3 dir="auto">New dependencies</h3>
<p dir="auto"><a href="https://github.com/emotion-js/emotion">Emotion</a> and various submodules - MIT License<br>
<code class="notranslate">babel-plugin-emotion</code> - MIT License<br>
<code class="notranslate">emotion-ts-plugin</code> - MIT License<br>
<code class="notranslate">jest-emotion</code> - MIT License</p>
<h3 dir="auto">Migration Plan and Compatibility</h3>
<p dir="auto">The plan to move toward Emotion-styled components would take the following path:</p>
<ol dir="auto">
<li>Coping/migrating LESS variables (colors, font sizes, etc) to JS based <code class="notranslate">theme</code> file, and provide it to all components in the React component tree via Emotions <code class="notranslate">ThemeProvider</code> HOC. This will lead to duplication of these variables, but this is temporary.</li>
<li>Create all styles for NEW components using Emotion, either with their <a href="https://emotion.sh/docs/css-prop" rel="nofollow">CSS prop</a> using "object styles", the <a href="https://emotion.sh/docs/@emotion/styled" rel="nofollow">styled</a> pattern using "tagged template literals", or the <a href="https://emotion.sh/docs/emotion-theming#usetheme" rel="nofollow">useTheme</a> hook.</li>
</ol>
<p dir="auto">To extend this idea toward deprecating Bootswatch/Cosmo, and eventually upgrading React-Bootstrap, the following approach may be used:</p>
<ol dir="auto">
<li>Migrating <code class="notranslate">React-Bootstrap</code> based components into similarly named wrapper components, and applying custom styles and theme variables as needed to shape the atomic component toward the target design(s). Here's a sketch of how a wrapped React-Bootstrap button might look, with some arbitrary custom styles illustrating prop and theme usage.</li>
</ol>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="/** @jsx jsx */

import styled from '@emotion/styled';
import { withTheme } from 'emotion-theming';
import {
    Button as React_Bootstrap_Button,
    // @ts-ignore
  } from 'react-bootstrap';

const Button = styled(React_Bootstrap_Button)`

  font-family: ${(props) =&gt; props.theme.font-family};
  border-radius: ${(props) =&gt; props.theme.borderRadius};
  background-color: ${props =&gt; props.primary ? props.theme.colors.primary : props.theme.colors.secondary};

  a {
    padding: 0;
    opacity: 0.8;
    &amp;:active {
      opacity: 1;
      border: 2px solid ${(props) =&gt; props.theme.colors.secondary.light2};
    }
  }
`;

export default withTheme(Button);"><pre class="notranslate"><code class="notranslate">/** @jsx jsx */

import styled from '@emotion/styled';
import { withTheme } from 'emotion-theming';
import {
    Button as React_Bootstrap_Button,
    // @ts-ignore
  } from 'react-bootstrap';

const Button = styled(React_Bootstrap_Button)`

  font-family: ${(props) =&gt; props.theme.font-family};
  border-radius: ${(props) =&gt; props.theme.borderRadius};
  background-color: ${props =&gt; props.primary ? props.theme.colors.primary : props.theme.colors.secondary};

  a {
    padding: 0;
    opacity: 0.8;
    &amp;:active {
      opacity: 1;
      border: 2px solid ${(props) =&gt; props.theme.colors.secondary.light2};
    }
  }
`;

export default withTheme(Button);
</code></pre></div>
<ol start="2" dir="auto">
<li>Wherever possible, migrate LESS styles from Cosmo/Bootswatch/custom styles, and put it into atomic components.</li>
<li>When LESS code has been sufficiently migrated into Emotion components, delete Cosmo theme and Bootswatch files (hooray!)</li>
<li>When all React-Bootstrap imports/usages have migrated to Superset-owned Emotion-styled components, it should be possible to upgrade React-Bootstrap and make relatively minor/straightforward changes to correct any unexpected style changes.</li>
</ol>
<p dir="auto">In the event of an emergency involving support or implementation of Emotion, it should be fairly straightforward to migrate to <a href="https://styled-components.com/" rel="nofollow">Styled-Components</a> as an optional ejection path. They follow the same patterns.</p>
<h3 dir="auto">Rejected Alternatives</h3>
<ul dir="auto">
<li><strong>Styled Components</strong> - The leading package, and the leading competition to Emotion. Downsides are that it is larger, less performant (they're addressing this), and that it doesn't (yet) support sourcemaps. The scale of this community is the largest, so it may be warranted to swtich to this in the future, which at this point is relatively trivial.</li>
<li><strong>JSS</strong> - Popular, but that seems to be in large part due to its use in Material UI. It doesn't seem to provide selling points that outweigh the features, ease of use, and emerging patterns provided by Emotion (and Emotion-like) libraries</li>
<li><strong>Glamorous</strong> - Follows similar patterns to Emotion/Styled-Components. The founder has officially recommended that users switch to Emotion (over Styled-Components) and has provided a codemod to do so.</li>
<li><strong>Aphrodite, Radium, Styletron</strong> - These (and others) provide plenty of feature overlap in their CSS-in-JS approaches, but seem lacking in OSS adoption and community support.</li>
</ul>
<p dir="auto">I am not able to add different formula type annotation layer that the initial. That's because when I choose dropdown option in modal then modal disappears.</p>
<h3 dir="auto">Expected results</h3>
<p dir="auto">Should not disappear.</p>
<h3 dir="auto">Actual results</h3>
<p dir="auto">Disappears.</p>
<h4 dir="auto">Screenshots</h4>
<details open="" class="details-reset border rounded-2">
  <summary class="px-3 py-2">
    <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-device-camera-video">
    <path d="M16 3.75v8.5a.75.75 0 0 1-1.136.643L11 10.575v.675A1.75 1.75 0 0 1 9.25 13h-7.5A1.75 1.75 0 0 1 0 11.25v-6.5C0 3.784.784 3 1.75 3h7.5c.966 0 1.75.784 1.75 1.75v.675l3.864-2.318A.75.75 0 0 1 16 3.75Zm-6.5 1a.25.25 0 0 0-.25-.25h-7.5a.25.25 0 0 0-.25.25v6.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-6.5ZM11 8.825l3.5 2.1v-5.85l-3.5 2.1Z"></path>
</svg>
    <span aria-label="Video description disappear.mov" class="m-1">disappear.mov</span>
    <span class="dropdown-caret"></span>
  </summary>

  <video src="https://user-images.githubusercontent.com/25153919/104373762-251ef680-5521-11eb-8a3a-f6880aaec106.mov" data-canonical-src="https://user-images.githubusercontent.com/25153919/104373762-251ef680-5521-11eb-8a3a-f6880aaec106.mov" controls="controls" muted="muted" class="d-block rounded-bottom-2 border-top width-fit" style="max-height:640px; min-height: 200px">

  </video>
</details>

<h4 dir="auto">How to reproduce the bug</h4>
<p dir="auto">Go to charts<br>
open random_time_series<br>
add annotation layer<br>
change formula / annotation layer type</p>
<h3 dir="auto">Environment</h3>
<p dir="auto">docker<br>
SHA <a class="commit-link" data-hovercard-type="commit" data-hovercard-url="https://github.com/apache/superset/commit/5f93a14f5dd422e6f9ed468390b128776f278b03/hovercard" href="https://github.com/apache/superset/commit/5f93a14f5dd422e6f9ed468390b128776f278b03"><tt>5f93a14</tt></a></p>
<h3 dir="auto">Checklist</h3>
<p dir="auto">Make sure to follow these steps before submitting your issue - thank you!</p>
<ul dir="auto">
<li>[ x] I have checked the superset logs for python stacktraces and included it here as text if there are any.</li>
<li>[ x] I have reproduced the issue with at least the latest released version of superset.</li>
<li>[ x] I have checked the issue tracker for the same issue and I haven't found one similar.</li>
</ul>
<h3 dir="auto">Additional context</h3>