npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@glitz/react

v5.0.0-alpha.0

Published

[![npm (scoped)](https://img.shields.io/npm/v/@glitz/react.svg)](https://www.npmjs.com/package/@glitz/react) [![@glitz/react bundle size (minified + gzip)](https://img.shields.io/bundlephobia/minzip/@glitz/react.svg)](https://bundlephobia.com/result?p=@gl

Downloads

694

Readme

Glitz

npm (scoped) @glitz/react bundle size (minified + gzip)

Flexible and composable React bindings for Glitz.

import { styled } from '@glitz/react';

const Box = styled.div({
  fontSize: '18px',
});

function Message(props) {
  return (
    <Box css={{ color: props.important ? 'maroon' : 'teal' }}>
      Hi and <styled.Span css={{ fontWeight: 'bold' }}>welcome!</styled.Span>
    </Box>
  );
}

Table of content

Getting started

$ npm install @glitz/react
import React from 'react';
import { render } from 'react-dom';
import { GlitzClient } from '@glitz/core';
import { GlitzProvider } from '@glitz/react';
import transformers from '@glitz/transformers';
import App from './App';

const glitz = new GlitzClient({ transformer: transformers() });

render(
  <GlitzProvider glitz={glitz}>
    <App />
  </GlitzProvider>,
  document.getElementById('container'),
);

Style Decorators

Style Decorators are reusable, shareable and type-safe style containers which can be used instead of style objects in some cases. You create Style Decorators with the super object styled() by having a style object (or another Style Decorator) as first argument.

Style Decorators existence can be confusing at times. But they exist for a number of reasons:

  • They are immutable

  • They embraces the built-in deep style composition mechanism since spreading style objects can bring negative effects

  • They are type-safe, you don't need to import types or worry about type widening and other warnings you may miss

    import { styled } from '@glitz/react';
    
    // Bad
    export const headingStyle = {
      fontWeight: 'bold',
    };
    
    styled.div(headingStyle); // ❌ Type error due to literal type widening
    
    // Good
    export const headingDecorator = styled({
      fontWeight: 'bold',
    });
    
    styled.div(headingDecorator); // 👌 No errors

Caching

Class names are cached hard within the Glitz-component. This cache invalidates as new style or theme objects are passed into the Glitz-component.

// 👌 Fast due to intact cache
const Success = styled.div({ color: 'green' });

// 👌 Fast due to intact cache
const successDecorator = styled({ color: 'green' });
function Success() {
  <styled.Div css={successDecorator} />;
}

// ❗ Fast, but not as fast as the other two due to cache invalidation on each render
function Error() {
  <styled.Div css={{ color: 'red' }} />;
}

Deep style composition

Spreading style objects can bring negative effects:

import { styled } from '@glitz/react';

export const lightLinkStyle = {
  color: 'grey',
  ':hover': {
    color: 'black',
    textDecoration: 'underline',
  },
};

const darkLinkStyle = {
  ...lightLinkStyle,
  ':hover': {
    color: 'white',
  },
};

const Link styled.a(fontStyle); // ❌ The declaration `color: black` will be gone

To fix this, Glitz makes sure style objects are deeply composed which means that multiple style objects will be treated deeply. They are not deeply merged. Instead, Glitz will keep track of of applied rules and ignore those that are overridden. But @keyframes and @font-face objects wont be treated deeply in any way.

import { styled } from '@glitz/react';

export const lightLinkDecorator = styled({
  color: 'grey',
  ':hover': {
    color: 'black',
    textDecoration: 'underline',
  },
});

const darkLinkDecorator = styled(lightLinkDecorator, {
  ':hover': {
    color: 'white',
  },
});

styled.div(darkLinkDecorator); // 👌 Deeply composed as expected
  // Results in:
  // {
  //   color: 'grey',
  //   ':hover': {
  //     color: 'white',
  //     textDecoration: 'underline',
  //   }
  // }
});

TypeScript

You're able to type your theme using module augmentation.

import * as Glitz from '@glitz/core';

declare module '@glitz/core' {
  interface Theme {
    linkColor: string;
    backgroundColor: string;
  }
}

Theming

Provide a theme object that will accessed from style property values.

import { styled, ThemeProvider } from '@glitz/react';

function Text(props) {
  return <styled.Span css={{ color: theme => theme.textColor }}>{props.children}</styled.Span>;
}

function Example() {
  return (
    <ThemeProvider theme={{ textColor: 'green' }}>
      <Text>Some green text</Text>
      <ThemeProvider theme={{ textColor: 'blue' }}>
        <Text>Some blue text</Text>
      </ThemeProvider>
    </ThemeProvider>
  );
}

Server rendering

You're able to use the GlitzServer class when server rendering is used for your application. Here's an example with a regular renderToString().

import { renderToString } from 'react-dom/server';
import { GlitzServer } from '@glitz/core';
import { GlitzProvider } from '@glitz/react';
import options from './glitz-options';
import App from './App';

const glitz = new GlitzServer(options);

const bodyMarkup = renderToString(
  <GlitzProvider glitz={glitz}>
    <App />
  </GlitzProvider>,
  document.getElementById('container'),
);

const headMarkup = glitz.getStyle(true);

You're also able to render with Node Stream.

import { renderToNodeStream } from 'react-dom/server';
import { GlitzServer } from '@glitz/core';
import { GlitzProvider } from '@glitz/react';
import options from './glitz-options';
import App from './App';

const glitz = new GlitzServer(options);

