@codecademy/styleguide 78.5.5-alpha.7e2d80.0 → 78.5.5-alpha.86d3e6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.storybook/components/index.tsx +0 -1
- package/CHANGELOG.md +1 -1
- package/package.json +2 -2
- package/src/lib/Atoms/SkipToContent/SkipToContent.mdx +5 -4
- package/src/lib/Molecules/Coachmark/Coachmark.mdx +6 -0
- package/src/lib/Molecules/Coachmark/Coachmark.stories.tsx +37 -1
- package/src/lib/Molecules/Flyout/Flyout.mdx +2 -2
- package/src/lib/Molecules/Modals/Modal/Modal.mdx +12 -2
- package/src/lib/Molecules/Modals/Overlay/Overlay.mdx +6 -0
- package/src/lib/Molecules/Modals/Overlay/Overlay.stories.tsx +67 -2
- package/src/lib/Molecules/Tabs/Tabs.mdx +2 -2
- package/src/lib/Molecules/Tips/InfoTip/InfoTip.mdx +26 -11
- package/src/lib/Molecules/Tips/InfoTip/InfoTip.stories.tsx +73 -10
- package/src/lib/Molecules/Tips/PreviewTip/PreviewTip.mdx +6 -0
- package/src/lib/Molecules/Tips/PreviewTip/PreviewTip.stories.tsx +68 -1
- package/src/lib/Molecules/Tips/ToolTip/ToolTip.mdx +6 -0
- package/src/lib/Molecules/Tips/ToolTip/ToolTip.stories.tsx +59 -0
- package/.storybook/components/Elements/KeyboardKey.tsx +0 -17
|
@@ -2,7 +2,6 @@ export * from './ImageWrapper';
|
|
|
2
2
|
export * from './TokenTable';
|
|
3
3
|
export * from './Headers';
|
|
4
4
|
export * from './Elements/Callout';
|
|
5
|
-
export * from './Elements/KeyboardKey';
|
|
6
5
|
export * from './Elements/Markdown';
|
|
7
6
|
export * from './Elements/ImageGallery';
|
|
8
7
|
export * from './Scales/ColorScale';
|
package/CHANGELOG.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
-
### [78.5.5-alpha.
|
|
6
|
+
### [78.5.5-alpha.86d3e6.0](https://github.com/Codecademy/gamut/compare/@codecademy/styleguide@78.5.4...@codecademy/styleguide@78.5.5-alpha.86d3e6.0) (2026-01-06)
|
|
7
7
|
|
|
8
8
|
**Note:** Version bump only for package @codecademy/styleguide
|
|
9
9
|
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codecademy/styleguide",
|
|
3
3
|
"description": "Styleguide & Component library for codecademy.com",
|
|
4
|
-
"version": "78.5.5-alpha.
|
|
4
|
+
"version": "78.5.5-alpha.86d3e6.0",
|
|
5
5
|
"author": "Codecademy Engineering",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
|
10
10
|
"repository": "git@github.com:Codecademy/gamut.git",
|
|
11
|
-
"gitHead": "
|
|
11
|
+
"gitHead": "2988ef3b1571897c2359c9031389d08356b819be"
|
|
12
12
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Canvas, Controls, Meta } from '@storybook/blocks';
|
|
2
2
|
|
|
3
|
-
import { ComponentHeader
|
|
3
|
+
import { ComponentHeader } from '~styleguide/blocks';
|
|
4
4
|
|
|
5
5
|
import * as SkipToContentStories from './SkipToContent.stories';
|
|
6
6
|
|
|
@@ -21,10 +21,11 @@ export const parameters = {
|
|
|
21
21
|
|
|
22
22
|
## Usage
|
|
23
23
|
|
|
24
|
-
Use `<SkipToContent />` to add a hidden-by-default link that becomes visible when the user <
|
|
24
|
+
Use `<SkipToContent />` to add a hidden-by-default link that becomes visible when the user <kbd>Tab</kbd>s over it (gives it focus).
|
|
25
25
|
It takes in the ID of the element it will scroll to and focus ([dev.to article explaining why](https://dev.to/robdodson/managing-focus-64l)) on click (via mouse or keyboard).
|
|
26
26
|
|
|
27
|
-
This type of control is necessary for pages that have a bunch of stuff keyboard users would have to
|
|
27
|
+
This type of control is necessary for pages that have a bunch of stuff keyboard users would have to Tab through to get
|
|
28
|
+
to the page's main content (like navigations).
|
|
28
29
|
|
|
29
30
|
For this element to work properly, there must be a `<SkipToContentTarget />` component with the id passed into this component for the `contentId` prop. The `<SkipToContentTarget />` component by default has a `tabIndex` of -1.
|
|
30
31
|
Example:
|
|
@@ -42,7 +43,7 @@ Example:
|
|
|
42
43
|
</div>
|
|
43
44
|
```
|
|
44
45
|
|
|
45
|
-
To see it, keep
|
|
46
|
+
To see it, keep tabbing around on this page or visit [the catalog](https://www.codecademy.com/catalog/language/javascript) and navigate via tab to see it in action.
|
|
46
47
|
|
|
47
48
|
## Playground
|
|
48
49
|
|
|
@@ -94,6 +94,12 @@ Using `popoverProps`, you can customize the look of the rendered popover. For ex
|
|
|
94
94
|
|
|
95
95
|
<Canvas of={CoachmarkStories.Customized} />
|
|
96
96
|
|
|
97
|
+
### Z-Index
|
|
98
|
+
|
|
99
|
+
You can customize the `zIndex` of the Coachmark's popover by passing `zIndex` through `popoverProps`. This is useful when the popover needs to appear above other positioned elements.
|
|
100
|
+
|
|
101
|
+
<Canvas of={CoachmarkStories.ZIndex} />
|
|
102
|
+
|
|
97
103
|
## Playground
|
|
98
104
|
|
|
99
105
|
<Canvas sourceState="shown" of={CoachmarkStories.Default} />
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Coachmark, FillButton, FlexBox, Text } from '@codecademy/gamut';
|
|
1
|
+
import { Box, Coachmark, FillButton, FlexBox, Text } from '@codecademy/gamut';
|
|
2
2
|
import * as patterns from '@codecademy/gamut-patterns';
|
|
3
3
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
4
4
|
import { ComponentProps, useEffect, useState } from 'react';
|
|
@@ -197,3 +197,39 @@ export const Customized: Story = {
|
|
|
197
197
|
);
|
|
198
198
|
},
|
|
199
199
|
};
|
|
200
|
+
|
|
201
|
+
export const ZIndex: Story = {
|
|
202
|
+
args: {
|
|
203
|
+
popoverProps: {
|
|
204
|
+
position: 'below',
|
|
205
|
+
zIndex: 5,
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
render: function ZIndexExample(args) {
|
|
209
|
+
const [shouldShow, setShouldShow] = useState(true);
|
|
210
|
+
|
|
211
|
+
return (
|
|
212
|
+
<FlexBox flexDirection="column" gap={16}>
|
|
213
|
+
<Box bg="paleBlue" p={16} zIndex={3} position="relative">
|
|
214
|
+
Element with z-index: 3
|
|
215
|
+
</Box>
|
|
216
|
+
<Coachmark
|
|
217
|
+
{...args}
|
|
218
|
+
renderPopover={() => (
|
|
219
|
+
<FlexBox alignItems="flex-start" flexDirection="column" p={16}>
|
|
220
|
+
<Text mb={8}>This coachmark has z-index: 5 via popoverProps</Text>
|
|
221
|
+
<FillButton size="small" onClick={() => setShouldShow(false)}>
|
|
222
|
+
Got it
|
|
223
|
+
</FillButton>
|
|
224
|
+
</FlexBox>
|
|
225
|
+
)}
|
|
226
|
+
shouldShow={shouldShow}
|
|
227
|
+
>
|
|
228
|
+
<FillButton onClick={() => setShouldShow(true)}>
|
|
229
|
+
Show Coachmark
|
|
230
|
+
</FillButton>
|
|
231
|
+
</Coachmark>
|
|
232
|
+
</FlexBox>
|
|
233
|
+
);
|
|
234
|
+
},
|
|
235
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Canvas, Controls, Meta } from '@storybook/blocks';
|
|
2
2
|
|
|
3
|
-
import { ComponentHeader,
|
|
3
|
+
import { ComponentHeader, LinkTo } from '~styleguide/blocks';
|
|
4
4
|
|
|
5
5
|
import * as FlyoutStories from './Flyout.stories';
|
|
6
6
|
|
|
@@ -25,7 +25,7 @@ export const parameters = {
|
|
|
25
25
|
|
|
26
26
|
## Usage
|
|
27
27
|
|
|
28
|
-
On button click, a container animates in from the left or right side of the window. Flyout can be configured to close by pressing the
|
|
28
|
+
On button click, a container animates in from the left or right side of the window. Flyout can be configured to close by pressing the “X” close icon, pressing they “esc” key, and/or clicking outside of the container.
|
|
29
29
|
|
|
30
30
|
Internally, Flyout is a combination of <LinkTo id="Molecules/Modals/Overlay">Overlay</LinkTo> and <LinkTo id="Atoms/Drawer">Drawer</LinkTo>.
|
|
31
31
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Canvas, Controls, Meta } from '@storybook/blocks';
|
|
2
2
|
|
|
3
|
-
import { ComponentHeader
|
|
3
|
+
import { ComponentHeader } from '~styleguide/blocks';
|
|
4
4
|
|
|
5
5
|
import * as ModalStories from './Modal.stories';
|
|
6
6
|
|
|
@@ -77,7 +77,7 @@ If the close button is hidden, you will need to create a custom way to close the
|
|
|
77
77
|
Other than creating buttons that can close the Modal, there are other ways a Modal can be closed by the user.
|
|
78
78
|
|
|
79
79
|
1. Clicking the content outside of the Modal
|
|
80
|
-
2.
|
|
80
|
+
2. Clicking the escape key on their keyboard
|
|
81
81
|
|
|
82
82
|
All of these methods default to `true` for accessibility reasons, and rely on setting the required `onRequestClose` prop and making sure it toggles the `isOpen` prop on the Modal.
|
|
83
83
|
|
|
@@ -89,6 +89,16 @@ A Modal can be made scrollable by including large content inside.
|
|
|
89
89
|
|
|
90
90
|
<Canvas of={ModalStories.Scrollable} />
|
|
91
91
|
|
|
92
|
+
## Z-Index
|
|
93
|
+
|
|
94
|
+
Modal accepts a `zIndex` prop (defaults to `3`) that controls the stacking order of its underlying Overlay. Use this when the modal needs to appear above other positioned elements like sticky headers or custom floating UI.
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
<Modal zIndex={10} isOpen={isOpen} onRequestClose={handleClose}>
|
|
98
|
+
Content that needs to appear above other positioned elements
|
|
99
|
+
</Modal>
|
|
100
|
+
```
|
|
101
|
+
|
|
92
102
|
## Focus management
|
|
93
103
|
|
|
94
104
|
The `containerFocusRef` prop allows you to programmatically control focus on the Modal container. This is useful for advanced focus management scenarios where you need to override the default focus behavior (the Modal has `data-autofocus` by default).
|
|
@@ -32,6 +32,12 @@ Unlike the legacy `Modal` implementations in the monolith, this:
|
|
|
32
32
|
|
|
33
33
|
- If you need styles such as a background behind content, see `Modal` for general modals and `Dialog` for confirmation flows.
|
|
34
34
|
|
|
35
|
+
## Z-Index
|
|
36
|
+
|
|
37
|
+
The `zIndex` prop controls the stacking order of the overlay. It defaults to `3`, which places it above most common UI elements. Increase this value when the overlay needs to appear above other positioned elements like sticky headers or floating UI.
|
|
38
|
+
|
|
39
|
+
<Canvas of={OverlayStories.ZIndex} />
|
|
40
|
+
|
|
35
41
|
## Playground
|
|
36
42
|
|
|
37
43
|
<Canvas sourceState="shown" of={OverlayStories.Default} />
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { FillButton, FlexBox, Overlay, Text } from '@codecademy/gamut';
|
|
2
|
-
import type { Meta } from '@storybook/react';
|
|
1
|
+
import { Box, FillButton, FlexBox, Overlay, Text } from '@codecademy/gamut';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
3
|
import { useEffect, useState } from 'react';
|
|
4
4
|
|
|
5
5
|
const meta: Meta<typeof Overlay> = {
|
|
@@ -8,6 +8,7 @@ const meta: Meta<typeof Overlay> = {
|
|
|
8
8
|
};
|
|
9
9
|
|
|
10
10
|
export default meta;
|
|
11
|
+
type Story = StoryObj<typeof Overlay>;
|
|
11
12
|
|
|
12
13
|
export const Default: React.FC<React.ComponentProps<typeof Overlay>> = (
|
|
13
14
|
args
|
|
@@ -34,3 +35,67 @@ export const Default: React.FC<React.ComponentProps<typeof Overlay>> = (
|
|
|
34
35
|
</>
|
|
35
36
|
);
|
|
36
37
|
};
|
|
38
|
+
|
|
39
|
+
export const ZIndex: Story = {
|
|
40
|
+
render: function ZIndexExample() {
|
|
41
|
+
const [defaultOpen, setDefaultOpen] = useState(false);
|
|
42
|
+
const [customOpen, setCustomOpen] = useState(false);
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<FlexBox flexDirection="column" gap={16}>
|
|
46
|
+
<FlexBox gap={16}>
|
|
47
|
+
<FillButton onClick={() => setDefaultOpen(true)}>
|
|
48
|
+
Open Overlay (default z-index: 3)
|
|
49
|
+
</FillButton>
|
|
50
|
+
<FillButton onClick={() => setCustomOpen(true)}>
|
|
51
|
+
Open Overlay (z-index: 10)
|
|
52
|
+
</FillButton>
|
|
53
|
+
</FlexBox>
|
|
54
|
+
|
|
55
|
+
<Box position="relative" height="100px">
|
|
56
|
+
<Box
|
|
57
|
+
position="absolute"
|
|
58
|
+
top={0}
|
|
59
|
+
left={0}
|
|
60
|
+
bg="paleYellow"
|
|
61
|
+
p={16}
|
|
62
|
+
zIndex={5}
|
|
63
|
+
>
|
|
64
|
+
<Text>Element with z-index: 5</Text>
|
|
65
|
+
</Box>
|
|
66
|
+
</Box>
|
|
67
|
+
|
|
68
|
+
<Overlay
|
|
69
|
+
isOpen={defaultOpen}
|
|
70
|
+
onRequestClose={() => setDefaultOpen(false)}
|
|
71
|
+
shroud
|
|
72
|
+
>
|
|
73
|
+
<FlexBox bg="white" p={24} borderRadius="md" flexDirection="column" gap={16}>
|
|
74
|
+
<Text>
|
|
75
|
+
This overlay uses the default z-index of 3.
|
|
76
|
+
<br />
|
|
77
|
+
It may appear behind elements with higher z-index values.
|
|
78
|
+
</Text>
|
|
79
|
+
<FillButton onClick={() => setDefaultOpen(false)}>Close</FillButton>
|
|
80
|
+
</FlexBox>
|
|
81
|
+
</Overlay>
|
|
82
|
+
|
|
83
|
+
<Overlay
|
|
84
|
+
isOpen={customOpen}
|
|
85
|
+
onRequestClose={() => setCustomOpen(false)}
|
|
86
|
+
shroud
|
|
87
|
+
zIndex={10}
|
|
88
|
+
>
|
|
89
|
+
<FlexBox bg="white" p={24} borderRadius="md" flexDirection="column" gap={16}>
|
|
90
|
+
<Text>
|
|
91
|
+
This overlay uses z-index: 10.
|
|
92
|
+
<br />
|
|
93
|
+
It will appear above the yellow element with z-index: 5.
|
|
94
|
+
</Text>
|
|
95
|
+
<FillButton onClick={() => setCustomOpen(false)}>Close</FillButton>
|
|
96
|
+
</FlexBox>
|
|
97
|
+
</Overlay>
|
|
98
|
+
</FlexBox>
|
|
99
|
+
);
|
|
100
|
+
},
|
|
101
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Canvas, Controls, Meta } from '@storybook/blocks';
|
|
2
2
|
|
|
3
|
-
import { ComponentHeader,
|
|
3
|
+
import { ComponentHeader, LinkTo } from '~styleguide/blocks';
|
|
4
4
|
|
|
5
5
|
import * as TabStories from './Tabs.stories';
|
|
6
6
|
|
|
@@ -67,7 +67,7 @@ It is recommended to add a unique `aria-label` to the `TabNav` component, to dif
|
|
|
67
67
|
|
|
68
68
|
### Tabs with interactive content
|
|
69
69
|
|
|
70
|
-
Normally, when you navigate to the contents of a `TabPanel` using the <
|
|
70
|
+
Normally, when you navigate to the contents of a `TabPanel` using the <kbd>tab</kbd> key or arrow keys, the entire section of the `TabPanel` will be in focus.
|
|
71
71
|
|
|
72
72
|
However, if you have tabs with interactive content within them (such as a button or link), and tab into the `TabPanel`, the focus will be on the interactive content and not the entirety of the `TabPanel`.
|
|
73
73
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Canvas, Controls, Meta } from '@storybook/blocks';
|
|
2
2
|
|
|
3
|
-
import { ComponentHeader
|
|
3
|
+
import { ComponentHeader } from '~styleguide/blocks';
|
|
4
4
|
|
|
5
5
|
import * as InfoTipStories from './InfoTip.stories';
|
|
6
6
|
|
|
@@ -25,7 +25,7 @@ export const parameters = {
|
|
|
25
25
|
|
|
26
26
|
## Usage
|
|
27
27
|
|
|
28
|
-
A tip is triggered by clicking on an information icon button and can be closed by clicking outside, pressing <
|
|
28
|
+
A tip is triggered by clicking on an information icon button and can be closed by clicking outside, pressing <kbd>Esc</kbd>, or clicking the info button again.
|
|
29
29
|
|
|
30
30
|
Use an infotip to provide additional info about a nearby element or content.
|
|
31
31
|
|
|
@@ -65,9 +65,9 @@ Links or buttons within InfoTips should be used sparingly and only when the info
|
|
|
65
65
|
|
|
66
66
|
When using `placement="floating"`, InfoTips implements focus management for easier navigation:
|
|
67
67
|
|
|
68
|
-
-
|
|
69
|
-
-
|
|
70
|
-
-
|
|
68
|
+
- **Tab**: Navigate forward through focusable elements (links, buttons) inside the tip. When reaching the last element, wraps back to the InfoTip button for convenience
|
|
69
|
+
- **Shift+Tab**: Navigate backward naturally through the page
|
|
70
|
+
- **Escape**: Closes the tip and returns focus to the InfoTip button
|
|
71
71
|
|
|
72
72
|
<Canvas of={InfoTipStories.KeyboardNavigation} />
|
|
73
73
|
|
|
@@ -75,16 +75,31 @@ When using `placement="floating"`, InfoTips implements focus management for easi
|
|
|
75
75
|
|
|
76
76
|
InfoTips have intelligent Escape key handling that works correctly both inside and outside Modals:
|
|
77
77
|
|
|
78
|
-
- **InfoTips close on
|
|
79
|
-
- **InfoTips inside Modals close first** - When an InfoTip is placed inside a Modal, pressing
|
|
80
|
-
- **Layered navigation** - After closing an InfoTip inside a Modal, pressing
|
|
81
|
-
- **Modals take priority over external InfoTips** - InfoTips detect when `dialog[open]`, `role="dialog"`, or `role="alertdialog"` elements are present and defer
|
|
78
|
+
- **InfoTips close on Escape** regardless of where keyboard focus is, and focus returns to the InfoTip button
|
|
79
|
+
- **InfoTips inside Modals close first** - When an InfoTip is placed inside a Modal, pressing Escape closes the InfoTip while keeping the Modal open
|
|
80
|
+
- **Layered navigation** - After closing an InfoTip inside a Modal, pressing Escape again closes the Modal
|
|
81
|
+
- **Modals take priority over external InfoTips** - InfoTips detect when `dialog[open]`, `role="dialog"`, or `role="alertdialog"` elements are present and defer Escape handling to them when the InfoTip is outside the Modal
|
|
82
82
|
|
|
83
83
|
<Canvas of={InfoTipStories.InfoTipInsideModal} />
|
|
84
84
|
|
|
85
|
-
##
|
|
85
|
+
## Custom Accessible Labeling
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
Provide either `ariaLabel` or `ariaLabelledby` to ensure screen reader users understand the purpose of the InfoTip button.
|
|
88
|
+
|
|
89
|
+
The InfoTip button's accessible label can be customized using either prop:
|
|
90
|
+
|
|
91
|
+
- **`ariaLabel`**: Directly sets the accessible label text. Useful when you want to provide a custom label without referencing another element.
|
|
92
|
+
- **`ariaLabelledby`**: References the ID of another element to use as the label. Useful when you want the InfoTip button to be labeled by visible text elsewhere on the page. This is useful for when the `InfoTip` is beside text that contextualizes it.
|
|
93
|
+
|
|
94
|
+
### Custom Role Description
|
|
95
|
+
|
|
96
|
+
The `InfoTipButton` uses [`aria-roledescription="More information button"`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-roledescription) to provide additional context to screen reader users about the button's specific purpose.
|
|
97
|
+
|
|
98
|
+
<Canvas of={InfoTipStories.AriaLabel} />
|
|
99
|
+
|
|
100
|
+
## Z-Index
|
|
101
|
+
|
|
102
|
+
You can customize the `zIndex` of the InfoTip's portal with the `zIndex` prop. This works for both `inline` and `floating` placements, and is useful when the tip needs to appear above other positioned elements.
|
|
88
103
|
|
|
89
104
|
<Canvas of={InfoTipStories.ZIndex} />
|
|
90
105
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Anchor,
|
|
3
3
|
Box,
|
|
4
|
+
Coachmark,
|
|
4
5
|
FillButton,
|
|
5
6
|
FlexBox,
|
|
6
7
|
GridBox,
|
|
@@ -195,6 +196,7 @@ export const InfoTipInsideModal: Story = {
|
|
|
195
196
|
},
|
|
196
197
|
render: function InfoTipInsideModal(args) {
|
|
197
198
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
199
|
+
const [showCoachmark, setShowCoachmark] = useState(false);
|
|
198
200
|
|
|
199
201
|
return (
|
|
200
202
|
<FlexBox center flexDirection="column" gap={16} py={64}>
|
|
@@ -233,6 +235,37 @@ export const InfoTipInsideModal: Story = {
|
|
|
233
235
|
closing the modal itself. Inline placement works correctly.
|
|
234
236
|
</Text>
|
|
235
237
|
|
|
238
|
+
<FlexBox alignItems="center" borderTop={1} gap={8} mt={8} pt={16}>
|
|
239
|
+
<Text id="modal-coachmark-text">
|
|
240
|
+
This modal also contains a Coachmark
|
|
241
|
+
</Text>
|
|
242
|
+
<Coachmark
|
|
243
|
+
popoverProps={{ zIndex: 3 }}
|
|
244
|
+
renderPopover={() => (
|
|
245
|
+
<FlexBox
|
|
246
|
+
alignItems="flex-start"
|
|
247
|
+
flexDirection="column"
|
|
248
|
+
p={16}
|
|
249
|
+
>
|
|
250
|
+
<Text mb={8}>
|
|
251
|
+
This Coachmark is inside a Modal. Try pressing Escape!
|
|
252
|
+
</Text>
|
|
253
|
+
<FillButton
|
|
254
|
+
size="small"
|
|
255
|
+
onClick={() => setShowCoachmark(false)}
|
|
256
|
+
>
|
|
257
|
+
Got it
|
|
258
|
+
</FillButton>
|
|
259
|
+
</FlexBox>
|
|
260
|
+
)}
|
|
261
|
+
shouldShow={showCoachmark}
|
|
262
|
+
>
|
|
263
|
+
<FillButton size="small" onClick={() => setShowCoachmark(true)}>
|
|
264
|
+
Show Coachmark
|
|
265
|
+
</FillButton>
|
|
266
|
+
</Coachmark>
|
|
267
|
+
</FlexBox>
|
|
268
|
+
|
|
236
269
|
<FillButton onClick={() => setIsModalOpen(false)}>
|
|
237
270
|
Close Modal
|
|
238
271
|
</FillButton>
|
|
@@ -245,19 +278,49 @@ export const InfoTipInsideModal: Story = {
|
|
|
245
278
|
|
|
246
279
|
export const ZIndex: Story = {
|
|
247
280
|
args: {
|
|
248
|
-
info: 'I
|
|
281
|
+
info: 'I have a custom z-index',
|
|
249
282
|
zIndex: 5,
|
|
250
283
|
},
|
|
251
284
|
render: (args) => (
|
|
252
|
-
<FlexBox center flexDirection="column" m={24} py={64}>
|
|
253
|
-
<
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
285
|
+
<FlexBox center flexDirection="column" gap={16} m={24} py={64}>
|
|
286
|
+
<Text variant="p-small">Inline placement:</Text>
|
|
287
|
+
<FlexBox alignItems="center" gap={8}>
|
|
288
|
+
<Box bg="paleBlue" p={8} zIndex={3} position="relative">
|
|
289
|
+
z-index: 3
|
|
290
|
+
</Box>
|
|
291
|
+
<InfoTip ariaLabel="inline default" info="Default z-index (inline)" />
|
|
292
|
+
<Box bg="paleBlue" p={8} zIndex={3} position="relative">
|
|
293
|
+
z-index: 3
|
|
294
|
+
</Box>
|
|
295
|
+
<InfoTip
|
|
296
|
+
{...args}
|
|
297
|
+
ariaLabel="inline custom"
|
|
298
|
+
info="z-index: 5 (inline)"
|
|
299
|
+
/>
|
|
300
|
+
</FlexBox>
|
|
301
|
+
|
|
302
|
+
<Text variant="p-small" mt={24}>
|
|
303
|
+
Floating placement:
|
|
304
|
+
</Text>
|
|
305
|
+
<FlexBox alignItems="center" gap={8}>
|
|
306
|
+
<Box bg="paleGreen" p={8} zIndex={3} position="relative">
|
|
307
|
+
z-index: 3
|
|
308
|
+
</Box>
|
|
309
|
+
<InfoTip
|
|
310
|
+
ariaLabel="floating default"
|
|
311
|
+
info="Default z-index (floating)"
|
|
312
|
+
placement="floating"
|
|
313
|
+
/>
|
|
314
|
+
<Box bg="paleGreen" p={8} zIndex={3} position="relative">
|
|
315
|
+
z-index: 3
|
|
316
|
+
</Box>
|
|
317
|
+
<InfoTip
|
|
318
|
+
{...args}
|
|
319
|
+
ariaLabel="floating custom"
|
|
320
|
+
info="z-index: 5 (floating)"
|
|
321
|
+
placement="floating"
|
|
322
|
+
/>
|
|
323
|
+
</FlexBox>
|
|
261
324
|
</FlexBox>
|
|
262
325
|
),
|
|
263
326
|
};
|
|
@@ -55,6 +55,12 @@ The `truncateLines` prop allows you to set the maximum number of lines that the
|
|
|
55
55
|
|
|
56
56
|
<Canvas of={PreviewTipStories.Truncation} />
|
|
57
57
|
|
|
58
|
+
## Z-Index
|
|
59
|
+
|
|
60
|
+
You can customize the `zIndex` of the PreviewTip's portal with the `zIndex` prop. This works for both `inline` and `floating` placements, and is useful when the tip needs to appear above other positioned elements.
|
|
61
|
+
|
|
62
|
+
<Canvas of={PreviewTipStories.ZIndex} />
|
|
63
|
+
|
|
58
64
|
## Playground
|
|
59
65
|
|
|
60
66
|
<Canvas sourceState="shown" of={PreviewTipStories.Default} />
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Box, FlexBox, PreviewTip } from '@codecademy/gamut';
|
|
1
|
+
import { Box, FlexBox, PreviewTip, Text } from '@codecademy/gamut';
|
|
2
2
|
import { SmileyIndifferentIcon } from '@codecademy/gamut-icons';
|
|
3
3
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
4
4
|
import { useState } from 'react';
|
|
@@ -110,3 +110,70 @@ const TruncationExample = (args: React.ComponentProps<typeof PreviewTip>) => {
|
|
|
110
110
|
export const Truncation: Story = {
|
|
111
111
|
render: (args) => <TruncationExample {...args} />,
|
|
112
112
|
};
|
|
113
|
+
|
|
114
|
+
export const ZIndex: Story = {
|
|
115
|
+
args: {
|
|
116
|
+
zIndex: 5,
|
|
117
|
+
},
|
|
118
|
+
render: (args) => (
|
|
119
|
+
<FlexBox center flexDirection="column" gap={16} py={64}>
|
|
120
|
+
<Text variant="p-small">Inline placement:</Text>
|
|
121
|
+
<FlexBox alignItems="center" gap={16}>
|
|
122
|
+
<Box bg="paleBlue" p={8} zIndex={3} position="relative">
|
|
123
|
+
z-index: 3
|
|
124
|
+
</Box>
|
|
125
|
+
<PreviewTip
|
|
126
|
+
{...args}
|
|
127
|
+
alignment="bottom-right"
|
|
128
|
+
href="#"
|
|
129
|
+
linkDescription="Default z-index (inline)"
|
|
130
|
+
>
|
|
131
|
+
Default z-index
|
|
132
|
+
</PreviewTip>
|
|
133
|
+
<Box bg="paleBlue" p={8} zIndex={3} position="relative">
|
|
134
|
+
z-index: 3
|
|
135
|
+
</Box>
|
|
136
|
+
<PreviewTip
|
|
137
|
+
{...args}
|
|
138
|
+
alignment="top-right"
|
|
139
|
+
href="#"
|
|
140
|
+
linkDescription="z-index: 5 (inline)"
|
|
141
|
+
zIndex={5}
|
|
142
|
+
>
|
|
143
|
+
z-index: 5
|
|
144
|
+
</PreviewTip>
|
|
145
|
+
</FlexBox>
|
|
146
|
+
|
|
147
|
+
<Text variant="p-small" mt={24}>
|
|
148
|
+
Floating placement:
|
|
149
|
+
</Text>
|
|
150
|
+
<FlexBox alignItems="center" gap={16}>
|
|
151
|
+
<Box bg="paleGreen" p={8} zIndex={3} position="relative">
|
|
152
|
+
z-index: 3
|
|
153
|
+
</Box>
|
|
154
|
+
<PreviewTip
|
|
155
|
+
{...args}
|
|
156
|
+
alignment="bottom-right"
|
|
157
|
+
href="#"
|
|
158
|
+
linkDescription="Default z-index (floating)"
|
|
159
|
+
placement="floating"
|
|
160
|
+
>
|
|
161
|
+
Default z-index
|
|
162
|
+
</PreviewTip>
|
|
163
|
+
<Box bg="paleGreen" p={8} zIndex={3} position="relative">
|
|
164
|
+
z-index: 3
|
|
165
|
+
</Box>
|
|
166
|
+
<PreviewTip
|
|
167
|
+
{...args}
|
|
168
|
+
alignment="top-right"
|
|
169
|
+
href="#"
|
|
170
|
+
linkDescription="z-index: 5 (floating)"
|
|
171
|
+
placement="floating"
|
|
172
|
+
zIndex={5}
|
|
173
|
+
>
|
|
174
|
+
z-index: 5
|
|
175
|
+
</PreviewTip>
|
|
176
|
+
</FlexBox>
|
|
177
|
+
</FlexBox>
|
|
178
|
+
),
|
|
179
|
+
};
|
|
@@ -63,6 +63,12 @@ When a Button is disabled with a tooltip, you must use the `aria-disabled` prop
|
|
|
63
63
|
|
|
64
64
|
<Canvas of={ToolTipStories.Disabled} />
|
|
65
65
|
|
|
66
|
+
## Z-Index
|
|
67
|
+
|
|
68
|
+
You can customize the `zIndex` of the ToolTip's portal with the `zIndex` prop. This works for both `inline` and `floating` placements, and is useful when the tip needs to appear above other positioned elements.
|
|
69
|
+
|
|
70
|
+
<Canvas of={ToolTipStories.ZIndex} />
|
|
71
|
+
|
|
66
72
|
## Playground
|
|
67
73
|
|
|
68
74
|
<Canvas sourceState="shown" of={ToolTipStories.Default} />
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Box,
|
|
2
3
|
FillButton,
|
|
3
4
|
FlexBox,
|
|
4
5
|
IconButton,
|
|
5
6
|
StrokeButton,
|
|
7
|
+
Text,
|
|
6
8
|
ToolTip,
|
|
7
9
|
} from '@codecademy/gamut';
|
|
8
10
|
import {
|
|
@@ -133,3 +135,60 @@ export const Disabled: Story = {
|
|
|
133
135
|
</FlexBox>
|
|
134
136
|
),
|
|
135
137
|
};
|
|
138
|
+
|
|
139
|
+
export const ZIndex: Story = {
|
|
140
|
+
render: () => (
|
|
141
|
+
<FlexBox center flexDirection="column" gap={16} m={24} py={64}>
|
|
142
|
+
<Text variant="p-small">Inline placement:</Text>
|
|
143
|
+
<FlexBox alignItems="center" gap={16}>
|
|
144
|
+
<Box bg="paleBlue" p={8} zIndex={3} position="relative">
|
|
145
|
+
z-index: 3
|
|
146
|
+
</Box>
|
|
147
|
+
<ToolTip id="zindex-inline-default" info="Default z-index (inline)">
|
|
148
|
+
<FillButton aria-describedby="zindex-inline-default">
|
|
149
|
+
Default
|
|
150
|
+
</FillButton>
|
|
151
|
+
</ToolTip>
|
|
152
|
+
<Box bg="paleBlue" p={8} zIndex={3} position="relative">
|
|
153
|
+
z-index: 3
|
|
154
|
+
</Box>
|
|
155
|
+
<ToolTip id="zindex-inline-custom" info="z-index: 5 (inline)" zIndex={5}>
|
|
156
|
+
<FillButton aria-describedby="zindex-inline-custom">
|
|
157
|
+
z-index: 5
|
|
158
|
+
</FillButton>
|
|
159
|
+
</ToolTip>
|
|
160
|
+
</FlexBox>
|
|
161
|
+
|
|
162
|
+
<Text variant="p-small" mt={24}>
|
|
163
|
+
Floating placement:
|
|
164
|
+
</Text>
|
|
165
|
+
<FlexBox alignItems="center" gap={16}>
|
|
166
|
+
<Box bg="paleGreen" p={8} zIndex={3} position="relative">
|
|
167
|
+
z-index: 3
|
|
168
|
+
</Box>
|
|
169
|
+
<ToolTip
|
|
170
|
+
id="zindex-floating-default"
|
|
171
|
+
info="Default z-index (floating)"
|
|
172
|
+
placement="floating"
|
|
173
|
+
>
|
|
174
|
+
<FillButton aria-describedby="zindex-floating-default">
|
|
175
|
+
Default
|
|
176
|
+
</FillButton>
|
|
177
|
+
</ToolTip>
|
|
178
|
+
<Box bg="paleGreen" p={8} zIndex={3} position="relative">
|
|
179
|
+
z-index: 3
|
|
180
|
+
</Box>
|
|
181
|
+
<ToolTip
|
|
182
|
+
id="zindex-floating-custom"
|
|
183
|
+
info="z-index: 5 (floating)"
|
|
184
|
+
placement="floating"
|
|
185
|
+
zIndex={5}
|
|
186
|
+
>
|
|
187
|
+
<FillButton aria-describedby="zindex-floating-custom">
|
|
188
|
+
z-index: 5
|
|
189
|
+
</FillButton>
|
|
190
|
+
</ToolTip>
|
|
191
|
+
</FlexBox>
|
|
192
|
+
</FlexBox>
|
|
193
|
+
),
|
|
194
|
+
};
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import styled from '@emotion/styled';
|
|
2
|
-
import { css } from '@codecademy/gamut-styles';
|
|
3
|
-
|
|
4
|
-
export const KeyboardKey = styled.kbd(
|
|
5
|
-
css({
|
|
6
|
-
mx: 2 as any,
|
|
7
|
-
fontFamily: 'monospace',
|
|
8
|
-
fontSize: '0.75rem' as any,
|
|
9
|
-
bg: 'background-selected',
|
|
10
|
-
border: 1,
|
|
11
|
-
borderColor: 'border-tertiary',
|
|
12
|
-
borderRadius: 'sm',
|
|
13
|
-
px: 4,
|
|
14
|
-
py: 2 as any,
|
|
15
|
-
boxShadow: 'inset 0 -1px 0 rgba(0, 0, 0, 0.2)',
|
|
16
|
-
})
|
|
17
|
-
);
|