@goncharovv/react-slots
v1.0.0
Published
react slots
Readme
@goncharovv/react-slots
Installation
npm install @goncharovv/react-slotsQuick start
- Define slots with
createSlot:
import { createSlot } from '@goncharovv/react-slots';
import { PropsWithChildren } from 'react';
const HeaderSlot = createSlot<PropsWithChildren>('Header');
const FooterSlot = createSlot<PropsWithChildren>('Footer');- Build a component and read slots with
useSlots:
import { useSlots } from '@goncharovv/react-slots';
import { FC, PropsWithChildren } from 'react';
const _Modal: FC<PropsWithChildren> = ({ children }) => {
const slots = useSlots(children);
const header = slots.get(HeaderSlot);
const footer = slots.get(FooterSlot);
return (
<div>
<header>{header?.rendered}</header>
{slots.getDefaultSlot()}
<footer>{footer?.rendered}</footer>
</div>
);
};
const Modal = Object.assign(_Modal, {
Header: HeaderSlot,
Footer: FooterSlot,
});- Use it:
<Modal>
<Modal.Header>Create Entity</Modal.Header>
<form id="form">
{/* default slot content */}
<input type="text" />
</form>
<Modal.Footer>
<button type="button">Cancel</button>
<button form="form" type="submit">Create</button>
</Modal.Footer>
</Modal>Passing props through slots
Slots can carry typed props. Read them via <slot>.props:
import { createSlot, useSlots } from '@goncharovv/react-slots';
import { FC, PropsWithChildren } from 'react';
interface TitleProps extends PropsWithChildren {
as: 'h1' | 'h2' | 'h3';
}
const Title: FC<TitleProps> = (props) => {
const { as: Component, children } = props;
return (
<Component>{children}</Component>
);
};
const TitleSlot = createSlot<TitleProps>('Title');
const _Heading: FC<PropsWithChildren> = ({ children }) => {
const slots = useSlots(children);
const title = slots.get(TitleSlot);
if (!title) throw new Error('Title slot is required');
return <Title {...title.props}>{title.rendered}</Title>;
};
const Heading = Object.assign(_Heading, {
Title: TitleSlot,
});