Skip to content

Commit 6e8201c

Browse files
feat: implement the plymorphic lesson
1 parent e4b6b12 commit 6e8201c

File tree

31 files changed

+355
-24
lines changed

31 files changed

+355
-24
lines changed

β€Žsrc/course/01-introduction/01-Welcome.mdx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,13 @@ Each lesson is broken down in an exercise file and a final file. The exercise fi
4848

4949
#### πŸ₯ˆ Silver
5050

51-
- [Compound components pattern](?path=/docs/lessons-πŸ₯ˆ-sliver-compound-components-pattern-01-lesson--docs)
52-
- [Controlled component pattern](?path=/docs/lessons-πŸ₯ˆ-sliver-controlled-components-pattern-01-lesson--docs)
53-
- [Render props pattern](?path=/docs/lessons-πŸ₯ˆ-sliver-render-props-pattern-01-lesson--docs)
54-
- [The Provider pattern](?path=/docs/lessons-πŸ₯ˆ-sliver-provider-pattern-01-lesson--docs)
55-
- [The State Reducer pattern](?path=/docs/lessons-πŸ₯ˆ-sliver-state-reducer-pattern-01-lesson--docs)
56-
- [Portals pattern](?path=/docs/lessons-πŸ₯ˆ-sliver-portals-01-lesson--docs)
51+
- [Compound components pattern](?path=/docs/lessons-πŸ₯ˆ-Silver-compound-components-pattern-01-lesson--docs)
52+
- [Controlled component pattern](?path=/docs/lessons-πŸ₯ˆ-Silver-controlled-components-pattern-01-lesson--docs)
53+
- [Render props pattern](?path=/docs/lessons-πŸ₯ˆ-Silver-render-props-pattern-01-lesson--docs)
54+
- [The Provider pattern](?path=/docs/lessons-πŸ₯ˆ-Silver-provider-pattern-01-lesson--docs)
55+
- [The State Reducer pattern](?path=/docs/lessons-πŸ₯ˆ-Silver-state-reducer-pattern-01-lesson--docs)
56+
- [Portals pattern](?path=/docs/lessons-πŸ₯ˆ-Silver-portals-01-lesson--docs)
57+
- [Polymorphic components pattern](?path=/docs/lessons-πŸ₯ˆ-silver-polymorphic-components-01-lesson--docs)
5758

5859
#### πŸ₯‡ Gold
5960

β€Žsrc/course/02- lessons/02-Silver/Compound/exercise/exercise.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { Meta, StoryObj } from '@storybook/react';
33
import { Exercise } from './exercise';
44

55
const meta: Meta<typeof Exercise> = {
6-
title: 'Lessons/πŸ₯ˆ Sliver/Compound Components Pattern/02-Exercise',
6+
title: 'Lessons/πŸ₯ˆ Silver/Compound Components Pattern/02-Exercise',
77
component: Exercise
88
};
99

β€Žsrc/course/02- lessons/02-Silver/Compound/final/final.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { Meta, StoryObj } from '@storybook/react';
33
import { Final } from './final';
44

55
const meta: Meta<typeof Final> = {
6-
title: 'Lessons/πŸ₯ˆ Sliver/Compound Components Pattern/03-Final',
6+
title: 'Lessons/πŸ₯ˆ Silver/Compound Components Pattern/03-Final',
77
component: Final
88
};
99

β€Žsrc/course/02- lessons/02-Silver/Compound/lesson.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Meta } from '@storybook/blocks';
22

3-
<Meta title="Lessons/πŸ₯ˆ Sliver/Compound Components Pattern/01-Lesson" />
3+
<Meta title="Lessons/πŸ₯ˆ Silver/Compound Components Pattern/01-Lesson" />
44

55
# Compound Components Pattern
66

β€Žsrc/course/02- lessons/02-Silver/Controlled/exercise/exercise.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Exercise } from './exercise';
44

55
const meta: Meta<typeof Exercise> = {
66
title:
7-
'Lessons/πŸ₯ˆ Sliver/Controlled Components Pattern/02-Exercise',
7+
'Lessons/πŸ₯ˆ Silver/Controlled Components Pattern/02-Exercise',
88
component: Exercise
99
};
1010

β€Žsrc/course/02- lessons/02-Silver/Controlled/final/final.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { Meta, StoryObj } from '@storybook/react';
33
import { Final } from './final';
44

55
const meta: Meta<typeof Final> = {
6-
title: 'Lessons/πŸ₯ˆ Sliver/Controlled Components Pattern/03-Final',
6+
title: 'Lessons/πŸ₯ˆ Silver/Controlled Components Pattern/03-Final',
77
component: Final
88
};
99

β€Žsrc/course/02- lessons/02-Silver/Controlled/lesson.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Meta } from '@storybook/blocks';
22

3-
<Meta title="Lessons/πŸ₯ˆ Sliver/Controlled Components Pattern/01-Lesson" />
3+
<Meta title="Lessons/πŸ₯ˆ Silver/Controlled Components Pattern/01-Lesson" />
44

