Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .changeset/list-block-index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
"@dextinity/site-react": minor
---

Pass the item index as second argument to `ListBlock`'s `block` function

This allows rendering list items based on their position, for instance, to stagger scroll-in animations.

**Example**

```tsx
<ListBlock
data={data}
block={(block, index) => (
<AnimateBoxInOnScroll direction="bottom" delay={200 * index}>
<KeyFactItemBlock data={block} />
</AnimateBoxInOnScroll>
)}
/>
```
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,5 @@ junit-storybook.xml
# Build output of @dextinity/agent-features (copied from the skills/ and rules/ folders at the repository root)
/packages/agent-features/skills/
/packages/agent-features/rules/
# Playwright CLI output (may contain credentials)
.playwright-cli/
Comment thread
VPS-Obi marked this conversation as resolved.
Outdated
23 changes: 13 additions & 10 deletions demo/site/src/common/blocks/AccordionBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { isWithPreviewPropsData, type PropsWithData, usePreview, withPreview } f
import type { AccordionBlockData } from "@src/blocks.generated";
import { AccordionItemBlock } from "@src/common/blocks/AccordionItemBlock";
import { PageLayout } from "@src/layout/PageLayout";
import { AnimateBoxInOnScroll } from "@src/util/animations/AnimateBoxInOnScroll";
import { useEffect, useMemo, useState } from "react";

import styles from "./AccordionBlock.module.scss";
Expand Down Expand Up @@ -62,16 +63,18 @@ export const AccordionBlock = withPreview(
};

