Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Misc Odyssey updates #2326

Merged
merged 16 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
9462602
feat(odyssey-react-mui): expose Stack and Grid from MUI
bryancunningham-okta Aug 23, 2024
1421781
feat(odyssey-react-mui): expose Autocomplete getOptionLabel prop
bryancunningham-okta Aug 23, 2024
efd6aed
fix(odyssey-storybook): fix deprectated storyName warning
bryancunningham-okta Aug 23, 2024
5bc15de
feat(odyssey-storybook): wrap stack and grid
bryancunningham-okta Aug 26, 2024
4f5005f
fix(odyssey-storybook): fix palette dark color and intro darker
bryancunningham-okta Aug 27, 2024
d6b876d
fix(odyssey-storybook): map darker to the correct number
bryancunningham-okta Aug 27, 2024
59c15c7
feat(odyssey-react-mui): add linkTarget for Callout
bryancunningham-okta Sep 30, 2024
7ab6822
feat(odyssey-react-mui): use ODS link and add story
bryancunningham-okta Sep 30, 2024
92eca61
feat(odyssey-react-mui): add correct prop description
bryancunningham-okta Sep 30, 2024
fd523cc
feat(odyssey-react-mui): add linkTarget for Banner
bryancunningham-okta Sep 30, 2024
a18c5d3
feat(odyssey-react-mui): use defs from LinkProps
bryancunningham-okta Sep 30, 2024
5bc7ef9
chore(odyssey-react-mui): remove disabled tooltip button story
bryancunningham-okta Sep 30, 2024
33c8f1b
chore(odyssey-react-mui): remove grid for now
bryancunningham-okta Sep 30, 2024
023645b
chore(odyssey-react-mui): add Stack stories
bryancunningham-okta Sep 30, 2024
c5eb3d4
fix(odyssey-react-mui): fix banner type error
bryancunningham-okta Sep 30, 2024
9194441
feat(odyssey-react-mui): add linkRel prop Banner and Callout
bryancunningham-okta Oct 1, 2024
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
13 changes: 13 additions & 0 deletions packages/odyssey-react-mui/src/Autocomplete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,17 @@ export type AutocompleteProps<
undefined,
IsCustomValueAllowed
>["defaultValue"];
/**
* Used to determine the string value for a given option. It's used to fill the input (and the list box options if renderOption is not provided). If used in free solo mode, it must accept both the type of the options and a string.
*
* `function(option: Value) => string`
*/
getOptionLabel?: UseAutocompleteProps<
OptionType,
HasMultipleChoices,
undefined,
IsCustomValueAllowed
>["getOptionLabel"];
KevinGhadyani-Okta marked this conversation as resolved.
Show resolved Hide resolved
/**
* Enables multiple choice selection
*/
Expand Down Expand Up @@ -249,6 +260,7 @@ const Autocomplete = <
defaultValue,
errorMessage,
errorMessageList,
getOptionLabel,
hasMultipleChoices,
id: idOverride,
inputValue,
Expand Down Expand Up @@ -571,6 +583,7 @@ const Autocomplete = <
disabled={isDisabled}
freeSolo={isCustomValueAllowed}
filterSelectedOptions={true}
getOptionLabel={getOptionLabel}
id={idOverride}
fullWidth={isFullWidth}
loading={isLoading}
Expand Down
43 changes: 29 additions & 14 deletions packages/odyssey-react-mui/src/Banner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { useTranslation } from "react-i18next";
import { Alert, AlertColor, AlertTitle, AlertProps } from "@mui/material";

import type { HtmlProps } from "./HtmlProps";
import { Link } from "./Link";
import { Link, LinkProps } from "./Link";
import { ScreenReaderText } from "./ScreenReaderText";

export const bannerRoleValues = ["status", "alert"] as const;
Expand All @@ -27,16 +27,6 @@ export const bannerSeverityValues: AlertColor[] = [
];

export type BannerProps = {
/**
* If linkUrl is not undefined, this is the text of the link.
* If left blank, it defaults to "Learn more".
* Note that linkText does nothing if linkUrl is not defined
*/
linkText?: string;
/**
* If defined, the alert will include a link to the URL
*/
linkUrl?: string;
/**
* The function that's fired when the user clicks the close button. If undefined,
* the close button will not be shown.
Expand All @@ -56,11 +46,30 @@ export type BannerProps = {
* The text content of the alert
*/
text: string;
} & Pick<HtmlProps, "testId" | "translate">;
} & Pick<HtmlProps, "testId" | "translate"> &
(
| {
linkRel?: LinkProps["rel"];
linkTarget?: LinkProps["target"];
linkText: string;
/**
* If defined, the Banner will include a link to the URL
*/
linkUrl: LinkProps["href"];
}
| {
linkRel?: never;
linkTarget?: never;
linkText?: never;
linkUrl?: never;
}
);

