diff options
| author | Armand Philippot <git@armandphilippot.com> | 2022-04-19 12:07:21 +0200 | 
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2022-04-19 12:07:21 +0200 | 
| commit | a4a406463d69f6901919d273e831dff22a838caf (patch) | |
| tree | 112f3363bbf8382e5bb53d46f26198c0e4ce658f /src/components/organisms/images | |
| parent | feaae9e550d2361cdd582f5a8c4298857ad8c7cf (diff) | |
chore: add a Gallery component
Diffstat (limited to 'src/components/organisms/images')
| -rw-r--r-- | src/components/organisms/images/gallery.module.scss | 26 | ||||
| -rw-r--r-- | src/components/organisms/images/gallery.stories.tsx | 75 | ||||
| -rw-r--r-- | src/components/organisms/images/gallery.test.tsx | 38 | ||||
| -rw-r--r-- | src/components/organisms/images/gallery.tsx | 35 | 
4 files changed, 174 insertions, 0 deletions
| diff --git a/src/components/organisms/images/gallery.module.scss b/src/components/organisms/images/gallery.module.scss new file mode 100644 index 0000000..a057ed9 --- /dev/null +++ b/src/components/organisms/images/gallery.module.scss @@ -0,0 +1,26 @@ +@use "@styles/abstracts/mixins" as mix; +@use "@styles/abstracts/placeholders"; + +.wrapper { +  @extend %reset-list; + +  display: grid; +  grid-template-columns: minmax(0, 1fr); +  gap: var(--spacing-sm); +  max-width: 100%; +  margin: var(--spacing-sm) 0; + +  @for $i from 0 to 6 { +    &--#{$i}-columns { +      @include mix.media("screen") { +        @include mix.dimensions("xs") { +          grid-template-columns: repeat(2, minmax(0, 1fr)); +        } + +        @include mix.dimensions("sm") { +          grid-template-columns: repeat(#{$i}, minmax(0, 1fr)); +        } +      } +    } +  } +} diff --git a/src/components/organisms/images/gallery.stories.tsx b/src/components/organisms/images/gallery.stories.tsx new file mode 100644 index 0000000..786cfff --- /dev/null +++ b/src/components/organisms/images/gallery.stories.tsx @@ -0,0 +1,75 @@ +import ResponsiveImage from '@components/molecules/images/responsive-image'; +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import Gallery from './gallery'; + +/** + * Gallery - Storybook Meta + */ +export default { +  title: 'Organisms/Images/Gallery', +  component: Gallery, +  argTypes: { +    children: { +      control: { +        type: null, +      }, +      description: 'Two or more ResponsiveImage component.', +      type: { +        name: 'function', +        required: true, +      }, +    }, +    columns: { +      control: { +        type: 'number', +        min: 2, +        max: 4, +      }, +      description: 'The columns count.', +      type: { +        name: 'number', +        required: true, +      }, +    }, +  }, +} as ComponentMeta<typeof Gallery>; + +const image = { +  alt: 'Modi provident omnis', +  height: 480, +  src: 'http://placeimg.com/640/480/fashion', +  width: 640, +}; + +const Template: ComponentStory<typeof Gallery> = (args) => ( +  <Gallery {...args}> +    <ResponsiveImage unoptimized {...image} /> +    <ResponsiveImage unoptimized {...image} /> +    <ResponsiveImage unoptimized {...image} /> +    <ResponsiveImage unoptimized {...image} /> +  </Gallery> +); + +/** + * Gallery Stories - Two columns + */ +export const TwoColumns = Template.bind({}); +TwoColumns.args = { +  columns: 2, +}; + +/** + * Gallery Stories - Three columns + */ +export const ThreeColumns = Template.bind({}); +ThreeColumns.args = { +  columns: 3, +}; + +/** + * Gallery Stories - Four columns + */ +export const FourColumns = Template.bind({}); +FourColumns.args = { +  columns: 4, +}; diff --git a/src/components/organisms/images/gallery.test.tsx b/src/components/organisms/images/gallery.test.tsx new file mode 100644 index 0000000..5f35f0a --- /dev/null +++ b/src/components/organisms/images/gallery.test.tsx @@ -0,0 +1,38 @@ +import ResponsiveImage from '@components/molecules/images/responsive-image'; +import { render, screen } from '@test-utils'; +import Gallery from './gallery'; + +const columns = 3; + +const image = { +  alt: 'Modi provident omnis', +  height: 480, +  src: 'http://placeimg.com/640/480/fashion', +  width: 640, +}; + +describe('Gallery', () => { +  it('renders the correct number of items', () => { +    render( +      <Gallery columns={columns}> +        <ResponsiveImage {...image} /> +        <ResponsiveImage {...image} /> +        <ResponsiveImage {...image} /> +        <ResponsiveImage {...image} /> +      </Gallery> +    ); +    expect(screen.getAllByRole('listitem')).toHaveLength(4); +  }); + +  it('renders the right number of columns', () => { +    render( +      <Gallery columns={columns}> +        <ResponsiveImage {...image} /> +        <ResponsiveImage {...image} /> +        <ResponsiveImage {...image} /> +        <ResponsiveImage {...image} /> +      </Gallery> +    ); +    expect(screen.getByRole('list')).toHaveClass(`wrapper--${columns}-columns`); +  }); +}); diff --git a/src/components/organisms/images/gallery.tsx b/src/components/organisms/images/gallery.tsx new file mode 100644 index 0000000..6c4a271 --- /dev/null +++ b/src/components/organisms/images/gallery.tsx @@ -0,0 +1,35 @@ +import { type ResponsiveImageProps } from '@components/molecules/images/responsive-image'; +import { Children, FC, ReactElement } from 'react'; +import styles from './gallery.module.scss'; + +export type GalleryColumn = 2 | 3 | 4; + +export type GalleryProps = { +  /** +   * The images using ResponsiveImage component. +   */ +  children: ReactElement<ResponsiveImageProps>[]; +  /** +   * The columns count. +   */ +  columns: GalleryColumn; +}; + +/** + * Gallery component + * + * Render a gallery of images. + */ +const Gallery: FC<GalleryProps> = ({ children, columns }) => { +  const columnsClass = `wrapper--${columns}-columns`; + +  return ( +    <ul className={`${styles.wrapper} ${styles[columnsClass]}`}> +      {Children.map(children, (child) => { +        return <li className={styles.item}>{child}</li>; +      })} +    </ul> +  ); +}; + +export default Gallery; | 