return (
<div className={styles.root}>
{data.blocks.map((block) => (
<AccordionItemBlock
key={block.key}
data={block.props}
onChange={() => handleChange(block.key)}
isExpanded={expandedItems.has(block.key)}
/>
))}
</div>
<AnimateBoxInOnScroll direction="bottom">
<div className={styles.root}>
{data.blocks.map((block) => (
<AccordionItemBlock
key={block.key}
data={block.props}
onChange={() => handleChange(block.key)}
isExpanded={expandedItems.has(block.key)}
/>
))}
</div>
</AnimateBoxInOnScroll>
);
},
{ label: "Accordion" },
Expand Down
5 changes: 4 additions & 1 deletion demo/site/src/common/blocks/ContactFormBlock.module.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
.form {
.formWrapper {
grid-column: 2 / -2;
}

.form {
display: flex;
flex-direction: column;
gap: 20px;
Expand Down
239 changes: 121 additions & 118 deletions demo/site/src/common/blocks/ContactFormBlock.tsx

Large diffs are not rendered by default.

53 changes: 28 additions & 25 deletions demo/site/src/common/blocks/MediaGalleryBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { MediaGalleryBlockData } from "@src/blocks.generated";
import { MediaBlock } from "@src/common/blocks/MediaBlock";
import { Typography } from "@src/common/components/Typography";
import { PageLayout } from "@src/layout/PageLayout";
import { AnimateBoxInOnScroll } from "@src/util/animations/AnimateBoxInOnScroll";
import clsx from "clsx";
import { useEffect, useRef, useState } from "react";
import { FormattedMessage, useIntl } from "react-intl";
Expand Down Expand Up @@ -53,31 +54,33 @@ export const MediaGalleryBlock = withPreview(
aria-label={intl.formatMessage({ id: "mediaGalleryBlock.prevSlide", defaultMessage: "Previous slide" })}
disabled={activeItem === 0}
/>
<BasicSwiper
className={styles.swiper}
slidesPerView={1}
slidesPerGroup={1}
modules={[Navigation]}
navigation={{ prevEl: prevButtonRef.current, nextEl: nextButtonRef.current }}
longSwipesRatio={0.1}
threshold={3}
allowTouchMove
watchOverflow
speed={400}
onSwiper={setSwiper}
onSlideChange={(swiper) => {
setActiveItem(swiper.activeIndex);
}}
>
{data.items.blocks.map((block) => (
<SwiperSlide key={block.key}>
<MediaBlock data={block.props.media} aspectRatio={data.aspectRatio} />
<Typography variant="paragraph200" className={styles.mediaCaption}>
{block.props.caption}
</Typography>
</SwiperSlide>
))}
</BasicSwiper>
<AnimateBoxInOnScroll direction="bottom">
<BasicSwiper
className={styles.swiper}
slidesPerView={1}
slidesPerGroup={1}
modules={[Navigation]}
navigation={{ prevEl: prevButtonRef.current, nextEl: nextButtonRef.current }}
longSwipesRatio={0.1}
threshold={3}
allowTouchMove
watchOverflow
speed={400}
onSwiper={setSwiper}
onSlideChange={(swiper) => {
setActiveItem(swiper.activeIndex);
}}
>
{data.items.blocks.map((block) => (
<SwiperSlide key={block.key}>
<MediaBlock data={block.props.media} aspectRatio={data.aspectRatio} />
<Typography variant="paragraph200" className={styles.mediaCaption}>
{block.props.caption}
</Typography>
</SwiperSlide>
))}
</BasicSwiper>
</AnimateBoxInOnScroll>
<Typography variant="paragraph300" className={styles.customPagination} role="status" aria-live="polite" aria-atomic="true">
<FormattedMessage
id="mediaGalleryBlock.pagination"
Expand Down
5 changes: 4 additions & 1 deletion demo/site/src/common/blocks/PageTreeIndexBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { type PropsWithData, withPreview } from "@dextinity/site-nextjs";
import type { PageTreeIndexBlockData } from "@src/blocks.generated";
import { PageLayout } from "@src/layout/PageLayout";
import { AnimateBoxInOnScroll } from "@src/util/animations/AnimateBoxInOnScroll";
import { createSitePath } from "@src/util/createSitePath";
import NextLink from "next/link";
import type { JSX } from "react";
Expand Down Expand Up @@ -43,7 +44,9 @@ export const PageTreeIndexBlock = withPreview(
const tree = buildTree(allNodes);
return (
<PageLayout grid>
<div className={styles.root}>{renderTree(tree)}</div>
<AnimateBoxInOnScroll direction="bottom" className={styles.root}>
{renderTree(tree)}
</AnimateBoxInOnScroll>
</PageLayout>
);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { type PropsWithData, withPreview } from "@dextinity/site-nextjs";
import type { StandaloneCallToActionListBlockData } from "@src/blocks.generated";
import { PageLayout } from "@src/layout/PageLayout";
import { AnimateBoxInOnScroll } from "@src/util/animations/AnimateBoxInOnScroll";
import clsx from "clsx";

import { CallToActionListBlock } from "./CallToActionListBlock";
Expand All @@ -12,9 +13,11 @@ type StandaloneCallToActionListBlockProps = PropsWithData<StandaloneCallToAction
export const StandaloneCallToActionListBlock = withPreview(
({ data: { callToActionList, alignment } }: StandaloneCallToActionListBlockProps) => {
return (
<div className={clsx(styles.root, styles[`root--${alignment}`])}>
<CallToActionListBlock data={callToActionList} />
</div>
<AnimateBoxInOnScroll direction="bottom" offset={300}>
<div className={clsx(styles.root, styles[`root--${alignment}`])}>
<CallToActionListBlock data={callToActionList} />
</div>
</AnimateBoxInOnScroll>
);
},
{ label: "CallToActionList" },
Expand Down
9 changes: 6 additions & 3 deletions demo/site/src/common/blocks/StandaloneHeadingBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { type PropsWithData, withPreview } from "@dextinity/site-nextjs";
import type { StandaloneHeadingBlockData } from "@src/blocks.generated";
import { PageLayout } from "@src/layout/PageLayout";
import { AnimateBoxInOnScroll } from "@src/util/animations/AnimateBoxInOnScroll";
import clsx from "clsx";

import { HeadingBlock } from "./HeadingBlock";
Expand All @@ -12,9 +13,11 @@ type StandaloneHeadingBlockProps = PropsWithData<StandaloneHeadingBlockData>;
export const StandaloneHeadingBlock = withPreview(
({ data: { heading, textAlignment } }: StandaloneHeadingBlockProps) => {
return (
<div className={clsx(styles.root, textAlignment === "center" && styles.rootCenter)}>
<HeadingBlock data={heading} />
</div>
<AnimateBoxInOnScroll direction="bottom">
<div className={clsx(styles.root, textAlignment === "center" && styles.rootCenter)}>
<HeadingBlock data={heading} />
</div>
</AnimateBoxInOnScroll>
);
},
{ label: "Heading" },
Expand Down
5 changes: 4 additions & 1 deletion demo/site/src/common/blocks/StandaloneMediaBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@
import { type PropsWithData, withPreview } from "@dextinity/site-nextjs";
import type { StandaloneMediaBlockData } from "@src/blocks.generated";
import { PageLayout } from "@src/layout/PageLayout";
import { AnimateBoxInOnScroll } from "@src/util/animations/AnimateBoxInOnScroll";

import { MediaBlock } from "./MediaBlock";

export const StandaloneMediaBlock = withPreview(
({ data: { media, aspectRatio } }: PropsWithData<StandaloneMediaBlockData>) => {
return (
<PageLayout>
<MediaBlock data={media} aspectRatio={aspectRatio} />
<AnimateBoxInOnScroll direction="bottom">
<MediaBlock data={media} aspectRatio={aspectRatio} />
</AnimateBoxInOnScroll>
</PageLayout>
);
},
Expand Down
9 changes: 6 additions & 3 deletions demo/site/src/common/blocks/StandaloneRichTextBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { type PropsWithData, withPreview } from "@dextinity/site-nextjs";
import type { StandaloneRichTextBlockData } from "@src/blocks.generated";
import { PageLayout } from "@src/layout/PageLayout";
import { AnimateBoxInOnScroll } from "@src/util/animations/AnimateBoxInOnScroll";

import { RichTextBlock } from "./RichTextBlock";
import styles from "./StandaloneRichTextBlock.module.scss";
Expand All @@ -11,9 +12,11 @@ type StandaloneRichTextBlockProps = PropsWithData<StandaloneRichTextBlockData>;
export const StandaloneRichTextBlock = withPreview(
({ data: { richText, textAlignment } }: StandaloneRichTextBlockProps) => {
return (
<div className={styles[textAlignment]}>
<RichTextBlock data={richText} disableLastBottomSpacing />
</div>
<AnimateBoxInOnScroll direction="bottom" offset={300}>
<div className={styles[textAlignment]}>
<RichTextBlock data={richText} disableLastBottomSpacing />
</div>
</AnimateBoxInOnScroll>
);
},
{ label: "RichText" },
Expand Down
45 changes: 24 additions & 21 deletions demo/site/src/common/blocks/TableBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { PropsWithData } from "@dextinity/site-nextjs";
import type { TableBlockData } from "@src/blocks.generated";
import { PageLayout } from "@src/layout/PageLayout";
import { AnimateBoxInOnScroll } from "@src/util/animations/AnimateBoxInOnScroll";
import clsx from "clsx";

import { RichTextBlock } from "./RichTextBlock";
Expand All @@ -10,28 +11,30 @@ export const TableBlock = ({ data }: PropsWithData<TableBlockData>) => {
return (
<PageLayout grid>
<div className={styles.pageLayoutContent}>
<table className={styles.table}>
<tbody>
{data.rows.map((row) => (
<tr key={row.id} className={styles.row}>
{data.columns.map((column) => {
const cellValue = row.cellValues.find((cellValue) => cellValue.columnId === column.id);
const highlightCell = row.highlighted || column.highlighted;
<AnimateBoxInOnScroll direction="bottom" offset={300}>
<table className={styles.table}>
<tbody>
{data.rows.map((row) => (
<tr key={row.id} className={styles.row}>
{data.columns.map((column) => {
const cellValue = row.cellValues.find((cellValue) => cellValue.columnId === column.id);
const highlightCell = row.highlighted || column.highlighted;

return (
<td key={column.id} className={clsx([styles.cell, highlightCell && styles["cell--highlighted"]])}>
{cellValue?.value && (
<div className={styles["cell__content"]}>
<RichTextBlock data={cellValue?.value} disableLastBottomSpacing />
</div>
)}
</td>
);
})}
</tr>
))}
</tbody>
</table>
return (
<td key={column.id} className={clsx([styles.cell, highlightCell && styles["cell--highlighted"]])}>
{cellValue?.value && (
<div className={styles["cell__content"]}>
<RichTextBlock data={cellValue?.value} disableLastBottomSpacing />
</div>
)}
</td>
);
})}
</tr>
))}
</tbody>
</table>
</AnimateBoxInOnScroll>
</div>
</PageLayout>
);
Expand Down
18 changes: 11 additions & 7 deletions demo/site/src/common/blocks/TextImageBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import { type PropsWithData, withPreview } from "@dextinity/site-nextjs";
import type { TextImageBlockData } from "@src/blocks.generated";
import { PageLayout } from "@src/layout/PageLayout";
import { AnimateBoxInOnScroll } from "@src/util/animations/AnimateBoxInOnScroll";
import { AnimateGroup } from "@src/util/animations/AnimateGroup";
import { createImageSizes } from "@src/util/createImageSizes";
import clsx from "clsx";

Expand All @@ -12,14 +14,16 @@ import styles from "./TextImageBlock.module.scss";
export const TextImageBlock = withPreview(
({ data: { text, image, imageAspectRatio, imagePosition } }: PropsWithData<TextImageBlockData>) => {
return (
<div className={clsx(styles.root, imagePosition === "left" && styles["root--imageLeft"])}>
<div className={styles.imageContainer}>
<DamImageBlock data={image} aspectRatio={imageAspectRatio} sizes={createImageSizes({ default: "100vw", md: "30vw" })} />
<AnimateGroup>
<div className={clsx(styles.root, imagePosition === "left" && styles["root--imageLeft"])}>
<AnimateBoxInOnScroll direction={imagePosition === "left" ? "left" : "right"} className={styles.imageContainer}>
<DamImageBlock data={image} aspectRatio={imageAspectRatio} sizes={createImageSizes({ default: "100vw", md: "30vw" })} />
</AnimateBoxInOnScroll>
<AnimateBoxInOnScroll direction="bottom" delay={100} offset={300} className={styles.textContainer}>
<RichTextBlock data={text} />
</AnimateBoxInOnScroll>
</div>
<div className={styles.textContainer}>
<RichTextBlock data={text} />
</div>
</div>
</AnimateGroup>
);
},
{ label: "Text/Image" },
Expand Down
5 changes: 4 additions & 1 deletion demo/site/src/common/blocks/TipTapRichTextBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { PageLayout } from "@src/layout/PageLayout";
import { ProductPriceBlock } from "@src/products/blocks/ProductPriceBlock";
import { ProductTeaserBlock } from "@src/products/blocks/ProductTeaserBlock";
import type { LoadedData as ProductTeaserLoadedData } from "@src/products/blocks/ProductTeaserBlock.loader";
import { AnimateBoxInOnScroll } from "@src/util/animations/AnimateBoxInOnScroll";

import { Typography, type TypographyProps } from "../components/Typography";
import { isValidLink } from "../helpers/HiddenIfInvalidLink";
Expand Down Expand Up @@ -102,7 +103,9 @@ export const TipTapRichTextBlock = withPreview(
export const PageContentTipTapRichTextBlock = (props: PropsWithData<TipTapRichTextBlockData>) => (
<PageLayout grid>
<div className={styles.pageLayoutContent}>
<TipTapRichTextBlock {...props} />
<AnimateBoxInOnScroll direction="bottom" offset={300}>
<TipTapRichTextBlock {...props} />
</AnimateBoxInOnScroll>
</div>
</PageLayout>
);
Loading
Loading