Skip to content

Commit 8c965bd

Browse files
authored
Merge branch 'master' into chore/storybook9
2 parents 41faf51 + e8d6726 commit 8c965bd

File tree

2 files changed

+171
-0
lines changed

2 files changed

+171
-0
lines changed
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
import { Button, CarouselSlider, Image, makeStyles, tokens, typographyStyles } from '@fluentui/react-components';
2+
import {
3+
Carousel,
4+
CarouselAnnouncerFunction,
5+
CarouselCard,
6+
CarouselNav,
7+
CarouselNavButton,
8+
CarouselNavContainer,
9+
CarouselViewport,
10+
Text,
11+
} from '@fluentui/react-components';
12+
import * as React from 'react';
13+
14+
const useClasses = makeStyles({
15+
bannerCard: {
16+
alignContent: 'center',
17+
borderRadius: tokens.borderRadiusXLarge,
18+
boxShadow: tokens.shadow16,
19+
height: '450px',
20+
textAlign: 'left',
21+
position: 'relative',
22+
},
23+
image: {
24+
borderRadius: 'inherit',
25+
},
26+
cardContainer: {
27+
display: 'flex',
28+
flexDirection: 'column',
29+
gap: tokens.spacingHorizontalS,
30+
31+
position: 'absolute',
32+
left: '10%',
33+
top: '25%',
34+
borderRadius: tokens.borderRadiusLarge,
35+
boxShadow: tokens.shadow8,
36+
background: tokens.colorNeutralBackground1,
37+
padding: `${tokens.spacingHorizontalXXL} ${tokens.spacingVerticalXXXL}`,
38+
maxWidth: '270px',
39+
width: '50%',
40+
},
41+
title: {
42+
...typographyStyles.title3,
43+
},
44+
subtext: {
45+
marginBottom: tokens.spacingVerticalM,
46+
...typographyStyles.body1,
47+
},
48+
container: {
49+
display: 'grid',
50+
gridTemplateColumns: '1fr',
51+
gridTemplateRows: 'auto 1fr',
52+
},
53+
card: {
54+
minHeight: '100px',
55+
},
56+
carousel: {
57+
flex: 1,
58+
paddingBottom: tokens.spacingVerticalXL,
59+
},
60+
controls: {
61+
display: 'flex',
62+
flexDirection: 'column',
63+
gap: tokens.spacingVerticalSNudge,
64+
65+
padding: `${tokens.spacingHorizontalMNudge} ${tokens.spacingVerticalMNudge}`,
66+
},
67+
field: {
68+
flex: 1,
69+
gridTemplateColumns: 'minmax(100px, max-content) 1fr',
70+
},
71+
dropdown: {
72+
maxWidth: 'max-content',
73+
},
74+
carouselHeader: {
75+
display: 'flex',
76+
justifyContent: 'space-between',
77+
alignItems: 'center',
78+
gap: tokens.spacingVerticalSNudge,
79+
marginBottom: tokens.spacingHorizontalL,
80+
},
81+
carouselHeaderTitle: {
82+
flex: '1',
83+
margin: '0',
84+
fontSize: tokens.fontSizeBase600,
85+
fontWeight: tokens.fontWeightSemibold,
86+
},
87+
carouselNavigation: { width: 'fit-content', alignSelf: 'center', margin: '0' },
88+
slider: {
89+
gap: tokens.spacingVerticalXXL,
90+
padding: `0 ${tokens.spacingVerticalXXL}`,
91+
},
92+
});
93+
94+
const IMAGES = [
95+
'https://fabricweb.azureedge.net/fabric-website/assets/images/swatch-picker/sea-full-img.jpg',
96+
'https://fabricweb.azureedge.net/fabric-website/assets/images/swatch-picker/bridge-full-img.jpg',
97+
'https://fabricweb.azureedge.net/fabric-website/assets/images/swatch-picker/park-full-img.jpg',
98+
'https://fabricweb.azureedge.net/fabric-website/assets/images/swatch-picker/sea-full-img.jpg',
99+
'https://fabricweb.azureedge.net/fabric-website/assets/images/swatch-picker/bridge-full-img.jpg',
100+
'https://fabricweb.azureedge.net/fabric-website/assets/images/swatch-picker/park-full-img.jpg',
101+
];
102+
103+
const BannerCard: React.FC<{ children: React.ReactNode; imageSrc: string; index: number }> = props => {
104+
const { children, imageSrc, index } = props;
105+
const classes = useClasses();
106+
107+
return (
108+
<CarouselCard autoSize className={classes.bannerCard} aria-label={`${index + 1} of ${IMAGES.length}`}>
109+
<Image fit="cover" src={imageSrc} role="presentation" className={classes.image} />
110+
111+
<div className={classes.cardContainer}>
112+
<div className={classes.title}>{children}</div>
113+
<div className={classes.subtext}>
114+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
115+
magna aliqua. Ut enim ad minim veniam.
116+
</div>
117+
<div>
118+
<Button appearance="primary">Call to action</Button>
119+
</div>
120+
</div>
121+
</CarouselCard>
122+
);
123+
};
124+
125+
const getAnnouncement: CarouselAnnouncerFunction = (index: number, totalSlides: number, slideGroupList: number[][]) => {
126+
return `Carousel slide ${index + 1} of ${totalSlides}`;
127+
};
128+
129+
export const TopNavigation = (): React.ReactElement => {
130+
const classes = useClasses();
131+
132+
return (
133+
<div className={classes.container}>
134+
<div className={classes.card}>
135+
<Carousel circular draggable announcement={getAnnouncement} className={classes.carousel}>
136+
<div className={classes.carouselHeader}>
137+
<Text as="h1" className={classes.carouselHeaderTitle}>
138+
Carousel Title
139+
</Text>
140+
<CarouselNavContainer
141+
next={{ 'aria-label': 'go to next' }}
142+
prev={{ 'aria-label': 'go to prev' }}
143+
className={classes.carouselNavigation}
144+
>
145+
<CarouselNav>{index => <CarouselNavButton aria-label={`Carousel Nav Button ${index}`} />}</CarouselNav>
146+
</CarouselNavContainer>
147+
</div>
148+
<CarouselViewport>
149+
<CarouselSlider className={classes.slider}>
150+
{IMAGES.map((imageSrc, index) => (
151+
<BannerCard key={`image-${index}`} imageSrc={imageSrc} index={index}>
152+
Card {index + 1}
153+
</BannerCard>
154+
))}
155+
</CarouselSlider>
156+
</CarouselViewport>
157+
</Carousel>
158+
</div>
159+
</div>
160+
);
161+
};
162+
163+
TopNavigation.parameters = {
164+
docs: {
165+
description: {
166+
story:
167+
'Top navigation places carousel controls at the header so users can see the title, page position, and navigation in one line. This story shows the default variant with previous and next buttons and dot pagination using CarouselNav inside CarouselNavContainer.',
168+
},
169+
},
170+
};

packages/react-components/react-carousel/stories/src/Carousel/index.stories.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import descriptionMd from './CarouselDescription.md';
1515
import bestPracticesMd from './CarouselBestPractices.md';
1616

1717
export { Default } from './CarouselDefault.stories';
18+
export { TopNavigation } from './CarouselTopNavigation.stories';
1819
export { Responsive } from './CarouselResponsive.stories';
1920
export { Controlled } from './CarouselControlled.stories';
2021
export { ImageSlideshow } from './CarouselImageBox.stories';

0 commit comments

Comments
 (0)