const Banner = ({
linkUrl,
linkRel,
linkTarget,
linkText,
linkUrl,
onClose,
role,
severity,
Expand All @@ -83,7 +92,13 @@ const Banner = ({
</ScreenReaderText>
<AlertTitle translate={translate}>{text}</AlertTitle>
{linkUrl && (
<Link href={linkUrl} variant="monochrome" translate={translate}>
<Link
href={linkUrl}
rel={linkRel}
target={linkTarget}
translate={translate}
variant="monochrome"
>
{linkText}
</Link>
)}
Expand Down
29 changes: 18 additions & 11 deletions packages/odyssey-react-mui/src/Callout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@
*/

import styled from "@emotion/styled";
import { Alert, AlertTitle, Box, Link as MuiLink } from "@mui/material";
import { Alert, AlertTitle, Box } from "@mui/material";
import { memo, ReactNode } from "react";
import { useTranslation } from "react-i18next";

import type { HtmlProps } from "./HtmlProps";
import { Link, LinkProps } from "./Link";
import {
DesignTokens,
useOdysseyDesignTokens,
Expand Down Expand Up @@ -92,18 +93,17 @@ export type CalloutProps = {
) &
(
| {
linkRel?: LinkProps["rel"];
linkTarget?: LinkProps["target"];
linkText: string;
/**
* If linkUrl is not undefined, this is the text of the link.
* If left blank, it defaults to "Learn more".
* Note that linkText does nothing if linkUrl is not defined
*/
linkUrl: string;
/**
* If defined, the Toast will include a link to the URL
* If defined, the Callout will include a link to the URL
*/
linkText: string;
linkUrl: LinkProps["href"];
}
| {
linkRel?: never;
linkTarget?: never;
linkUrl?: never;
linkText?: never;
}
Expand All @@ -120,6 +120,8 @@ const ContentContainer = styled("div", {

const Callout = ({
children,
linkRel,
linkTarget,
linkText,
linkUrl,
role,
Expand Down Expand Up @@ -153,9 +155,14 @@ const Callout = ({
{text && <Paragraph>{text}</Paragraph>}
{linkUrl && (
<Box>
<MuiLink href={linkUrl} variant="monochrome">
<Link
href={linkUrl}
rel={linkRel}
target={linkTarget}
variant="monochrome"
>
{linkText}
</MuiLink>
</Link>
</Box>
)}
</ContentContainer>
Expand Down
4 changes: 3 additions & 1 deletion packages/odyssey-react-mui/src/Link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ export type LinkProps = {
*/
onClick?: MuiLinkProps["onClick"];
/**
* The HTML `rel` attribute for the Link
* The rel attribute defines the relationship between a linked resource and the current document
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel
*/
rel?: string;
/**
Expand Down
56 changes: 56 additions & 0 deletions packages/odyssey-react-mui/src/Stack.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*!
* Copyright (c) 2023-present, Okta, Inc. and/or its affiliates. All rights reserved.
* The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
*
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and limitations under the License.
*/

import { memo } from "react";
import { Stack as MuiStack, StackProps as MuiStackProps } from "@mui/material";

export const stackSpacingValues = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] as const;
export const stackDirectionValues = [
"row",
"row-reverse",
"column",
"column-reverse",
] as const;

export type OdysseyStackProps = {
children?: MuiStackProps["children"];
/**
* The component used for the root node. Either a string to use a HTML element or a component.
*/
component?: MuiStackProps["component"];
/**
* Defines the flex-direction style property. It is applied for all screen sizes.
*/
direction?: (typeof stackDirectionValues)[number];
/**
* Defines the space between immediate children.
*/
spacing?: (typeof stackSpacingValues)[number];
sx?: MuiStackProps["sx"];
};

const Stack = ({
children,
direction = "column",
spacing = 2,
}: OdysseyStackProps) => {
return (
<MuiStack direction={direction} spacing={spacing}>
{children}
</MuiStack>
);
};

const MemoizedStack = memo(Stack);
MemoizedStack.displayName = "Stack";

export { MemoizedStack as Stack };
3 changes: 3 additions & 0 deletions packages/odyssey-react-mui/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export {
Paper,
/** @deprecated Will be removed in a future Odyssey version in lieu of a wrapped version. */
ScopedCssBaseline,
/** @deprecated Will be removed in a future Odyssey version in lieu of a wrapped version. */
ThemeProvider,
} from "@mui/material";

Expand All @@ -49,6 +50,7 @@ export type {
MenuListProps,
PaperProps,
ScopedCssBaselineProps,
StackProps,
ThemeOptions,
} from "@mui/material";

Expand Down Expand Up @@ -100,6 +102,7 @@ export * from "./RadioGroup";
export * from "./ScreenReaderText";
export * from "./SearchField";
export * from "./Select";
export * from "./Stack";
export * from "./Status";
export * from "./Surface";
export * from "./Tabs";
Expand Down
8 changes: 2 additions & 6 deletions packages/odyssey-react-mui/src/labs/datePickerTheme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,6 @@ const dateStyles: StateStyles = {
hoverSelected: ({ theme }) => ({
backgroundColor: theme.palette.primary.dark,
color: theme.palette.primary.contrastText,

"@media (pointer: fine)": {
backgroundColor: theme.palette.primary.main,
},
}),
outsideOfMonth: ({ theme }) => ({
backgroundColor: "transparent",
Expand Down Expand Up @@ -158,8 +154,8 @@ export const datePickerTheme: ThemeOptions = {
borderStyle: theme.mixins.borderStyle,
borderWidth: theme.mixins.borderWidth,
borderRadius: theme.mixins.borderRadius,
paddingBlock: theme.spacing(3),
paddingInline: theme.spacing(3),
paddingBlock: theme.spacing(6),
paddingInline: theme.spacing(6),
},
}),
},
Expand Down
3 changes: 2 additions & 1 deletion packages/odyssey-react-mui/src/theme/palette.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ export const palette = ({
lighter: odysseyTokens.HueBlue50,
light: odysseyTokens.HueBlue300,
main: odysseyTokens.HueBlue500,
dark: odysseyTokens.HueBlue900,
dark: odysseyTokens.HueBlue700,
darker: odysseyTokens.HueBlue800,
contrastText: odysseyTokens.TypographyColorInverse,
},
secondary: {
Expand Down
2 changes: 2 additions & 0 deletions packages/odyssey-react-mui/src/theme/palette.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@

declare module "@mui/material/styles" {
interface PaletteColor {
darker?: string;
lighter?: string;
}
interface SimplePaletteColorOptions {
darker?: string;
lighter?: string;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,38 @@ import { MuiThemeDecorator } from "../../../../.storybook/components";
import { userEvent, within } from "@storybook/testing-library";
import { expect, jest } from "@storybook/jest";
import { axeRun } from "../../../axe-util";
import type { PlaywrightProps } from "../storybookTypes";

const storybookMeta: Meta<typeof Banner> = {
type PlayType = {
args: BannerProps;
canvasElement: HTMLElement;
step: PlaywrightProps<BannerProps>["step"];
};

const storybookMeta: Meta<BannerProps> = {
title: "MUI Components/Banner",
component: Banner,
argTypes: {
linkRel: {
control: "text",
description:
"The rel attribute defines the relationship between a linked resource and the current document.",
table: {
type: {
summary: "string",
},
},
},
linkTarget: {
control: "text",
description:
"The target property of the `HTMLAnchorElement` interface is a string that indicates where to display the linked resource.",
table: {
type: {
summary: "string",
},
},
},
linkText: {
control: "text",
description:
Expand Down Expand Up @@ -138,7 +165,7 @@ export const Linked: StoryObj<BannerProps> = {
severity: "error",
text: "An unidentified flying object compromised Hangar 18.",
},
play: async ({ canvasElement, step }) => {
play: async ({ canvasElement, step }: PlayType) => {
await step("check for the link text", async () => {
const canvas = within(canvasElement);
const link = canvas.getByText("View report") as HTMLAnchorElement;
Expand All @@ -148,11 +175,22 @@ export const Linked: StoryObj<BannerProps> = {
},
};

export const LinkWithTarget: StoryObj<BannerProps> = {
args: {
linkTarget: "_blank",
linkText: "View report",
linkUrl: "#anchor",
role: "status",
severity: "error",
text: "An unidentified flying object compromised Hangar 18.",
},
};

export const Dismissible: StoryObj<BannerProps> = {
args: {
onClose: jest.fn(),
},
play: async ({ args, canvasElement, step }) => {
play: async ({ args, canvasElement, step }: PlayType) => {
await step("dismiss the banner on click", async () => {
const canvas = within(canvasElement);
const button = canvas.getByTitle("Close");
Expand Down
Loading