Building Plume Components with Plume Hooks
Plume provides a set of React hooks that you can use to bring your designs to life. Plume supports hooks for building Buttons, Checkboxes, Select dropdowns, TextFields, Sliders, and more!
What does a Plume component look like?
Using a Plume component feels just like using any other component library — each Plume component comes with a set of well-defined props, with full typescript support. The main difference is that you can design exactly how the component looks and feels using Plasmic, and can easily create additional components variants that suit your need.
What does “Plume-compatible” mean?
Your Plasmic design for a Plume component may need to have:
- Variants corresponding to different states of the component. For example, for a Checkbox component, you may need a variant that indicates the “checked” state of the Checkbox; for a Select component, you may need a variant that renders the “opened” state of the component.
- Slots corresponding to contents passed in by props or generated by Plume. For example, for a Button component, you may need a slot for the content of the Button, and a slot for the start icon of the Button.
- Named elements corresponding to different anatomical parts of the component. For example, for a Select dropdown component, you will need elements that correspond to the root, the trigger button, and the dropdown overlay. Plume needs to know about these elements to attach the appropriate event handlers, and provide the proper ARIA attributes for accessibility.
Using the Plume hooks
For each Plume component, there is a corresponding hook. The general shape of these hooks take these arguments:
plasmicClass
ー the generatedPlasmic*
classprops
ー the component props, which is a subset of thePlume*Props
. The Plume hook will automatically apply all variants and args that happen to be in your props for you.config
ー configuration Plume needs to activate the right variants or attach the right handlers. Usually a set of variant names for different states, element names that we want to attach props or handlers to, and slot names that we want to fill with generated content.ref
ー used with React.forwardRef for imperative programmatic access to the Plume component. Each Plume component comes with its own ref interface; most of the time, there’s a function to get the root DOM element, and a function to focus.
The Plume hooks then return an object with these keys:
plumeProps
ー an object with the variants, overrides, and args that you should spread onto thePlasmic*
component.state
ー for components where this makes sense, the current state of the Plume component. You can use this to additionally control the state of the Plume component, or to query for and render additional information for the component. For example, for aSlider
, you may want access to the current value of a slider thumb, so you can render it in a tooltip.
Using a Plume hook for your Plume-compatible component often looks like this:
// file: MyComponent.tsx
import PlasmicMyComponent from "./plasmic/PlasmicMyComponent";
import {
PlumeComponentProps,
PlumeComponentRef,
useComponent
} from "@plasmicapp/plume";
// Your component should extend the minimum set of props required
// for this Plume component.
interface MyComponentProps extends PlumeComponentProps {
// It can additionally have any other variants or slots that
// you've defined for your component.
type?: "primary" | "secondary";
size?: "small" | "large";
}
function MyComponent_(props: MyComponentProps, ref: PlumeComponentRef) {
// Call the Plume hook
const { plumeProps } = useComponent(
// Pass in the generated Plasmic* class
PlasmicMyComponent,
// Pass in the component props
props,
{
// Pass in how you map your component variants /
// elements / props to the Plume spec.
// Map certain Plume component states to your component's
// variants
// Mapping "isDisabled" Plume component state to
// Variant Group "state", Variant "isDisabled"
isDisabledVariant: ["state", "isDisabled"],
// Mapping "isSelected" Plume component state to
// Variant Group "state", Variant "isSelected"
isSelectedVariant: ["state", "isSelected"],
// Map certain required Plume elements to your
// component's elements
root: "root",
label: "labelContainer",
// Map certain required Plume slots to your
// component's slots
contentSlot: "children"
},
ref
);
return (
<PlasmicMyComponent
// Spread the `plumeProps` onto your Plasmic* component
{...plumeProps}
// useComponent automatically applies your variants and
// args found in your props, so you don't need to do it
// yourself.
// But you may have other parts of your component that
// Plume doesn't know about that you'll want to provide
// overrides for
someNode={{
// override props
}}
// You may also have other variants to activate based
// on your props
withIcon={!!props.icon}
/>
);
}
const MyComponent = React.forwardRef(MyComponent_);
export default MyComponent;
React-Aria and friends
Under the hood, Plume wraps around hooks provided by the great React-Aria project, an exciting new framework for attaching accessible behavior to your components. With Plasmic, it is now easier than ever to build your own fully custom component system — you make the designs in Plasmic, React-Aria brings the accessibility and interactivity, and Plume brings the two together! Read more about how this works.