diff --git a/.size-limit.json b/.size-limit.json index d366e6c..f615cbd 100644 --- a/.size-limit.json +++ b/.size-limit.json @@ -3,11 +3,11 @@ "name": "JS Minified", "path": "dist/*.js", "gzip": false, - "limit": "1610B" + "limit": "1782B" }, { "name": "JS Compressed", "path": "dist/*.js", - "limit": "748B" + "limit": "786B" } ] diff --git a/README.md b/README.md index a54ee99..9a811ee 100644 --- a/README.md +++ b/README.md @@ -219,6 +219,8 @@ Creates a new section (a heading and its level). | `component` | `node` | Yes | The heading component. Can be anything but best used in combination with ``. | | `children` | `node` | No | The content of the new level. | + + #### Example ```jsx diff --git a/src/index.test.tsx b/src/index.test.tsx index 8b860b4..a09e475 100644 --- a/src/index.test.tsx +++ b/src/index.test.tsx @@ -179,4 +179,26 @@ describe("Section component", () => { expect(pEl.tagName).toBe("P"); }); + + it("should render a heading at the specified level", () => { + const { getByText } = render( +
My H1}> +
My H2}> +
My H3}> +
My H2-2} level={2}> +
My H3-2}>
+
+
+
+
+ ); + + const heading2El = getByText("My H2-2"); + + expect(heading2El.tagName).toBe("H2"); + + const heading3El = getByText("My H3-2"); + + expect(heading3El.tagName).toBe("H3"); + }); }); diff --git a/src/index.tsx b/src/index.tsx index 4e4d5ef..5a7b5aa 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -25,7 +25,10 @@ type HProps = React.DetailedHTMLProps< render?: (context: LevelContextValue) => React.ReactElement; }; -function InternalH( +/** + * Renders a dynamic HTML heading (h1, h2, etc.) or custom component according to the current level. + */ +export const H = React.forwardRef(function H( { render, ...props }: HProps, forwardedRef: React.ForwardedRef ): JSX.Element { @@ -36,37 +39,63 @@ function InternalH( } return ; -} +}); + +type LevelProps = { + level?: Level; + children?: React.ReactNode; +}; /** - * Renders a dynamic HTML heading (h1, h2, etc.) or custom component according to the current level. + * Renders `children` 1 level down, or at the desired level. + * @param children The children in the next level, or the desired level + * @param level The desired level */ -export const H = React.forwardRef(InternalH); +function Level({ level: desiredLevel, children }: LevelProps): JSX.Element { + const { level: currentLevel } = useLevel(); + + const level = desiredLevel ?? (Math.min(currentLevel + 1, 6) as Level); + + const value = { + level, + Component: `h${level}` as Heading, + }; + + return ( + {children} + ); +} type SectionProps = { component: React.ReactNode; children?: React.ReactNode; + level?: Level; }; /** * Renders `component` in the current level and `children` in the next level. * @param component A component containing a heading * @param children The children in the next level + * @param level A specific level to render instead of the current one */ -export function Section({ component, children }: SectionProps): JSX.Element { - const { level } = useLevel(); - - const nextLevel = Math.min(level + 1, 6) as Level; - - const value = { - level: nextLevel, - Component: `h${nextLevel}` as Heading, - }; +export function Section({ + component, + children, + level, +}: SectionProps): JSX.Element { + if (level) { + return ( + + {component} + {children} + + ); + } return ( <> {component} - {children} + {children} ); }