From 9a69f169ee6d6a40b08f0e9e6eb1d2abd9821845 Mon Sep 17 00:00:00 2001 From: dreamwasp Date: Wed, 10 Dec 2025 12:31:32 -0500 Subject: [PATCH] docs: add zIndex documentation to floating components - Overlay: add zIndex story and docs section - Modal: add zIndex note with code example - InfoTip: update story to show inline and floating placements - PreviewTip: add zIndex story showing both placements - ToolTip: add zIndex story showing both placements - Coachmark: add zIndex story using popoverProps passthrough --- packages/gamut/src/Popover/Popover.tsx | 8 +- packages/gamut/src/Popover/elements.tsx | 8 +- packages/gamut/src/Popover/types.tsx | 5 ++ packages/gamut/src/Tip/shared/FloatingTip.tsx | 2 + packages/gamut/src/Tip/shared/types.tsx | 7 +- .../src/lib/Molecules/Coachmark/Coachmark.mdx | 6 ++ .../Molecules/Coachmark/Coachmark.stories.tsx | 38 ++++++++- .../src/lib/Molecules/Modals/Modal/Modal.mdx | 10 +++ .../lib/Molecules/Modals/Overlay/Overlay.mdx | 6 ++ .../Modals/Overlay/Overlay.stories.tsx | 69 ++++++++++++++- .../lib/Molecules/Tips/InfoTip/InfoTip.mdx | 19 ++++- .../Tips/InfoTip/InfoTip.stories.tsx | 83 ++++++++++++++++--- .../Molecules/Tips/PreviewTip/PreviewTip.mdx | 6 ++ .../Tips/PreviewTip/PreviewTip.stories.tsx | 69 ++++++++++++++- .../lib/Molecules/Tips/ToolTip/ToolTip.mdx | 6 ++ .../Tips/ToolTip/ToolTip.stories.tsx | 59 +++++++++++++ 16 files changed, 376 insertions(+), 25 deletions(-) diff --git a/packages/gamut/src/Popover/Popover.tsx b/packages/gamut/src/Popover/Popover.tsx index 86bbb05d9ee..601c2f5b065 100755 --- a/packages/gamut/src/Popover/Popover.tsx +++ b/packages/gamut/src/Popover/Popover.tsx @@ -40,8 +40,8 @@ export const Popover: React.FC = ({ variant, }), verticalOffset = getDefaultOffset({ axis: 'vertical', position, variant }), - widthRestricted, + zIndex, }) => { const [popoverHeight, setPopoverHeight] = useState(0); const [popoverWidth, setPopoverWidth] = useState(0); @@ -233,7 +233,11 @@ export const Popover: React.FC = ({ ); return ( - + {skipFocusTrap ? ( <>{contents} ) : ( diff --git a/packages/gamut/src/Popover/elements.tsx b/packages/gamut/src/Popover/elements.tsx index 04908315050..74b251d02b5 100644 --- a/packages/gamut/src/Popover/elements.tsx +++ b/packages/gamut/src/Popover/elements.tsx @@ -61,12 +61,12 @@ export const PatternContainer = styled.div( ); export const PopoverPortal: React.FC< - Pick & WithChildrenProp -> = ({ animation, isOpen, ...rest }) => + Pick & WithChildrenProp +> = ({ animation, isOpen, zIndex, ...rest }) => animation ? ( {isOpen && ( - + ) : ( - + ); export type PopoverContainerProps = Pick; diff --git a/packages/gamut/src/Popover/types.tsx b/packages/gamut/src/Popover/types.tsx index b85d4d4595c..40807e752ff 100755 --- a/packages/gamut/src/Popover/types.tsx +++ b/packages/gamut/src/Popover/types.tsx @@ -113,4 +113,9 @@ export type PopoverProps = PopoverBaseProps & * Whether to add width restrictions to Popover. */ widthRestricted?: boolean; + + /** + * z-index for the Popover's portal. Defaults to 1. + */ + zIndex?: number; }; diff --git a/packages/gamut/src/Tip/shared/FloatingTip.tsx b/packages/gamut/src/Tip/shared/FloatingTip.tsx index c251d1570cf..41a1a33000d 100644 --- a/packages/gamut/src/Tip/shared/FloatingTip.tsx +++ b/packages/gamut/src/Tip/shared/FloatingTip.tsx @@ -36,6 +36,7 @@ export const FloatingTip: React.FC = ({ type, username, wrapperRef, + zIndex, }) => { const ref = useRef(null); @@ -172,6 +173,7 @@ export const FloatingTip: React.FC = ({ targetRef={ref} variant="secondary" widthRestricted={false} + zIndex={zIndex} > void); type: 'info' | 'tool' | 'preview'; wrapperRef?: React.RefObject; - zIndex?: number; } & React.PropsWithChildren; diff --git a/packages/styleguide/src/lib/Molecules/Coachmark/Coachmark.mdx b/packages/styleguide/src/lib/Molecules/Coachmark/Coachmark.mdx index 381e882de7e..c4962dfd8bf 100644 --- a/packages/styleguide/src/lib/Molecules/Coachmark/Coachmark.mdx +++ b/packages/styleguide/src/lib/Molecules/Coachmark/Coachmark.mdx @@ -94,6 +94,12 @@ Using `popoverProps`, you can customize the look of the rendered popover. For ex +### Z-Index + +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. + + + ## Playground diff --git a/packages/styleguide/src/lib/Molecules/Coachmark/Coachmark.stories.tsx b/packages/styleguide/src/lib/Molecules/Coachmark/Coachmark.stories.tsx index 126306353ec..3c14c2a86ed 100644 --- a/packages/styleguide/src/lib/Molecules/Coachmark/Coachmark.stories.tsx +++ b/packages/styleguide/src/lib/Molecules/Coachmark/Coachmark.stories.tsx @@ -1,4 +1,4 @@ -import { Coachmark, FillButton, FlexBox, Text } from '@codecademy/gamut'; +import { Box, Coachmark, FillButton, FlexBox, Text } from '@codecademy/gamut'; import * as patterns from '@codecademy/gamut-patterns'; import type { Meta, StoryObj } from '@storybook/react'; import { ComponentProps, useEffect, useState } from 'react'; @@ -197,3 +197,39 @@ export const Customized: Story = { ); }, }; + +export const ZIndex: Story = { + args: { + popoverProps: { + position: 'below', + zIndex: 5, + }, + }, + render: function ZIndexExample(args) { + const [shouldShow, setShouldShow] = useState(true); + + return ( + + + Element with z-index: 3 + + ( + + This coachmark has z-index: 5 via popoverProps + setShouldShow(false)}> + Got it + + + )} + shouldShow={shouldShow} + > + setShouldShow(true)}> + Show Coachmark + + + + ); + }, +}; diff --git a/packages/styleguide/src/lib/Molecules/Modals/Modal/Modal.mdx b/packages/styleguide/src/lib/Molecules/Modals/Modal/Modal.mdx index ad0ff55a868..7a6b2eabfe5 100644 --- a/packages/styleguide/src/lib/Molecules/Modals/Modal/Modal.mdx +++ b/packages/styleguide/src/lib/Molecules/Modals/Modal/Modal.mdx @@ -89,6 +89,16 @@ A Modal can be made scrollable by including large content inside. +## Z-Index + +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. + +```tsx + + Content that needs to appear above other positioned elements + +``` + ## Focus management 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). diff --git a/packages/styleguide/src/lib/Molecules/Modals/Overlay/Overlay.mdx b/packages/styleguide/src/lib/Molecules/Modals/Overlay/Overlay.mdx index 58af32ec62d..fc8a6327120 100644 --- a/packages/styleguide/src/lib/Molecules/Modals/Overlay/Overlay.mdx +++ b/packages/styleguide/src/lib/Molecules/Modals/Overlay/Overlay.mdx @@ -32,6 +32,12 @@ Unlike the legacy `Modal` implementations in the monolith, this: - If you need styles such as a background behind content, see `Modal` for general modals and `Dialog` for confirmation flows. +## Z-Index + +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. + + + ## Playground diff --git a/packages/styleguide/src/lib/Molecules/Modals/Overlay/Overlay.stories.tsx b/packages/styleguide/src/lib/Molecules/Modals/Overlay/Overlay.stories.tsx index cc24ef064c6..a6c9e9aedce 100644 --- a/packages/styleguide/src/lib/Molecules/Modals/Overlay/Overlay.stories.tsx +++ b/packages/styleguide/src/lib/Molecules/Modals/Overlay/Overlay.stories.tsx @@ -1,5 +1,5 @@ -import { FillButton, FlexBox, Overlay, Text } from '@codecademy/gamut'; -import type { Meta } from '@storybook/react'; +import { Box, FillButton, FlexBox, Overlay, Text } from '@codecademy/gamut'; +import type { Meta, StoryObj } from '@storybook/react'; import { useEffect, useState } from 'react'; const meta: Meta = { @@ -8,6 +8,7 @@ const meta: Meta = { }; export default meta; +type Story = StoryObj; export const Default: React.FC> = ( args @@ -34,3 +35,67 @@ export const Default: React.FC> = ( ); }; + +export const ZIndex: Story = { + render: function ZIndexExample() { + const [defaultOpen, setDefaultOpen] = useState(false); + const [customOpen, setCustomOpen] = useState(false); + + return ( + + + setDefaultOpen(true)}> + Open Overlay (default z-index: 3) + + setCustomOpen(true)}> + Open Overlay (z-index: 10) + + + + + + Element with z-index: 5 + + + + setDefaultOpen(false)} + shroud + > + + + This overlay uses the default z-index of 3. +
+ It may appear behind elements with higher z-index values. +
+ setDefaultOpen(false)}>Close +
+
+ + setCustomOpen(false)} + shroud + zIndex={10} + > + + + This overlay uses z-index: 10. +
+ It will appear above the yellow element with z-index: 5. +
+ setCustomOpen(false)}>Close +
+
+
+ ); + }, +}; diff --git a/packages/styleguide/src/lib/Molecules/Tips/InfoTip/InfoTip.mdx b/packages/styleguide/src/lib/Molecules/Tips/InfoTip/InfoTip.mdx index 15b440bf553..903042c971f 100644 --- a/packages/styleguide/src/lib/Molecules/Tips/InfoTip/InfoTip.mdx +++ b/packages/styleguide/src/lib/Molecules/Tips/InfoTip/InfoTip.mdx @@ -82,9 +82,24 @@ InfoTips have intelligent Escape key handling that works correctly both inside a -## InfoTips and zIndex +## Custom Accessible Labeling -You can change the zIndex of your `InfoTip` with the zIndex property. +Provide either `ariaLabel` or `ariaLabelledby` to ensure screen reader users understand the purpose of the InfoTip button. + +The InfoTip button's accessible label can be customized using either prop: + +- **`ariaLabel`**: Directly sets the accessible label text. Useful when you want to provide a custom label without referencing another element. +- **`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. + +### Custom Role Description + +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. + + + +## Z-Index + +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. diff --git a/packages/styleguide/src/lib/Molecules/Tips/InfoTip/InfoTip.stories.tsx b/packages/styleguide/src/lib/Molecules/Tips/InfoTip/InfoTip.stories.tsx index 66807b72d2b..4f806892d19 100644 --- a/packages/styleguide/src/lib/Molecules/Tips/InfoTip/InfoTip.stories.tsx +++ b/packages/styleguide/src/lib/Molecules/Tips/InfoTip/InfoTip.stories.tsx @@ -1,6 +1,7 @@ import { Anchor, Box, + Coachmark, FillButton, FlexBox, GridBox, @@ -195,6 +196,7 @@ export const InfoTipInsideModal: Story = { }, render: function InfoTipInsideModal(args) { const [isModalOpen, setIsModalOpen] = useState(false); + const [showCoachmark, setShowCoachmark] = useState(false); return ( @@ -233,6 +235,37 @@ export const InfoTipInsideModal: Story = { closing the modal itself. Inline placement works correctly. + + + This modal also contains a Coachmark + + ( + + + This Coachmark is inside a Modal. Try pressing Escape! + + setShowCoachmark(false)} + > + Got it + + + )} + shouldShow={showCoachmark} + > + setShowCoachmark(true)}> + Show Coachmark + + + + setIsModalOpen(false)}> Close Modal @@ -245,19 +278,49 @@ export const InfoTipInsideModal: Story = { export const ZIndex: Story = { args: { - info: 'I am inline, cool', + info: 'I have a custom z-index', zIndex: 5, }, render: (args) => ( - - - I will not be behind the infotip, sad + unreadable - - - - I will be behind the infotip, nice + great - - + + Inline placement: + + + z-index: 3 + + + + z-index: 3 + + + + + + Floating placement: + + + + z-index: 3 + + + + z-index: 3 + + + ), }; diff --git a/packages/styleguide/src/lib/Molecules/Tips/PreviewTip/PreviewTip.mdx b/packages/styleguide/src/lib/Molecules/Tips/PreviewTip/PreviewTip.mdx index 6889298460f..df0b228b230 100644 --- a/packages/styleguide/src/lib/Molecules/Tips/PreviewTip/PreviewTip.mdx +++ b/packages/styleguide/src/lib/Molecules/Tips/PreviewTip/PreviewTip.mdx @@ -55,6 +55,12 @@ The `truncateLines` prop allows you to set the maximum number of lines that the +## Z-Index + +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. + + + ## Playground diff --git a/packages/styleguide/src/lib/Molecules/Tips/PreviewTip/PreviewTip.stories.tsx b/packages/styleguide/src/lib/Molecules/Tips/PreviewTip/PreviewTip.stories.tsx index 5095548c279..011aa49406c 100644 --- a/packages/styleguide/src/lib/Molecules/Tips/PreviewTip/PreviewTip.stories.tsx +++ b/packages/styleguide/src/lib/Molecules/Tips/PreviewTip/PreviewTip.stories.tsx @@ -1,4 +1,4 @@ -import { Box, FlexBox, PreviewTip } from '@codecademy/gamut'; +import { Box, FlexBox, PreviewTip, Text } from '@codecademy/gamut'; import { SmileyIndifferentIcon } from '@codecademy/gamut-icons'; import type { Meta, StoryObj } from '@storybook/react'; import { useState } from 'react'; @@ -110,3 +110,70 @@ const TruncationExample = (args: React.ComponentProps) => { export const Truncation: Story = { render: (args) => , }; + +export const ZIndex: Story = { + args: { + zIndex: 5, + }, + render: (args) => ( + + Inline placement: + + + z-index: 3 + + + Default z-index + + + z-index: 3 + + + z-index: 5 + + + + + Floating placement: + + + + z-index: 3 + + + Default z-index + + + z-index: 3 + + + z-index: 5 + + + + ), +}; diff --git a/packages/styleguide/src/lib/Molecules/Tips/ToolTip/ToolTip.mdx b/packages/styleguide/src/lib/Molecules/Tips/ToolTip/ToolTip.mdx index b6b991b5cd7..eb601570601 100644 --- a/packages/styleguide/src/lib/Molecules/Tips/ToolTip/ToolTip.mdx +++ b/packages/styleguide/src/lib/Molecules/Tips/ToolTip/ToolTip.mdx @@ -63,6 +63,12 @@ When a Button is disabled with a tooltip, you must use the `aria-disabled` prop +## Z-Index + +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. + + + ## Playground diff --git a/packages/styleguide/src/lib/Molecules/Tips/ToolTip/ToolTip.stories.tsx b/packages/styleguide/src/lib/Molecules/Tips/ToolTip/ToolTip.stories.tsx index d4fa6f4133e..b43691ec466 100644 --- a/packages/styleguide/src/lib/Molecules/Tips/ToolTip/ToolTip.stories.tsx +++ b/packages/styleguide/src/lib/Molecules/Tips/ToolTip/ToolTip.stories.tsx @@ -1,8 +1,10 @@ import { + Box, FillButton, FlexBox, IconButton, StrokeButton, + Text, ToolTip, } from '@codecademy/gamut'; import { @@ -133,3 +135,60 @@ export const Disabled: Story = { ), }; + +export const ZIndex: Story = { + render: () => ( + + Inline placement: + + + z-index: 3 + + + + Default + + + + z-index: 3 + + + + z-index: 5 + + + + + + Floating placement: + + + + z-index: 3 + + + + Default + + + + z-index: 3 + + + + z-index: 5 + + + + + ), +};