Skip to content

Commit

Permalink
fix(image-block): restore old caption classes and add props forwarding
Browse files Browse the repository at this point in the history
  • Loading branch information
gcornut committed Aug 14, 2024
1 parent f472c95 commit 47e2493
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 9 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Fixed

- `ImageBlock`: restore old caption class names.

### Changed

- `ImageBlock`: add `titleProps` and `descriptionProps` to forward to the title and description.

## [3.8.0][] - 2024-08-13

### Fixed
Expand Down
28 changes: 28 additions & 0 deletions packages/lumx-react/src/components/image-block/ImageBlock.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import { commonTestsSuiteRTL } from '@lumx/react/testing/utils';

import { render } from '@testing-library/react';
import { queryByClassName } from '@lumx/react/testing/utils/queries';
import { toNestedProps } from '@lumx/react/stories/decorators/withNestedProps';

import { ImageBlock, ImageBlockProps } from './ImageBlock';
import { FullFeatured } from './ImageBlock.stories';

const CLASSNAME = ImageBlock.className as string;

Expand All @@ -14,6 +17,31 @@ const setup = (props: Partial<ImageBlockProps> = {}) => {
};

describe(`<${ImageBlock.displayName}>`, () => {
it('should render caption elements', () => {
const props = {
...toNestedProps(FullFeatured.args),
titleProps: { className: 'custom-title-class' },
descriptionProps: { className: 'custom-description-class' },
};
const { imageBlock } = setup(props);
const wrapper = queryByClassName(imageBlock as HTMLElement, 'lumx-image-block__wrapper');
expect(wrapper).toBeInTheDocument();

const caption = queryByClassName(wrapper as HTMLElement, 'lumx-image-block__caption');
expect(caption).toBeInTheDocument();

const title = queryByClassName(caption as HTMLElement, 'lumx-image-block__title');
expect(title).toBeInTheDocument();
expect(title).toHaveClass(props.titleProps.className);

const description = queryByClassName(caption as HTMLElement, 'lumx-image-block__description');
expect(description).toBeInTheDocument();
expect(description).toHaveClass(props.descriptionProps.className);

const tags = queryByClassName(wrapper as HTMLElement, 'lumx-image-block__tags');
expect(tags).toBeInTheDocument();
});

// Common tests suite.
commonTestsSuiteRTL(setup, {
baseClassName: CLASSNAME,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,15 @@ export const ImageBlock: Comp<ImageBlockProps, HTMLDivElement> = forwardRef((pro
captionStyle,
className,
description,
descriptionProps,
fillHeight,
image,
size,
tags,
theme,
thumbnailProps,
title,
titleProps,
...forwardedProps
} = props;
return (
Expand Down Expand Up @@ -118,10 +120,12 @@ export const ImageBlock: Comp<ImageBlockProps, HTMLDivElement> = forwardRef((pro
/>
<ImageCaption
as="figcaption"
className={`${CLASSNAME}__wrapper`}
baseClassName={CLASSNAME}
theme={theme}
title={title}
titleProps={titleProps}
description={description}
descriptionProps={descriptionProps}
tags={tags}
captionStyle={captionStyle}
align={align}
Expand Down
62 changes: 54 additions & 8 deletions packages/lumx-react/src/components/image-block/ImageCaption.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
import React, { CSSProperties, ReactNode } from 'react';

import { FlexBox, HorizontalAlignment, Text, TextProps } from '@lumx/react';
import { HasClassName, HasPolymorphicAs, HasTheme } from '@lumx/react/utils/type';
import { HasPolymorphicAs, HasTheme } from '@lumx/react/utils/type';
import classNames from 'classnames';

type As = 'div' | 'figcaption';

type ForwardedTextProps = Omit<TextProps, 'as' | 'typography' | 'color' | 'colorVariant'>;

export type ImageCaptionMetadata = {
/** Image title to display in the caption. */
title?: string;
/** Props to pass to the title. */
titleProps?: ForwardedTextProps;
/** Image description. Can be either a string, or sanitized html. */
description?: string | { __html: string };
/** Props to pass to the title. */
descriptionProps?: ForwardedTextProps;
/** Tag content. */
tags?: ReactNode;
/** Caption custom CSS style. */
captionStyle?: CSSProperties;
};

export type ImageCaptionProps<AS extends As = 'figcaption'> = HasTheme &
HasClassName &
HasPolymorphicAs<AS> &
ImageCaptionMetadata & {
/** Base className for sub elements */
baseClassName?: string;
/** Alignment. */
align?: HorizontalAlignment;
/** Truncate text on title & description (no line wrapping). */
Expand All @@ -28,7 +36,19 @@ export type ImageCaptionProps<AS extends As = 'figcaption'> = HasTheme &

/** Internal component used to render image captions */
export const ImageCaption = <AS extends As>(props: ImageCaptionProps<AS>) => {
const { className, theme, as = 'figcaption', title, description, tags, captionStyle, align, truncate } = props;
const {
baseClassName,
theme,
as = 'figcaption',
title,
titleProps,
description,
descriptionProps,
tags,
captionStyle,
align,
truncate,
} = props;
if (!title && !description && !tags) return null;

const titleColor = { color: theme === 'dark' ? 'light' : 'dark' } as const;
Expand All @@ -41,25 +61,51 @@ export const ImageCaption = <AS extends As>(props: ImageCaptionProps<AS>) => {
return (
<FlexBox
as={as}
className={className}
className={classNames(baseClassName && `${baseClassName}__wrapper`)}
style={captionStyle}
orientation="vertical"
vAlign={align}
hAlign={align === 'center' ? align : undefined}
gap="regular"
>
{(title || description) && (
<Text as="p" truncate={truncate} {...baseColor}>
<Text
as="p"
className={classNames(baseClassName && `${baseClassName}__caption`)}
truncate={truncate}
{...baseColor}
>
{title && (
<Text as="span" typography="subtitle1" {...titleColor}>
<Text
{...titleProps}
as="span"
className={classNames(titleProps?.className, baseClassName && `${baseClassName}__title`)}
typography="subtitle1"
{...titleColor}
>
{title}
</Text>
)}{' '}
{description && <Text as="span" typography="body1" {...descriptionContent} />}
{description && (
<Text
{...descriptionProps}
as="span"
className={classNames(
descriptionProps?.className,
baseClassName && `${baseClassName}__description`,
)}
typography="body1"
{...descriptionContent}
/>
)}
</Text>
)}
{tags && (
<FlexBox orientation="horizontal" vAlign={align}>
<FlexBox
className={classNames(baseClassName && `${baseClassName}__tags`)}
orientation="horizontal"
vAlign={align}
>
{tags}
</FlexBox>
)}
Expand Down

0 comments on commit 47e2493

Please sign in to comment.