app.use('*', (request, response) => {
  response.write('<html><head></head><body><div id="container">');

  const stream = renderToNodeStream(
    <GlitzProvider glitz={glitz} stream>
      <App />
    </GlitzProvider>,
  );

  stream.pipe(response, { end: 'false' });

  stream.on('end', () => {
    response.end('</div></body></html>');
  });
});

For more information, see the "server rendering" section for @glitz/core.

API

<GlitzProvider />

Provides all Glitz-component with the Glitz core instance.

<GlitzProvider
  /* Required, provides instance of `new GlitzClient` or `new GlitzServer` */
  glitz={GlitzClient | GlitzServer}
  /* Optional (default `false`), enables stream rendering of Glitz style */
  stream={boolean}
>

styled.[tagname](...style: Style | StyleDecorator)

Where [tagname] is lowercase e.g. div or span like styled.div(staticStyle: Style).

Returns a component:

<StyledComponent
  /* Any valid prop that `<[tagname] />` accepts */
  /* Optional, compose with so called dynamic styles */
  css={[style]}
  /* Optional, forwards a function to the inner element as `ref` */
  ref={[ref]}
/>

Tag name functions can be any valid React tag name (lower cased). It provides the possibility to have static style outside the component to not bloat your JSX-blocks.

Dynamic style are in the other hand inside using the css prop (see next example). In this way, the logical parts of the code becomes centralized to where you receive props and the typing remains manageable, if you use TypeScript.

import { styled } from '@glitz/react';

const Box = styled.div({
  fontSize: '18px',
});

function Example(props) {
  return <Box>Hi and welcome!</Box>;
}

<styled.[Tagname] />

Where [Tagname] is capitalized e.g. Div or Span like <styled.Div />.

Returns a component:

<styled.[Tagname]
  /* Any valid prop that `<[tagname] />` accepts */
  /* Optional, compose with e.g. dynamic styles */
  css={[style]}
  /* Optional, forwards a function to the inner element as `ref` */
  ref={[ref]}
/>

You can also use capitalized tag name (initial letter upper cased) which exposes a component directly. When you don't have or want to use static style.

import { styled } from '@glitz/react';

function Example(props) {
  return (
    <styled.Div
      css={{
        fontSize: props.xlarge ? '24px' : '18px',
      }}
    >
      Hi and welcome!
    </styled.Div>
  );
}

styled(component: ComponentType, ...style?: Style | StyleDecorator)

Returns a component:

<StyledComponent
  /* Any prop that `component` accepts */
  /* Optional, compose with e.g. dynamic styles */
  css={[style]}
  /* Optional, forwards a function to the inner element as `ref` */
  ref={[ref]}
/>

You can also use styled as a HOC. This enables you to compose external components locally without having to create wrapping elements. This can be useful with your shared components.

The inner component will receive one compose() prop as described below.

styled(...style: Style | StyleDecorator)

Returns a StyleDecorator.

import { styled } from '@glitz/react';

function List(props) {
  return <styled.Ul>{props.items.map((item = <li key={item.key}>{item.text}</li>))}</styled.Ul>;
}

const listDecorator = styled({
  fontSize: '18px',
  listStyle: 'square',
});

/* Will be styled as a list with squares, `18px` and `bold` */
const ImportantList = styled(List, listDecorator, {
  fontWeight: 'bold',
});

/* Will be styled as a list with squares and `24px` */
const LargeList = styled(List, listDecorator, {
  fontSize: '24px',
});

<ThemeProvider />

Provides a theme to the style object.

<ThemeProvider
  /* Required, provides theme object to styles */
  theme={Object}
>

Any theme can be used and replaced anywhere and you receive them by using a function for a property that returns a value.

import React from 'react';
import { styled, ThemeProvider } from '@glitz/react';

const theme1 = {
  linkColor: 'maroon',
};

const theme2 = {
  linkColor: 'teal',
};

const Link = styled.a({
  // This function will be called when rendered
  color: theme => theme.linkColor,
});

function Example() {
  return (
    <ThemeProvider theme={theme1}>
      <Link>Link is maroon</Link>
      <ThemeProvider theme={theme2}>
        <Link>Link is teal</Link>
      </ThemeProvider>
    </ThemeProvider>
  );
}

<StyleProvider />

Applies class names as string directly through className-prop instead of passing the compose()-prop. This works great with third-party components that accepts a className-prop for styling.

import React from 'react';
import { styled, applyClassName } from '@glitz/react';
import { Link } from 'react-router-dom';

const CustomLink = styled(applyClassName(Link), {
  color: 'green',
  ':hover': {
    color: 'darkgreen',
  },
});

applyClassName(component: ComponentType)

Applies class names as string directly through className-prop instead of passing the compose()-prop. This works great with third-party components that accepts a className-prop for styling.

import React from 'react';
import { styled, applyClassName } from '@glitz/react';
import { Link } from 'react-router-dom';

const CustomLink = styled(applyClassName(Link), {
  color: 'green',
  ':hover': {
    color: 'darkgreen',
  },
});

forwardStyle(component: ComponentType)

Styles automatically forwards to the nearest Glitz-component. But you can use this to forward it manually to a different Glitz-component using the compose()-prop.

import React from 'react';
import { styled, forwardStyle, ForwardStyleProps } from '@glitz/react';
import { Overlay } from './overlay';

const Modal = styled(
  forwardStyle((props: ForwardStyleProps) => (
    <Overlay>
      <styled.Div css={props.compose()}>{props.children}</styled.Div>
    </Overlay>
  )),
);

useStyle(style: Style | StyleDecorator)

React hook that returns class names for the given style.

useTheme()

React hook that returns the provided Glitz-theme.