JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 465
  • Score
    100M100P100Q99662F
  • License CC BY-SA 4.0

Spend less time crafting your Compound Components structure

Package Exports

  • react-compound-composer
  • react-compound-composer/dist/react-compound-composer.js
  • react-compound-composer/dist/react-compound-composer.module.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (react-compound-composer) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

Logo

Spend less time crafting your Compound Components structure



Description

This library aims to make it easier to develop and maintain Compound Components by encapsulating context creation and compound composition logic under two core helpers.

Check those amazing posts to learn more about Compound Components:

Examples/Demo

  1. Simple Counter Example: An almost in-line example of a Counter with its own state. Here just for a very quick proof-of-concept.
  2. A Better Structured Example: An example of an Accordion compound
  3. Nested Compounds Example: An example of nested compound
  4. Flattened Root Example: An example of how you can flatten Root components

How to Use?

1. Create your Context

Start off by creating your context. This context will be available via a hook on all the sub-components. A good way to keep a dispatch-editable state across the components.

import { contextBuilder } from "react-compound-composer";

const {
  Consumer: CounterConsumer, // Consumer is also returned, just for convenience
  Provider: CounterProvider,
  useContext: useCounterContext,
} = contextBuilder(() => {
  const [count, setCount] = useState(0);

  return {
    count,
    increase: (count: number) => setCount((c) => c + count),
    decrease: (count: number) => setCount((c) => c - count),
  };
});

2. Create your Root & Sub Components

Create a few components to be composed under the compound.

import React from "react";

const CounterRoot = (props: React.PropsWithChildren) => {
  return (
    <div
      style={{
        display: "flex",
        flexDirection: "column",
        gap: 10,
        alignItems: "center",
      }}
    >
      {props.children}
    </div>
  );
};
import React from "react";

const CounterCount = () => {
  const ctx = useCounterContext();
  return <span>{ctx.count}</span>;
};
import React from "react";

const CounterIncrease = () => {
  const ctx = useCounterContext();
  return <button onClick={() => ctx.increase(1)}>Increase</button>;
};
import React from "react";

const CounterDecrease = () => {
  const ctx = useCounterContext();
  return <button onClick={() => ctx.decrease(1)}>Decrease</button>;
};

3. Compose your Compound with them!

Finally compose your Compound with the components you've created.

import { compoundBuilder } from "react-compound-composer";

export const Counter = compoundBuilder({
  name: "Counter",
  provider: CounterProvider,
  components: {
    Root: CounterRoot,
    Count: CounterCount,
    Increase: CounterIncrease,
    Decrease: CounterDecrease,
  },
});

4. Enjoy your Compound!

Use your compound as desired.

export default function App() {
  return (
    <main>
      <Counter.Root>
        <Counter.Increase />
        <Counter.Count />
        <Counter.Decrease />
      </Counter.Root>
    </main>
  );
}

How to Flatten Root Components?

If you prefer using the root components without actually using their Root properties, you can set the flattenRoot option to true. Like so:

import { compoundBuilder } from "react-compound-composer";

export const Counter = compoundBuilder({
  name: "Counter",
  provider: CounterProvider,
  flattenRoot: true,
  components: {
    Root: CounterRoot,
    Count: CounterCount,
    Increase: CounterIncrease,
    Decrease: CounterDecrease,
  },
});

and use the Compound like so:

export default function App() {
  return (
    <main>
      <Counter>
        <Counter.Increase />
        <Counter.Count />
        <Counter.Decrease />
      </Counter>
    </main>
  );
}

License

© 2023 Taha Anılcan Metinyurt (iGoodie)

For any part of this work for which the license is applicable, this work is licensed under the Attribution-ShareAlike 4.0 International license. (See LICENSE).

Creative Commons License