1.0.2 • Published 4 years ago

react-ambient v1.0.2

Weekly downloads
2
License
ISC
Repository
github
Last release
4 years ago

react-ambient

Dead-simple solution for changing the background dynamically based on the most prominent content.

See the demo

Quick Start

1 Install

npm i --save react-ambient

2 Add provider

import { AmbientProvider } from 'react-ambient';

function AppLayout() {
  return (
    <AmbientProvider>
      <YourPageView />
    </AmbientProvider>
  );
}

3 Add sections

import { useAmbient } from 'react-ambient';

function Section({ backgroundContent, children }) {
  const [props, { renderBackground }] = useAmbient();

  return (
    <section {...props}>
      {renderBackground(backgroundContent)}
      {children}
    </section>
  );
}

function YourPageView() {
  return (
    <main>
      <Section backgroundContent={<FancyBackground />}>
        <p>Section content</p>
      </Section>
      <Section backgroundContent={<AdvertisingVideo />}>
        <p>Section content</p>
      </Section>
    </main>
  );
}

4 That's it!

You can find full typings for all exported tools in the docs. Or you can view another example in the Storybook.

Usage Tips

Getting started is easy, but there's a bit more to making a page with dynamic backgrounds than just changing the background.

Reacting to the active content globally

You probably want to change some aspects of the current visible content based on the active background. For example, if one of your backgrounds is dark and the other is light, you want content to be visible with good contrast against both while the user scrolls and transitions between them. How can that be done?

Good news, I thought of that! The trick is, each content component which you call useAmbient from can pass its own free-form user data. This data will be available to every content component when they render. Once you it clicks, you'll find it's quite easy to share global data to all content components based on which one is active:

// suppose we pass a 'color' prop to each section, indicating what its foreground color should be,
// and a 'background' prop, which tells what its background should be. as conscientious developers
// we have made sure there's a good contrast between these colors.
function Section({ color, background }) {
  // notice we're pulling out `activeData` from the return values
  const [props, { activeData, renderBackground }] = useAmbient({
    // let's pass our section's foreground color to `data` - now all sections
    // will know the foreground color of this section when it's the active one.
    data: { color },
  });

  return (
    // by pulling the color value from activeData, we are using the color
    // as specified by the currently active section, which presumably will
    // have the best contrast with the currently active background.
    <section {...props} style={{ color: activeData && activeData.color }}>
      {/* (just assume we have a ColorBackground component that renders a solid color here) */}
      {renderBackground(<ColorBackground background={background} />)}
      <p>Some content</p>
    </section>
  );
}

So in each <Section> we render (in this example), we're passing the foreground color to data - and when it renders, the activeData will have the appropriate foreground color, even if the rendered section isn't the one with the active background.

This feature can be used for more than just foreground color though. Put whatever data you want in there!

Changing the transition animation

This library ships with a pretty reasonable fade transition by default, but maybe you want something fancier - or nothing at all. That's easy to do, just pass a WrapperComponent to useAmbient:

import { Scale } from '@material-ui/core';

function Section() {
  const [props, { renderBackground }] = useAmbient({
    WrapperComponent: Scale,
    getWrapperProps: ({ active }) => ({ in: active }),
  });

  return (
    <section {...props}>
      {renderBackground(<BackgroundImage />)}
      Some content
    </section>
  );
}

In this example we're using the Scale transition component from material-ui. Neat!

If you don't want a transition at all, you can pass null.

Of course, if you've got your own component, it probably takes specific props to control the animation. That's where getWrapperProps comes in. Pass a function here which takes the current ambient state ({ active: boolean; activeData: D; activeKey: string; }, where D is the shape of whatever data you provide to useAmbient), and returns the props for your component.

1.0.2

4 years ago

1.0.1

4 years ago

1.0.0

4 years ago