55
# Controlled Components Pattern
66

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import type { Meta, StoryObj } from '@storybook/react';
2+
3+
import { Exercise } from './exercise';
4+
5+
const meta: Meta<typeof Exercise> = {
6+
title: 'Lessons/πŸ₯ˆ Silver/Polymorphic Components/02-Exercise',
7+
component: Exercise
8+
};
9+
10+
export default meta;
11+
type Story = StoryObj<typeof Exercise>;
12+
13+
/*
14+
* See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas
15+
* to learn more about using the canvasElement to query the DOM
16+
*/
17+
export const Default: Story = {
18+
play: async () => {},
19+
args: {}
20+
};
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { HTMLAttributes } from 'react';
2+
3+
/**
4+
* Exercise: Refactor the Heading component to correctly use the polymorphic pattern.
5+
*
6+
* πŸ€” Observations of this file
7+
* In the current component you can see that the as prop is a string so if a developer in a team uses the wrong element they would just get the h2 element.
8+
* Font sizes are clearly defined to the element so there is no flexibility in sizes which can lead to developers pleasing designers but... breaking accessibility or vice versa where designs do not look the same as what was provided.
9+
*
10+
* We need to tackle this in stages...
11+
*
12+
* Stage one - Refactoring the component to use Polymorphic style so we remove the switch statement.
13+
* Stage two - decouple the font size to the element
14+
* Stage three - allow for developers to have a size medium breakpoint for special designs.
15+
*
16+
*/
17+
18+
// πŸ§‘πŸ»β€πŸ’» 1.a - Create a type called allowedHTMLElements
19+
20+
// πŸ§‘πŸ»β€πŸ’» 2.a - Create a type called FontSizes and it's a union of 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl'
21+
22+
interface IHeading extends HTMLAttributes<HTMLHeadingElement> {
23+
// πŸ§‘πŸ»β€πŸ’» 1.b - Update the type of string to be the type you defined as part of 1.a
24+
as?: string;
25+
// πŸ§‘πŸ»β€πŸ’» 2.b - Create a new prop called size?: FontSizes;
26+
// πŸ§‘πŸ»β€πŸ’» 3.a - Create a new prop called sizeMd?: FontSizes;
27+
children?: React.ReactNode | React.ReactNode[];
28+
}
29+
30+
const Heading = ({
31+
// πŸ§‘πŸ»β€πŸ’» 1.c - add : Element = 'h2' what this will do is redefine the prop to be a capital variable which can be used as a React Component.
32+
as = 'h2',
33+
// πŸ§‘πŸ»β€πŸ’» 2.c - Create a new prop called size
34+
// πŸ§‘πŸ»β€πŸ’» 3.b - Create a new prop called sizeMd
35+
children,
36+
...rest
37+
}: IHeading) => {
38+
// πŸ§‘πŸ»β€πŸ’» 1.d - Create a variable called elementFontSize which uses useMemo to return a string from an object key mapping. For example: useMemo(() => ({ h1: 'text-3xl' }[Element]), [Element]);
39+
// πŸ§‘πŸ»β€πŸ’» 2.d - In the useMemo add the size as a dependency and then check if size exists. If it does, return `text-${size}` if not, return what was there previously. Move onto 3.a.
40+
41+
// πŸ§‘πŸ»β€πŸ’» 3.c - create another useMemo for largeFontSizes where we find an array of md:text-(sm-3xl) and we need to "find" which one in that array "includes" sizeMd props value.
42+
43+
// πŸ§ͺ 3.d Head down to the storybook Exercise Component and add a few more variants in.
44+
45+
// πŸ§‘πŸ»β€πŸ’» 1.e return the Element with the className={classNames('mb-3 font-semibold', elementFontSize)} don't forget the ...rest
46+
// πŸ’£ 1.f remove the old code below. Move onto step 2.a.
47+
if (as)
48+
switch (as) {
49+
case 'h1':
50+
return (
51+
<h1 {...rest} className="text-3xl mb-3 font-semibold">
52+
{children}
53+
</h1>
54+
);
55+
case 'h3':
56+
return (
57+
<h3 {...rest} className="text-xl mb-3 font-semibold">
58+
{children}
59+
</h3>
60+
);
61+
case 'h4':
62+
return (
63+
<h4 {...rest} className="text-lg mb-3 font-semibold">
64+
{children}
65+
</h4>
66+
);
67+
case 'h5':
68+
return (
69+
<h5 {...rest} className="text-md mb-3 font-semibold">
70+
{children}
71+
</h5>
72+
);
73+
case 'h6':
74+
return (
75+
<h6 {...rest} className="text-sm mb-3 font-semibold">
76+
{children}
77+
</h6>
78+
);
79+
default:
80+
return (
81+
<h2 {...rest} className="text-2xl mb-3 font-semibold">
82+
{children}
83+
</h2>
84+
);
85+
}
86+
};
87+
88+
export const Exercise = () => (
89+
<article>
90+
<Heading as="h1">Heading One</Heading>
91+
<Heading as="h2">Heading Two</Heading>
92+
<Heading as="h3">Heading Three</Heading>
93+
<Heading as="h4">Heading Four</Heading>
94+
<Heading as="h5">Heading Five</Heading>
95+
<Heading as="h6">Heading Six</Heading>
96+
{/* 3.e πŸ‘¨πŸ»β€πŸ’» Implement a heading as h2 and size sm */}
97+
98+
{/* 3.e πŸ‘¨πŸ»β€πŸ’» Implement a heading as h2 and size sm and sizeMd is 3xl */}
99+
100+
{/* 3.e πŸ‘¨πŸ»β€πŸ’» Implement a heading as h2 and sizeMd is 3xl */}
101+
</article>
102+
);
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import type { Meta, StoryObj } from '@storybook/react';
2+
3+
import { Final } from './final';
4+
5+
const meta: Meta<typeof Final> = {
6+
title: 'Lessons/πŸ₯ˆ Silver/Polymorphic Components/03-Final',
7+
component: Final
8+
};
9+
10+
export default meta;
11+
type Story = StoryObj<typeof Final>;
12+
13+
/*
14+
* See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas
15+
* to learn more about using the canvasElement to query the DOM
16+
*/
17+
export const Default: Story = {
18+
play: async () => {},
19+
args: {}
20+
};

0 commit comments

Comments
Β (0)