Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
506 changes: 490 additions & 16 deletions src/components/Carousel/Carousel.stories.tsx

Large diffs are not rendered by default.

153 changes: 55 additions & 98 deletions src/components/Carousel/Carousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,18 @@ import { Disclosure, DisclosureSummary } from '../Disclosure';

type CarouselImage = {
src: string;
srcSet?: string;
alt: string;
width: number;
height: number;
};

type CarouselImageSource = {
srcSet: string;
width?: number;
height?: number;
media: string;
};

export type CarouselSlide = {
id: string;
label: string;
href: string;
href?: string;
target?: string;
image: CarouselImage;
imageSources?: CarouselImageSource[];
};

// Carousel Sub Components
Expand Down Expand Up @@ -163,34 +156,24 @@ const CarouselPageNav = (props: CarouselPageNavProps) => {
type CarouselBackgroundLayerProps = {
className?: string;
image: CarouselImage;
imageSources?: CarouselImageSource[];
};

const CarouselBackgroundLayer = (props: CarouselBackgroundLayerProps) => {
const { className, image, imageSources } = props;
const { className, image } = props;

return (
<div
aria-hidden={true}
className={`absolute -inset-1/2 blur-[25px] transform-gpu pointer-events-none ${className ?? ''}`}
>
<picture>
{imageSources?.map((source) => (
<source
key={source.media}
srcSet={source.srcSet}
media={source.media}
width={source.width}
height={source.height}
/>
))}
<img
className='h-full w-full object-cover'
src={image.src}
alt=''
width={image.width}
height={image.height}
/>
</picture>
<img
className='h-full w-full object-cover'
src={image.src}
srcSet={image.srcSet}
alt=''
width={image.width}
height={image.height}
/>
<div className='absolute inset-0 bg-white mix-blend-soft-light' />
</div>
);
Expand Down Expand Up @@ -240,38 +223,30 @@ const CarouselExpandList = (props: CarouselExpandListProps) => {
<a
className={`
block relative
hover:outline hover:outline-4 hover:outline-blue-900 hover:-outline-offset-1
focus-visible:outline focus-visible:outline-4 focus-visible:outline-black focus-visible:outline-offset-[calc(2/16*1rem)] focus-visible:rounded-4 focus-visible:ring-[calc(2/16*1rem)] focus-visible:ring-yellow-300
hover:after:absolute hover:after:inset-[1px] hover:after:ring-[calc(2/16*1rem)] hover:after:ring-inset hover:after:ring-white hover:after:pointer-events-none
${slide.href ? `
hover:outline hover:outline-4 hover:outline-blue-900 hover:-outline-offset-1
focus-visible:outline focus-visible:outline-4 focus-visible:outline-black focus-visible:outline-offset-[calc(2/16*1rem)] focus-visible:rounded-4 focus-visible:ring-[calc(2/16*1rem)] focus-visible:ring-yellow-300
hover:after:absolute hover:after:inset-[1px] hover:after:ring-[calc(2/16*1rem)] hover:after:ring-inset hover:after:ring-white hover:after:pointer-events-none
` : ''}
`}
href={slide.href}
target={slide.target}
>
<span className='sr-only'>{slide.label}</span>
<div className='grid place-content-center h-full rounded-[inherit] outline outline-2 outline-black -outline-offset-2'>
<picture>
{slide.imageSources?.map((source) => (
<source
key={source.media}
srcSet={source.srcSet}
media={source.media}
width={source.width}
height={source.height}
/>
))}
<img
className='block max-w-full size-auto'
src={slide.image.src}
alt={slide.image.alt}
width={slide.image.width}
height={slide.image.height}
/>
</picture>
<img
className='block max-w-full size-auto'
src={slide.image.src}
srcSet={slide.image.srcSet}
alt={slide.image.alt}
width={slide.image.width}
height={slide.image.height}
/>
</div>
</a>
</div>
<div className='[grid-area:main] relative -z-10 overflow-clip'>
<CarouselBackgroundLayer image={slide.image} imageSources={slide.imageSources} />
<CarouselBackgroundLayer image={slide.image} />
</div>
</li>
);
Expand Down Expand Up @@ -324,35 +299,27 @@ const CarouselPanelArea = (props: CarouselPanelAreaProps) => {
<a
className={`
block relative
after:absolute after:pointer-events-none
hover:outline hover:outline-4 hover:outline-blue-900 hover:-outline-offset-2
focus-visible:overflow-hidden focus-visible:outline focus-visible:outline-4 focus-visible:outline-black focus-visible:-outline-offset-[calc(2/16*1rem)] focus-visible:rounded-8 focus-visible:ring-[calc(2/16*1rem)] focus-visible:ring-yellow-300
hover:after:inset-[2px] hover:after:ring-[calc(2/16*1rem)] hover:after:ring-inset hover:after:ring-white
focus-visible:after:inset-[2px] focus-visible:after:ring-[calc(2/16*1rem)] focus-visible:after:ring-inset focus-visible:after:ring-yellow-300 focus-visible:after:rounded-6
${currentSlide.href ? `
after:absolute after:pointer-events-none
hover:outline hover:outline-4 hover:outline-blue-900 hover:-outline-offset-2
focus-visible:overflow-hidden focus-visible:outline focus-visible:outline-4 focus-visible:outline-black focus-visible:-outline-offset-[calc(2/16*1rem)] focus-visible:rounded-8 focus-visible:ring-[calc(2/16*1rem)] focus-visible:ring-yellow-300
hover:after:inset-[2px] hover:after:ring-[calc(2/16*1rem)] hover:after:ring-inset hover:after:ring-white
focus-visible:after:inset-[2px] focus-visible:after:ring-[calc(2/16*1rem)] focus-visible:after:ring-inset focus-visible:after:ring-yellow-300 focus-visible:after:rounded-6
` : ''}
`}
href={currentSlide.href}
target={currentSlide.target}
>
<span className='sr-only'>{mainLabel}</span>
<div className='grid place-content-center h-full rounded-[inherit] outline outline-2 outline-black -outline-offset-2'>
<picture>
{currentSlide.imageSources?.map((source) => (
<source
key={source.media}
srcSet={source.srcSet}
media={source.media}
width={source?.width}
height={source?.height}
/>
))}
<img
className='block max-w-full size-auto'
src={currentSlide.image.src}
alt={currentSlide.image.alt}
width={currentSlide.image.width}
height={currentSlide.image.height}
/>
</picture>
<img
className='block max-w-full size-auto'
src={currentSlide.image.src}
srcSet={currentSlide.image.srcSet}
alt={currentSlide.image.alt}
width={currentSlide.image.width}
height={currentSlide.image.height}
/>
</div>
</a>
</div>
Expand All @@ -374,24 +341,14 @@ const CarouselPanelArea = (props: CarouselPanelAreaProps) => {
focus-visible:outline focus-visible:outline-4 focus-visible:outline-black focus-visible:outline-offset-[calc(2/16*1rem)] focus-visible:rounded-[calc(4/16*1rem)] focus-visible:ring-[calc(2/16*1rem)] focus-visible:ring-yellow-300
`}
>
<picture>
{nextSlide.imageSources?.map((source) => (
<source
key={source.media}
srcSet={source.srcSet}
media={source.media}
width={source?.width}
height={source?.height}
/>
))}
<img
className='block max-w-full size-auto'
src={nextSlide.image.src}
alt=''
width={nextSlide.image.width}
height={nextSlide.image.height}
/>
</picture>
<img
className='block max-w-full size-auto'
src={nextSlide.image.src}
srcSet={nextSlide.image.srcSet}
alt=''
width={nextSlide.image.width}
height={nextSlide.image.height}
/>

<span className='block border-t border-solid-gray-420 p-4 text-std-16B-170 decoration-inherit'>
次の{unit}
Expand All @@ -400,10 +357,7 @@ const CarouselPanelArea = (props: CarouselPanelAreaProps) => {
</p>

<div className='[grid-area:main] relative -z-10 overflow-clip'>
<CarouselBackgroundLayer
image={currentSlide.image}
imageSources={currentSlide.imageSources}
/>
<CarouselBackgroundLayer image={currentSlide.image} />
</div>

<div
Expand All @@ -412,7 +366,7 @@ const CarouselPanelArea = (props: CarouselPanelAreaProps) => {
group-has-[[open]]/carousel:!hidden @[64rem]:block
`}
>
<CarouselBackgroundLayer image={nextSlide.image} imageSources={nextSlide.imageSources} />
<CarouselBackgroundLayer image={nextSlide.image} />
</div>
</div>
);
Expand All @@ -435,6 +389,7 @@ export type CarouselProps = ComponentProps<'section'> & {
export const Carousel = (props: CarouselProps) => {
const {
className,
children,
slides,
currentIndex,
unit = 'スライド',
Expand All @@ -461,11 +416,12 @@ export const Carousel = (props: CarouselProps) => {
<section className={`@container group/carousel block ${className ?? ''}`} {...rest}>
<div
className={`
relative z-0 max-w-[calc(1440/16*1rem)] text-solid-gray-800 text-std-16N-170
relative z-0 max-w-[calc(1024/16*1rem)] text-solid-gray-800 text-std-16N-170
@[64rem]:px-12
`}
ref={innerRef}
>
{children}
<CarouselPanelArea
currentSlide={currentSlide}
nextSlide={nextSlide}
Expand Down Expand Up @@ -506,3 +462,4 @@ export const Carousel = (props: CarouselProps) => {
</section>
);
};

53 changes: 53 additions & 0 deletions src/components/Carousel/CarouselSingle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import type { ComponentProps } from 'react';

export type CarouselSingleProps = ComponentProps<'div'>;

export const CarouselSingle = (props: CarouselSingleProps) => {
const { className, children, ...rest } = props;
return (
<div className={`${className ?? ''}`} {...rest}>
{children}
</div>
);
};

export type CarouselSingleLinkProps = ComponentProps<'a'>;

export const CarouselSingleLink = (props: CarouselSingleLinkProps) => {
const { className, href, children, ...rest } = props;

if (href) {
return (
<a
className={`
relative block w-fit
after:absolute after:pointer-events-none
hover:outline hover:outline-4 hover:outline-blue-900 hover:-outline-offset-[calc(2/16*1rem)]
hover:after:inset-[2px] hover:after:ring-[calc(2/16*1rem)] hover:after:ring-inset hover:after:ring-white
focus-visible:overflow-hidden focus-visible:outline focus-visible:outline-4 focus-visible:outline-black focus-visible:-outline-offset-[calc(2/16*1rem)] focus-visible:rounded-8
focus-visible:after:inset-[2px] focus-visible:after:ring-[calc(2/16*1rem)] focus-visible:after:ring-inset focus-visible:after:ring-yellow-300 focus-visible:after:rounded-6 focus-visible:after:pointer-events-none
${className ?? ''}
`}
href={href}
{...rest}
>
{children}
</a>
);
}

return <span className={`relative block w-fit ${className ?? ''}`}>{children}</span>;
};

export type CarouselSingleImageProps = ComponentProps<'img'>;

export const CarouselSingleImage = (props: CarouselSingleImageProps) => {
const { className, alt, ...rest } = props;
return (
<img
className={`block max-w-full h-auto outline outline-2 outline-black -outline-offset-2 ${className ?? ''}`}
alt={alt}
{...rest}
/>
);
};
Binary file modified src/components/Carousel/carousel-sample-images/image-1.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/components/Carousel/carousel-sample-images/image-2.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/components/Carousel/carousel-sample-images/image-3.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/components/Carousel/carousel-sample-images/image-4.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions src/components/Carousel/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
export type { CarouselProps, CarouselSlide } from './Carousel';
export { Carousel } from './Carousel';
export type {
CarouselSingleImageProps,
CarouselSingleLinkProps,
CarouselSingleProps,
} from './CarouselSingle';
export { CarouselSingle, CarouselSingleImage, CarouselSingleLink } from './CarouselSingle';
2 changes: 1 addition & 1 deletion src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export {
export { Blockquote } from './Blockquote';
export { BreadcrumbItem, BreadcrumbList, Breadcrumbs, BreadcrumbsLabel } from './Breadcrumbs';
export { Button, buttonBaseStyle, buttonSizeStyle, buttonVariantStyle } from './Button';
export { Carousel } from './Carousel';
export { Carousel, CarouselSingle, CarouselSingleImage, CarouselSingleLink } from './Carousel';
export { Checkbox } from './Checkbox';
export { ChipLabel } from './ChipLabel';
export * from './DatePicker';
Expand Down
3 changes: 3 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export {
buttonSizeStyle,
buttonVariantStyle,
Carousel,
CarouselSingle,
CarouselSingleImage,
CarouselSingleLink,
Checkbox,
ChipLabel,
DatePicker,
Expand Down