From c5af9cdbbec87dac30686cfd7360e2bc82d0ee25 Mon Sep 17 00:00:00 2001 From: Twan Braas Date: Tue, 23 Jan 2024 13:40:05 +0100 Subject: [PATCH 1/2] Create infinite autofill component --- src/components/AutoFill/AutoFill.stories.tsx | 1 - .../InfiniteAutoFill/InfiniteAutoFill.mdx | 64 +++++++++++++ .../InfiniteAutoFill.stories.tsx | 96 +++++++++++++++++++ .../InfiniteAutoFill.test.tsx | 66 +++++++++++++ .../InfiniteAutoFill/InfiniteAutoFill.tsx | 25 +++++ 5 files changed, 251 insertions(+), 1 deletion(-) create mode 100644 src/components/InfiniteAutoFill/InfiniteAutoFill.mdx create mode 100644 src/components/InfiniteAutoFill/InfiniteAutoFill.stories.tsx create mode 100644 src/components/InfiniteAutoFill/InfiniteAutoFill.test.tsx create mode 100644 src/components/InfiniteAutoFill/InfiniteAutoFill.tsx diff --git a/src/components/AutoFill/AutoFill.stories.tsx b/src/components/AutoFill/AutoFill.stories.tsx index 636d925..8777010 100644 --- a/src/components/AutoFill/AutoFill.stories.tsx +++ b/src/components/AutoFill/AutoFill.stories.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react/jsx-no-literals */ import { type Meta, type StoryObj } from '@storybook/react'; import { AutoFill } from './AutoFill.js'; diff --git a/src/components/InfiniteAutoFill/InfiniteAutoFill.mdx b/src/components/InfiniteAutoFill/InfiniteAutoFill.mdx new file mode 100644 index 0000000..e8aee6d --- /dev/null +++ b/src/components/InfiniteAutoFill/InfiniteAutoFill.mdx @@ -0,0 +1,64 @@ +import { Canvas, Meta } from '@storybook/blocks'; +import * as stories from './InfiniteAutoFill.stories'; + + + +# InfiniteAutoFill + +Uses the AutoFill to repeat children to fill the parent element in given axis. In addition to that +it adds the children one more time to the end of the list. This can be useful for example marquee's. + +## Reference + +```ts +interface InfiniteAutoFillProps { + children: ReadonlyArray; + axis?: 'x' | 'y'; // Default: 'x' +} + +function InfiniteAutoFill(props: InfiniteAutoFillProps): ReactElement; +``` + +## InfiniteAutoFill for X axis + +Fills components horizontally + one extra. + +```tsx +function DemoComponent() { + return ( +
+ +
+
Child
+
+
+
+ ); +} +``` + +### Demo + + + +## InfiniteAutoFill for Y axis + +Fills components vertically + one extra. + +```tsx +function DemoComponent() { + return ( +
+ +
+
Child
+
+
+
+ ); +} +``` + +### Demo + + diff --git a/src/components/InfiniteAutoFill/InfiniteAutoFill.stories.tsx b/src/components/InfiniteAutoFill/InfiniteAutoFill.stories.tsx new file mode 100644 index 0000000..d18884a --- /dev/null +++ b/src/components/InfiniteAutoFill/InfiniteAutoFill.stories.tsx @@ -0,0 +1,96 @@ +import { type Meta, type StoryObj } from '@storybook/react'; +import { InfiniteAutoFill } from './InfiniteAutoFill.js'; + +const meta = { + title: 'Components / InfiniteAutoFill', + component: InfiniteAutoFill, +} satisfies Meta; + +type Story = StoryObj; + +export default meta; + +export const Horizontal: Story = { + render() { + return ( +
+ +
+
+
+ +
+
+
+ +
+ ); + }, + args: { + children:
, + }, +}; + +export const Vertical: Story = { + render() { + return ( +
+ +
+
+
+ +
+ ); + }, + args: { + children:
, + }, +}; diff --git a/src/components/InfiniteAutoFill/InfiniteAutoFill.test.tsx b/src/components/InfiniteAutoFill/InfiniteAutoFill.test.tsx new file mode 100644 index 0000000..68cf18b --- /dev/null +++ b/src/components/InfiniteAutoFill/InfiniteAutoFill.test.tsx @@ -0,0 +1,66 @@ +import { render, waitFor } from '@testing-library/react'; +import { describe, expect, it } from 'vitest'; +import { InfiniteAutoFill } from './InfiniteAutoFill.js'; + +describe('InfiniteAutoFill', () => { + it('should not crash', async () => { + const result = render( + +
+ , + ); + + expect(result.baseElement.firstElementChild).toBeDefined(); + }); + + it('should fill parent element', async () => { + const result = render( +
+ +
+ +
, + {}, + ); + + waitFor(async () => { + const children = await result.findAllByTestId('child'); + + expect(children.length).toBe(6); + }); + }); + + it('should overflow parent element', async () => { + const result = render( +
+ +
+ +
, + {}, + ); + + waitFor(async () => { + const children = await result.findAllByTestId('child'); + + expect(children.length).toBe(7); + }); + }); + + it('should fill parent element', async () => { + const result = render( +
+ +
+ +
, + {}, + ); + + waitFor(async () => { + const children = await result.findAllByTestId('child'); + + expect(children.length).toBe(6); + }); + }); +}); diff --git a/src/components/InfiniteAutoFill/InfiniteAutoFill.tsx b/src/components/InfiniteAutoFill/InfiniteAutoFill.tsx new file mode 100644 index 0000000..6d7c5a6 --- /dev/null +++ b/src/components/InfiniteAutoFill/InfiniteAutoFill.tsx @@ -0,0 +1,25 @@ +import { type ReactElement, type RefCallback } from 'react'; +import { AutoFill } from '../../index.js'; + +type InfiniteAutoFillChildrenProps = { + ref: RefCallback; +}; + +type InfiniteAutoFillProps = { + children: + | ReactElement + | ReadonlyArray>; + axis?: 'x' | 'y'; +}; + +/** + * Repeats children to fill the parent element in given axis. + */ +export function InfiniteAutoFill({ children, axis = 'x' }: InfiniteAutoFillProps): ReactElement { + return ( + <> + {children} + {children} + + ); +} From 168e305557dea9690dbfc5cc6d6aeeb735b7450a Mon Sep 17 00:00:00 2001 From: Twan Braas Date: Mon, 29 Jan 2024 15:19:02 +0100 Subject: [PATCH 2/2] Re-use types from AutoFill to InfiniteAutoFill --- src/components/AutoFill/AutoFill.mdx | 2 +- src/components/AutoFill/AutoFill.tsx | 2 +- .../InfiniteAutoFill/InfiniteAutoFill.mdx | 5 +++-- .../InfiniteAutoFill/InfiniteAutoFill.tsx | 15 +++------------ 4 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/components/AutoFill/AutoFill.mdx b/src/components/AutoFill/AutoFill.mdx index c607b23..536fd74 100644 --- a/src/components/AutoFill/AutoFill.mdx +++ b/src/components/AutoFill/AutoFill.mdx @@ -48,7 +48,7 @@ Fills components vertically. function DemoComponent() { return (
- +
Child
diff --git a/src/components/AutoFill/AutoFill.tsx b/src/components/AutoFill/AutoFill.tsx index 2d4e798..8fc3c44 100644 --- a/src/components/AutoFill/AutoFill.tsx +++ b/src/components/AutoFill/AutoFill.tsx @@ -18,7 +18,7 @@ type AutoFillChildrenProps = { ref: RefCallback; }; -type AutoFillProps = { +export type AutoFillProps = { children: | ReactElement | ReadonlyArray>; diff --git a/src/components/InfiniteAutoFill/InfiniteAutoFill.mdx b/src/components/InfiniteAutoFill/InfiniteAutoFill.mdx index e8aee6d..237a0c6 100644 --- a/src/components/InfiniteAutoFill/InfiniteAutoFill.mdx +++ b/src/components/InfiniteAutoFill/InfiniteAutoFill.mdx @@ -6,7 +6,8 @@ import * as stories from './InfiniteAutoFill.stories'; # InfiniteAutoFill Uses the AutoFill to repeat children to fill the parent element in given axis. In addition to that -it adds the children one more time to the end of the list. This can be useful for example marquee's. +it adds the children one more time to the end of the list. This can be useful for example marquees +or infinite carousels. ## Reference @@ -49,7 +50,7 @@ Fills components vertically + one extra. function DemoComponent() { return (
- +
Child
diff --git a/src/components/InfiniteAutoFill/InfiniteAutoFill.tsx b/src/components/InfiniteAutoFill/InfiniteAutoFill.tsx index 6d7c5a6..d19043c 100644 --- a/src/components/InfiniteAutoFill/InfiniteAutoFill.tsx +++ b/src/components/InfiniteAutoFill/InfiniteAutoFill.tsx @@ -1,21 +1,12 @@ -import { type ReactElement, type RefCallback } from 'react'; +import { type ComponentProps, type ReactElement } from 'react'; import { AutoFill } from '../../index.js'; -type InfiniteAutoFillChildrenProps = { - ref: RefCallback; -}; - -type InfiniteAutoFillProps = { - children: - | ReactElement - | ReadonlyArray>; - axis?: 'x' | 'y'; -}; +type InfiniteAutoFillProps = ComponentProps; /** * Repeats children to fill the parent element in given axis. */ -export function InfiniteAutoFill({ children, axis = 'x' }: InfiniteAutoFillProps): ReactElement { +export function InfiniteAutoFill({ children, axis }: InfiniteAutoFillProps): ReactElement { return ( <> {children}