aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/organisms/images/gallery.module.scss26
-rw-r--r--src/components/organisms/images/gallery.stories.tsx75
-rw-r--r--src/components/organisms/images/gallery.test.tsx38
-rw-r--r--src/components/organisms/images/gallery.tsx35
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;