GithubHelp home page GithubHelp logo

happy-ferret / react-shade Goto Github PK

View Code? Open in Web Editor NEW

This project forked from treshugart/react-shade

0.0 2.0 0.0 559 KB

Use the native Web Component Shadow DOM API as React components in a super-duper-Reacty way (i.e. declaratively).

Home Page: https://react-shade.netlify.com/

License: MIT License

JavaScript 100.00%

react-shade's Introduction

react-shade

Use the native Web Component Shadow DOM API as React components in a super-duper-Reacty way (i.e. declaratively).

Check out the demo and code for it!

Install

npm install react-shade

Why

This library exposes the W3C standardised Web Component APIs for Shadow DOM as a set of React components. This side-steps a lot of work that needs to be done to work with the imperative APIs - as well as the proposed declarative APIs - and gives you a nice, clean and simple interface to encapsulate your DOM / styles in a perfectly declarative manner.

Usage

import React from 'react';
import { render } from 'react-dom';
import Root, { Slot, Style } from 'react-shade';

const App = () => (
  <Root>
    <Style>
      {{
        '.totes-not-global': {
          fontWeight: 'bold'
        }
      }}
    </Style>
    <span className="totes-not-global">This will be bold.</span>
    <Slot>
      <span className="totes-not-global">This will NOT be bold</span>
    </Slot>
  </Root>
);

render(<App />, window.root);

This will produce something like:

<!-- Requires a wrapping node because it needs to have a node to attach
the shadow root to. -->
<div>
  <!-- This is where the slot content ends up (as light DOM). -->
  <span slot="slot-0">This will NOT be bold</span>
  #shadow-root
    <!-- ReactDOM doesn't support calling createPortal() on a shadow root so
    we must create a wrapper node to portal into. Yes this is a valid name
    and it's been picked because it's likely to not conflict. Once React
    supports rendering to a shadow root this can be completely removed. -->
    <shadow--root>
      <style>.totes-not-global{font-weight:bold;}</style>
      <slot name="slot-0"></slot>
    </shadow--root>
</div>

There's some drawbacks as noted above in the HTML comments:

  1. Attaching a shadow root requires a real DOM node. We don't want to reach up in the hierarchy and mutate the DOM, so the Root component needs to generate a node to attach a shadow to. This defaults to a div, but can be whatever you want. This isn't something that will ever be able to change due to the nature of the DOM and React.
  2. ReactDOM doesn't support calling createPortal() on a shadow root (or document fragment, which is what a shadow root appears to be under certain conditions). Therefore, we have to create a wrapper for the shadow root that we can use as the portal node. Once React supports rendering to a shadow root, this can be simplified.

Creating styled components

There is a styled export that is a shortcut for creating primitive components that have a default styling.

import React from 'react';
import { styled } from 'react-shade';

const Div = styled({
  ':host': {
    fontSize: '1.2em',
    padding: 10
  }
});

Differences to native Shadow DOM

A keen eye might spot some of these and notice that it's not how you'd normally do Shadow DOM with imperative JavaScript or HTML. I assure you, that is only superficial. All aspects of react-shade's API fully utilises the native APIs.

Custom slot component

This was chosen because it's a more idiomatic way of declaring content where custom elements aren't being used. Underneath the hood, the Slot will portal the content back to the host so it gets distributed using the built-in algorithms.

<Slot>
  <span className="totes-not-global">This will NOT be bold</span>
</Slot>

Custom style component

This may appear to be syntactic sugar for using objects to represent your style strings, but there's a bit more to it.

<Style>
  {{
    selector: {
      style: 'property'
    }
  }}
</Style>

For example, this can be minified without adding anything extra to your build pipeline. You can also specify functions that react to props that are passed to Style. Both the set of rules and each property can be specified as a function. Whatever props that are passed to Style will be passed through.

const rulesAsFunction = ({ font }) => ({
  body: {
    fontFamily: valueAsFunction
  }
});
const valueAsFunction = ({ font }) => font;

<Style font={'Helvetica'}>
  {rulesAsFunction}
</Style>

You may also specify an Array for a value and it will be mapped into a string using the standard rules listed above.

<Style prop={'property'}>
  {{
    body: {
      margin: [10, 0]
    }
  }}
</Style>

NOTE: All numeric values will get converted to px units.

CSS custom properties (variables)

Props are useful for passing in data from your application state. However, it's recommended you simply use CSS variables where you don't need to do that.

<Style>
  {{
    ':root': {
      '--grid-size': 5
    },
    body: {
      margin: ['calc(var(--grid-size) * 2)', 0]
    }
  }}
</Style>

react-shade's People

Contributors

treshugart avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.