` element using its default monospace font, although this is not mandated by the HTML standard. - [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/mark)
### p
@@ -145,7 +145,7 @@ Many screen readers do not let users know of the presence of `ins`. To fix this,
> The `` HTML element represents a paragraph. Paragraphs are usually represented in visual media as blocks of text separated from adjacent blocks by blank lines and/or first-line indentation, but HTML paragraphs can be any structural grouping of related content, such as images or form fields. - [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/p)",
### pre
@@ -153,7 +153,7 @@ Many screen readers do not let users know of the presence of `ins`. To fix this,
> The `
` HTML element represents preformatted text which is to be presented exactly as written in the HTML file. The text is typically rendered using a non-proportional, or "monospaced, font. Whitespace inside this element is displayed as written. - [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/pre)
### q
@@ -161,7 +161,7 @@ Many screen readers do not let users know of the presence of `ins`. To fix this,
> The HTML `` element indicates that the enclosed text is a short inline quotation. Most modern browsers implement this by surrounding the text in quotation marks. This element is intended for short quotations that don't require paragraph breaks; for long quotations use the `` element - [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/q)
### s
@@ -169,7 +169,7 @@ Many screen readers do not let users know of the presence of `ins`. To fix this,
> The HTML `` element renders text with a strikethrough, or a line through it. Use the `` element to represent things that are no longer relevant or no longer accurate. However, `` is not appropriate when indicating document edits; for that, use the `` and `` elements, as appropriate. - [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/s)
### samp
@@ -177,7 +177,7 @@ Many screen readers do not let users know of the presence of `ins`. To fix this,
> The HTML Sample Element (``) is used to enclose inline text which represents sample (or quoted) output from a computer program. Its contents are typically rendered using the browser's default monospaced font (such as Courier or Lucida Console). - [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/samp)
### small
@@ -185,7 +185,7 @@ Many screen readers do not let users know of the presence of `ins`. To fix this,
> The `` HTML element represents side-comments and small print, like copyright and legal text, independent of its styled presentation. By default, it renders text within it one font-size smaller, such as from small to x-small. - [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/small)
### strong
@@ -193,7 +193,7 @@ Many screen readers do not let users know of the presence of `ins`. To fix this,
> The `` HTML element indicates that its contents have strong importance, seriousness, or urgency. Browsers typically render the contents in bold type. - [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/strong)
### sub
@@ -201,7 +201,7 @@ Many screen readers do not let users know of the presence of `ins`. To fix this,
> The `` HTML element specifies inline text which should be displayed as subscript for solely typographical reasons. Subscripts are typically rendered with a lowered baseline using smaller text. - [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sub)",
### sup
@@ -209,7 +209,7 @@ Many screen readers do not let users know of the presence of `ins`. To fix this,
> The `` HTML element specifies inline text which is to be displayed as superscript for solely typographical reasons. Superscripts are usually rendered with a raised baseline using smaller text. - [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sup)",
### var
@@ -217,7 +217,7 @@ Many screen readers do not let users know of the presence of `ins`. To fix this,
> The `` HTML element represents the name of a variable in a mathematical expression or a programming context. It's typically presented using an italicized version of the current typeface, although that behavior is browser-dependent. - [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/var)",
## Usage
diff --git a/packages/odyssey-storybook/src/components/Text/TextElements.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Text/TextElements.stories.tsx
similarity index 98%
rename from packages/odyssey-storybook/src/components/Text/TextElements.stories.tsx
rename to packages/odyssey-storybook/src/components/odyssey-legacy/Text/TextElements.stories.tsx
index 2a8630aa7f..f7dbc67575 100644
--- a/packages/odyssey-storybook/src/components/Text/TextElements.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Text/TextElements.stories.tsx
@@ -18,11 +18,11 @@ import {
Heading,
Link,
ScreenReaderText,
-} from "../../../../odyssey-react/src";
+} from "../../../../../odyssey-react/src";
import TextMdx from "./Text.mdx";
export default {
- title: `Components/Text/Elements`,
+ title: `Legacy Components/Text/Elements`,
component: Text,
argTypes: {
children: {
diff --git a/packages/odyssey-storybook/src/components/Text/TextStyles.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Text/TextStyles.stories.tsx
similarity index 97%
rename from packages/odyssey-storybook/src/components/Text/TextStyles.stories.tsx
rename to packages/odyssey-storybook/src/components/odyssey-legacy/Text/TextStyles.stories.tsx
index ff45cfcfac..1b74949dde 100644
--- a/packages/odyssey-storybook/src/components/Text/TextStyles.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Text/TextStyles.stories.tsx
@@ -12,10 +12,10 @@
import React from "react";
import { Story } from "@storybook/react";
-import { Text, TextProps } from "../../../../odyssey-react/src";
+import { Text, TextProps } from "../../../../../odyssey-react/src";
export default {
- title: `Components/Text/Styles`,
+ title: `Legacy Components/Text/Styles`,
component: Text,
argTypes: {
children: {
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/TextArea/TextArea.mdx b/packages/odyssey-storybook/src/components/odyssey-legacy/TextArea/TextArea.mdx
new file mode 100644
index 0000000000..9dc0c04374
--- /dev/null
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/TextArea/TextArea.mdx
@@ -0,0 +1,33 @@
+import { ArgsTable, Canvas, Meta, Story } from "@storybook/addon-docs";
+import { theme } from "../../../../../odyssey-react/src/components/TextArea/TextArea.theme";
+import { ThemeTable } from "../../../../.storybook/components";
+
+
+
+# TextArea
+
+TextArea allows users to edit and input data.
+
+
+
+## Props
+
+
+
+
+
+## Stories
+
+
+
+
+
+
diff --git a/packages/odyssey-storybook/src/components/TextArea/TextArea.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/TextArea/TextArea.stories.tsx
similarity index 94%
rename from packages/odyssey-storybook/src/components/TextArea/TextArea.stories.tsx
rename to packages/odyssey-storybook/src/components/odyssey-legacy/TextArea/TextArea.stories.tsx
index 49e4a45953..c05addc331 100644
--- a/packages/odyssey-storybook/src/components/TextArea/TextArea.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/TextArea/TextArea.stories.tsx
@@ -12,11 +12,11 @@
import React from "react";
import type { Story } from "@storybook/react";
-import { TextArea, TextAreaProps } from "../../../../odyssey-react/src";
+import { TextArea, TextAreaProps } from "../../../../../odyssey-react/src";
import TextAreaMdx from "./TextArea.mdx";
export default {
- title: `Components/TextArea`,
+ title: `Legacy Components/TextArea`,
component: TextArea,
parameters: {
docs: {
diff --git a/packages/odyssey-storybook/src/components/TextInput/TextInput.mdx b/packages/odyssey-storybook/src/components/odyssey-legacy/TextInput/TextInput.mdx
similarity index 94%
rename from packages/odyssey-storybook/src/components/TextInput/TextInput.mdx
rename to packages/odyssey-storybook/src/components/odyssey-legacy/TextInput/TextInput.mdx
index 89a228ffee..882ca40418 100644
--- a/packages/odyssey-storybook/src/components/TextInput/TextInput.mdx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/TextInput/TextInput.mdx
@@ -1,6 +1,6 @@
import { ArgsTable, Canvas, Meta, Story } from "@storybook/addon-docs";
-import { theme } from "../../../../odyssey-react/src/components/TextInput/TextInput.theme";
-import { ThemeTable } from "../../../.storybook/components";
+import { theme } from "../../../../../odyssey-react/src/components/TextInput/TextInput.theme";
+import { ThemeTable } from "../../../../.storybook/components";
@@ -14,7 +14,7 @@ Text inputs allow users to edit and input data. They can range from simple searc
This default serves as the basis for our Text Inputs. A shown here, they required paired with a paired Label.
-
+
### Search
@@ -22,7 +22,7 @@ Standalone Search provides minimal UI for searching outside of normal form conte
In this case, we recommend using the placeholder attribute to state the scope of your search. This text should match the hidden label.
-
+
#### Button variant
diff --git a/packages/odyssey-storybook/src/components/TextInput/TextInput.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/TextInput/TextInput.stories.tsx
similarity index 95%
rename from packages/odyssey-storybook/src/components/TextInput/TextInput.stories.tsx
rename to packages/odyssey-storybook/src/components/odyssey-legacy/TextInput/TextInput.stories.tsx
index 21347de311..d7170e752c 100644
--- a/packages/odyssey-storybook/src/components/TextInput/TextInput.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/TextInput/TextInput.stories.tsx
@@ -12,11 +12,11 @@
import React from "react";
import type { Story } from "@storybook/react";
-import { TextInput, TextInputProps } from "../../../../odyssey-react/src";
+import { TextInput, TextInputProps } from "../../../../../odyssey-react/src";
import TextInputMdx from "./TextInput.mdx";
export default {
- title: `Components/TextInput`,
+ title: `Legacy Components/TextInput`,
component: TextInput,
parameters: {
docs: {
diff --git a/packages/odyssey-storybook/src/components/Toast/Toast.mdx b/packages/odyssey-storybook/src/components/odyssey-legacy/Toast/Toast.mdx
similarity index 97%
rename from packages/odyssey-storybook/src/components/Toast/Toast.mdx
rename to packages/odyssey-storybook/src/components/odyssey-legacy/Toast/Toast.mdx
index 1c49aed6cb..391ed53234 100644
--- a/packages/odyssey-storybook/src/components/Toast/Toast.mdx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Toast/Toast.mdx
@@ -1,6 +1,6 @@
import { ArgsTable, Canvas, Meta, Story } from "@storybook/addon-docs";
-import { theme } from "../../../../odyssey-react/src/components/Toast/Toast.theme";
-import { ThemeTable } from "../../../.storybook/components";
+import { theme } from "../../../../../odyssey-react/src/components/Toast/Toast.theme";
+import { ThemeTable } from "../../../../.storybook/components";
diff --git a/packages/odyssey-storybook/src/components/Toast/Toast.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Toast/Toast.stories.tsx
similarity index 97%
rename from packages/odyssey-storybook/src/components/Toast/Toast.stories.tsx
rename to packages/odyssey-storybook/src/components/odyssey-legacy/Toast/Toast.stories.tsx
index 012af76cdf..d44f7d09e8 100644
--- a/packages/odyssey-storybook/src/components/Toast/Toast.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Toast/Toast.stories.tsx
@@ -24,11 +24,11 @@ import {
TextInput,
Button,
Form,
-} from "../../../../odyssey-react/src";
+} from "../../../../../odyssey-react/src";
import ToastMdx from "./Toast.mdx";
export default {
- title: `Components/Alerts/Toast`,
+ title: `Legacy Components/Alerts/Toast`,
component: Toast,
parameters: {
layout: "fullscreen",
diff --git a/packages/odyssey-storybook/src/components/Tooltip/Tooltip.mdx b/packages/odyssey-storybook/src/components/odyssey-legacy/Tooltip/Tooltip.mdx
similarity index 94%
rename from packages/odyssey-storybook/src/components/Tooltip/Tooltip.mdx
rename to packages/odyssey-storybook/src/components/odyssey-legacy/Tooltip/Tooltip.mdx
index 785b13e666..4e4d88645a 100644
--- a/packages/odyssey-storybook/src/components/Tooltip/Tooltip.mdx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Tooltip/Tooltip.mdx
@@ -1,6 +1,6 @@
import { ArgsTable, Canvas, Meta, Story } from "@storybook/addon-docs";
-import { theme } from "../../../../odyssey-react/src/components/Tooltip/Tooltip.theme";
-import { ThemeTable } from "../../../.storybook/components";
+import { theme } from "../../../../../odyssey-react/src/components/Tooltip/Tooltip.theme";
+import { ThemeTable } from "../../../../.storybook/components";
@@ -66,7 +66,7 @@ When positioning a Tooltip, ensure:
- The Tooltip is always visible when activated, not cropped or off-page.
## Content
diff --git a/packages/odyssey-storybook/src/components/Tooltip/Tooltip.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Tooltip/Tooltip.stories.tsx
similarity index 93%
rename from packages/odyssey-storybook/src/components/Tooltip/Tooltip.stories.tsx
rename to packages/odyssey-storybook/src/components/odyssey-legacy/Tooltip/Tooltip.stories.tsx
index ed64c76891..a249bec252 100644
--- a/packages/odyssey-storybook/src/components/Tooltip/Tooltip.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Tooltip/Tooltip.stories.tsx
@@ -13,12 +13,16 @@
import React from "react";
import type { Story } from "@storybook/react";
import { action } from "@storybook/addon-actions";
-import { Tooltip, TooltipProps, Button } from "../../../../odyssey-react/src";
+import {
+ Tooltip,
+ TooltipProps,
+ Button,
+} from "../../../../../odyssey-react/src";
import TooltipMdx from "./Tooltip.mdx";
export default {
- title: `Components/Tooltip`,
+ title: `Legacy Components/Tooltip`,
component: Tooltip,
parameters: {
layout: "centered",
diff --git a/packages/odyssey-storybook/src/components/CircularProgress/CircularProgress.mdx b/packages/odyssey-storybook/src/components/odyssey-mui/CircularProgress/CircularProgress.mdx
similarity index 100%
rename from packages/odyssey-storybook/src/components/CircularProgress/CircularProgress.mdx
rename to packages/odyssey-storybook/src/components/odyssey-mui/CircularProgress/CircularProgress.mdx
diff --git a/packages/odyssey-storybook/src/components/CircularProgress/CircularProgress.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-mui/CircularProgress/CircularProgress.stories.tsx
similarity index 94%
rename from packages/odyssey-storybook/src/components/CircularProgress/CircularProgress.stories.tsx
rename to packages/odyssey-storybook/src/components/odyssey-mui/CircularProgress/CircularProgress.stories.tsx
index 8a2e69d8ae..8bf0b4570d 100644
--- a/packages/odyssey-storybook/src/components/CircularProgress/CircularProgress.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-mui/CircularProgress/CircularProgress.stories.tsx
@@ -13,7 +13,7 @@
import React from "react";
import { Story } from "@storybook/react";
import { CircularProgress, CircularProgressProps } from "@mui/material";
-import { MuiThemeDecorator } from "../../../.storybook/components/MuiThemeDecorator";
+import { MuiThemeDecorator } from "../../../../.storybook/components";
import CircularProgressMdx from "./CircularProgress.mdx";
diff --git a/packages/odyssey-storybook/src/components/PasswordInput/PasswordInput.mdx b/packages/odyssey-storybook/src/components/odyssey-mui/PasswordInput/PasswordInput.mdx
similarity index 100%
rename from packages/odyssey-storybook/src/components/PasswordInput/PasswordInput.mdx
rename to packages/odyssey-storybook/src/components/odyssey-mui/PasswordInput/PasswordInput.mdx
diff --git a/packages/odyssey-storybook/src/components/PasswordInput/PasswordInput.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-mui/PasswordInput/PasswordInput.stories.tsx
similarity index 97%
rename from packages/odyssey-storybook/src/components/PasswordInput/PasswordInput.stories.tsx
rename to packages/odyssey-storybook/src/components/odyssey-mui/PasswordInput/PasswordInput.stories.tsx
index 1f39bfe988..2623bdeb9c 100644
--- a/packages/odyssey-storybook/src/components/PasswordInput/PasswordInput.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-mui/PasswordInput/PasswordInput.stories.tsx
@@ -18,7 +18,7 @@ import {
createTheme,
} from "@mui/material/styles";
import { ThemeProvider } from "@storybook/theming";
-import { MuiThemeDecorator } from "../../../.storybook/components";
+import { MuiThemeDecorator } from "../../../../.storybook/components";
import PasswordInputMdx from "./PasswordInput.mdx";
diff --git a/packages/odyssey-storybook/src/components/Typography/Typography.mdx b/packages/odyssey-storybook/src/components/odyssey-mui/Typography/Typography.mdx
similarity index 100%
rename from packages/odyssey-storybook/src/components/Typography/Typography.mdx
rename to packages/odyssey-storybook/src/components/odyssey-mui/Typography/Typography.mdx
diff --git a/packages/odyssey-storybook/src/components/Typography/Typography.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-mui/Typography/Typography.stories.tsx
similarity index 96%
rename from packages/odyssey-storybook/src/components/Typography/Typography.stories.tsx
rename to packages/odyssey-storybook/src/components/odyssey-mui/Typography/Typography.stories.tsx
index d6ff988bca..fc88e6c2f2 100644
--- a/packages/odyssey-storybook/src/components/Typography/Typography.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-mui/Typography/Typography.stories.tsx
@@ -13,7 +13,7 @@
import React from "react";
import { Story } from "@storybook/react";
import { Typography, TypographyProps } from "@mui/material";
-import { MuiThemeDecorator } from "../../../.storybook/components/MuiThemeDecorator";
+import { MuiThemeDecorator } from "../../../../.storybook/components";
import TypographyMdx from "./Typography.mdx";
From 91a80c1fbc1c94875bf83fde33296f22a81dedf1 Mon Sep 17 00:00:00 2001
From: Edbury Enegren <36284167+edburyenegren-okta@users.noreply.github.com>
Date: Fri, 24 Jun 2022 11:36:21 -0700
Subject: [PATCH 03/22] fix(odyssey-storybook): fix font-family display in MUI
components
---
.../.storybook/components/MuiThemeDecorator.tsx | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/packages/odyssey-storybook/.storybook/components/MuiThemeDecorator.tsx b/packages/odyssey-storybook/.storybook/components/MuiThemeDecorator.tsx
index 8f70baf0f4..f638d908ad 100644
--- a/packages/odyssey-storybook/.storybook/components/MuiThemeDecorator.tsx
+++ b/packages/odyssey-storybook/.storybook/components/MuiThemeDecorator.tsx
@@ -9,7 +9,14 @@ export const MuiThemeDecorator: DecoratorFn = (Story) => (
-
+
+
+
);
From db4686daefe160ac453f20447db435cb47a49249 Mon Sep 17 00:00:00 2001
From: Edbury Enegren <36284167+edburyenegren-okta@users.noreply.github.com>
Date: Fri, 24 Jun 2022 11:36:44 -0700
Subject: [PATCH 04/22] docs(odyssey-storybook): add Checkbox, Radio stories
---
packages/odyssey-storybook/package.json | 1 +
.../odyssey-mui/Checkbox/Checkbox.mdx | 79 +++++++++
.../odyssey-mui/Checkbox/Checkbox.stories.tsx | 163 ++++++++++++++++++
.../components/odyssey-mui/Radio/Radio.mdx | 49 ++++++
.../odyssey-mui/Radio/Radio.stories.tsx | 109 ++++++++++++
5 files changed, 401 insertions(+)
create mode 100644 packages/odyssey-storybook/src/components/odyssey-mui/Checkbox/Checkbox.mdx
create mode 100644 packages/odyssey-storybook/src/components/odyssey-mui/Checkbox/Checkbox.stories.tsx
create mode 100644 packages/odyssey-storybook/src/components/odyssey-mui/Radio/Radio.mdx
create mode 100644 packages/odyssey-storybook/src/components/odyssey-mui/Radio/Radio.stories.tsx
diff --git a/packages/odyssey-storybook/package.json b/packages/odyssey-storybook/package.json
index f25b228dd6..020501df22 100644
--- a/packages/odyssey-storybook/package.json
+++ b/packages/odyssey-storybook/package.json
@@ -13,6 +13,7 @@
"@applitools/eyes-storybook": "^3.27.6",
"@babel/core": "^7.15.0",
"@mui/material": "^5.8.2",
+ "@mui/utils": "^5.8.2",
"@okta/odyssey-babel-loader": "^0.14.1",
"@okta/odyssey-design-tokens": "^0.14.1",
"@okta/odyssey-lifecycle": "^0.14.1",
diff --git a/packages/odyssey-storybook/src/components/odyssey-mui/Checkbox/Checkbox.mdx b/packages/odyssey-storybook/src/components/odyssey-mui/Checkbox/Checkbox.mdx
new file mode 100644
index 0000000000..0f74945204
--- /dev/null
+++ b/packages/odyssey-storybook/src/components/odyssey-mui/Checkbox/Checkbox.mdx
@@ -0,0 +1,79 @@
+import { ArgsTable, Canvas, Meta, Story } from "@storybook/addon-docs";
+
+
+
+# Checkbox
+
+Checkboxes appear as a square shaped UI accompanied by a caption. Checkboxes can be found in tables, forms, or in and around text inputs.
+
+## Behavior
+
+Users can click a Checkbox to make a choice and click it again to deselect an option. They allow users to select one or more options of something.
+
+Checkboxes may appear individually or as a group.
+
+
+
+
+
+### Required Checkboxes
+
+Unlike other inputs, Odyssey assumes Checkboxes are optional by default.
+
+Individual checkboxes can be set to required. This is useful when a user confirms they have read the terms of service.
+
+## States
+
+Checkboxes support several states: enabled, hover, focus, disabled, invalid, required, and indeterminate.
+
+### Enabled
+
+Checkboxes in their "unchecked" state are considered enabled. They are ready for user interaction.
+
+
+
+### Checked
+
+Checked Checkboxes, sometimes referred to as "ticked", display a check to indicate the they are selected.
+
+
+
+### Disabled
+
+Disabled inputs are unavailable for interaction and cannot be focused. They can be used when input is disallowed, possibly due to a system state or access restrictions.
+
+Checkboxes may be disabled individually or as a group. The values of disabled inputs will not be submitted.
+
+
+
+### Invalid
+
+Checkboxes present as invalid when a required input is left unchecked or an incompatible choice has been made.
+
+When indicating a validation error, please use FormHelperText set to `error` to indicate the nature of the problem. Color alone is not an accessible way to signify that something has gone wrong.
+
+Unlike Radio Buttons, Checkboxes validate individually, not as a group.
+
+
+
+### Indeterminate
+
+In the case of nested checkboxes, an indeterminate state may be required.
+
+Note that this state is visual-only and will be submitted as either "checked" or "unchecked" depending on the internal state.
+
+
diff --git a/packages/odyssey-storybook/src/components/odyssey-mui/Checkbox/Checkbox.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-mui/Checkbox/Checkbox.stories.tsx
new file mode 100644
index 0000000000..306cdb3878
--- /dev/null
+++ b/packages/odyssey-storybook/src/components/odyssey-mui/Checkbox/Checkbox.stories.tsx
@@ -0,0 +1,163 @@
+/*!
+ * Copyright (c) 2021-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 React from "react";
+import { Story } from "@storybook/react";
+import {
+ Checkbox,
+ FormControl,
+ FormControlLabel,
+ FormGroup,
+ FormHelperText,
+ FormLabel,
+} from "@mui/material";
+import { visuallyHidden } from "@mui/utils";
+import { MuiThemeDecorator } from "../../../../.storybook/components";
+
+import CheckboxMdx from "./Checkbox.mdx";
+
+export default {
+ title: `MUI Components/Checkbox`,
+ component: Checkbox,
+ parameters: {
+ docs: {
+ page: CheckboxMdx,
+ },
+ },
+ argTypes: {
+ defaultChecked: {
+ control: "boolean",
+ defaultValue: false,
+ },
+ disabled: {
+ control: "boolean",
+ defaultValue: false,
+ },
+ error: {
+ control: "text",
+ defaultValue: null,
+ },
+ hint: {
+ control: "text",
+ defaultValue:
+ "Ensure these systems are operating before initiating warp.",
+ },
+ indeterminate: {
+ control: "boolean",
+ defaultValue: false,
+ },
+ invalid: {
+ control: "boolean",
+ defaultValue: false,
+ },
+ label: {
+ control: "text",
+ defaultValue: "Systems check",
+ },
+ },
+ decorators: [MuiThemeDecorator],
+};
+
+const SingleTemplate: Story = (args) => {
+ const {} = args;
+ return (
+
+
+ }
+ label="Pre-flight systems check complete"
+ />
+ {args.error && (
+
+ Error: {args.error}
+
+ )}
+
+ );
+};
+
+export const Single = SingleTemplate.bind({});
+Single.parameters = { controls: { exclude: ["hint", "label"] } };
+Single.args = {};
+
+export const Checked = SingleTemplate.bind({});
+Checked.parameters = { controls: { exclude: ["hint", "label"] } };
+Checked.args = {
+ defaultChecked: true,
+};
+
+export const Indeterminate = SingleTemplate.bind({});
+Indeterminate.parameters = { controls: { exclude: ["hint", "label"] } };
+Indeterminate.args = {
+ indeterminate: true,
+};
+
+const GroupTemplate: Story = (args) => {
+ const {} = args;
+ return (
+
+ Systems check
+ {args.hint && {args.hint}}
+
+ }
+ label="Life support"
+ />
+ }
+ label="Warp core containment"
+ />
+ }
+ label="Cetacean ops"
+ />
+
+ {args.error && (
+
+ Error: {args.error}
+
+ )}
+
+ );
+};
+
+export const Group = GroupTemplate.bind({});
+Group.parameters = {
+ controls: { exclude: ["defaultChecked", "indeterminate"] },
+};
+Group.args = {};
+
+export const Disabled = GroupTemplate.bind({});
+Disabled.parameters = {
+ controls: { exclude: ["defaultChecked", "indeterminate"] },
+};
+Disabled.args = {
+ disabled: true,
+};
+
+export const Error = GroupTemplate.bind({});
+Error.parameters = {
+ controls: { exclude: ["defaultChecked", "indeterminate"] },
+};
+Error.args = {
+ invalid: true,
+ error: "Systems must be checked prior to launch.",
+};
diff --git a/packages/odyssey-storybook/src/components/odyssey-mui/Radio/Radio.mdx b/packages/odyssey-storybook/src/components/odyssey-mui/Radio/Radio.mdx
new file mode 100644
index 0000000000..3ad4ded06e
--- /dev/null
+++ b/packages/odyssey-storybook/src/components/odyssey-mui/Radio/Radio.mdx
@@ -0,0 +1,49 @@
+import { ArgsTable, Canvas, Meta, Story } from "@storybook/addon-docs";
+
+
+
+# Radio
+
+Radios appear as a ring shaped UI accompanied by a caption that allows the user to choose only one option at a time.
+
+## Behavior
+
+Radio Buttons allow users to select one option from a set. Users can click a Radio to make a choice; selecting another will deselect the last.
+
+
+
+## States
+
+The most prominent Radio states are `enabled`, `disabled`, and `invalid`.
+
+### Enabled
+
+Radio Buttons in their "unchecked" state are considered enabled. They are ready for user interaction.
+
+
+
+### Disabled
+
+Disabled inputs are unavailable for interaction and cannot be focused. They can be used when input is disallowed, possibly due to a system state or access restrictions.
+
+Radios may be disabled as a group or individually.
+
+
+
+### Invalid
+
+Radios are invalid when a required input is left unchecked or an incompatible choice has been made.
+
+When indicating a validation error, please use FormHelperText set to `error` to indicate the nature of the problem. Color alone is not an accessible way to signify that something has gone wrong.
+
+Unlike Checkboxes, Radios validate as a group, not individually.
+
+
diff --git a/packages/odyssey-storybook/src/components/odyssey-mui/Radio/Radio.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-mui/Radio/Radio.stories.tsx
new file mode 100644
index 0000000000..473c823eac
--- /dev/null
+++ b/packages/odyssey-storybook/src/components/odyssey-mui/Radio/Radio.stories.tsx
@@ -0,0 +1,109 @@
+/*!
+ * Copyright (c) 2021-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 React from "react";
+import { Story } from "@storybook/react";
+import {
+ FormControl,
+ FormControlLabel,
+ FormHelperText,
+ FormLabel,
+ Radio,
+ RadioGroup,
+} from "@mui/material";
+import { visuallyHidden } from "@mui/utils";
+import { MuiThemeDecorator } from "../../../../.storybook/components";
+
+import RadioMdx from "./Radio.mdx";
+
+export default {
+ title: `MUI Components/Radio`,
+ component: Radio,
+ parameters: {
+ docs: {
+ page: RadioMdx,
+ },
+ },
+ argTypes: {
+ disabled: {
+ control: "boolean",
+ defaultValue: false,
+ },
+ error: {
+ control: "text",
+ defaultValue: null,
+ },
+ hint: {
+ control: "text",
+ defaultValue: "Select the speed at which you wish to travel.",
+ },
+ invalid: {
+ control: "boolean",
+ defaultValue: false,
+ },
+ label: {
+ control: "text",
+ defaultValue: "Speed",
+ },
+ },
+ decorators: [MuiThemeDecorator],
+};
+
+const DefaultTemplate: Story = (args) => {
+ const {} = args;
+ return (
+
+ {args.label}
+ {args.hint && {args.hint}}
+
+ }
+ label="Lightspeed"
+ />
+ }
+ label="Warp speed"
+ />
+ }
+ label="Ludicrous speed"
+ />
+
+ {args.error && (
+
+ Error: {args.error}
+
+ )}
+
+ );
+};
+
+export const Default = DefaultTemplate.bind({});
+Default.args = {};
+
+export const Disabled = DefaultTemplate.bind({});
+Disabled.args = {
+ disabled: true,
+};
+
+export const Invalid = DefaultTemplate.bind({});
+Invalid.args = {
+ invalid: true,
+ error: "This field is required.",
+};
From afbc5b497bf3b9f871d0cf7403efbc9ea247ab6a Mon Sep 17 00:00:00 2001
From: Edbury Enegren <36284167+edburyenegren-okta@users.noreply.github.com>
Date: Fri, 24 Jun 2022 11:37:13 -0700
Subject: [PATCH 05/22] chore: update yarn.lock
---
yarn.lock | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/yarn.lock b/yarn.lock
index d98986d772..239bf08ae8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5182,6 +5182,21 @@ __metadata:
languageName: node
linkType: hard
+"@mui/utils@npm:^5.8.2":
+ version: 5.8.4
+ resolution: "@mui/utils@npm:5.8.4"
+ dependencies:
+ "@babel/runtime": ^7.17.2
+ "@types/prop-types": ^15.7.5
+ "@types/react-is": ^16.7.1 || ^17.0.0
+ prop-types: ^15.8.1
+ react-is: ^17.0.2
+ peerDependencies:
+ react: ^17.0.0 || ^18.0.0
+ checksum: 4d36ff74ee231be7f146bde7bb1f31f717c18f9c2617b5100448d827ac6a4e745645fd035be728ac408604ba58e2b375a96b1d50711801a150b2489c0ff2caf2
+ languageName: node
+ linkType: hard
+
"@nicolo-ribaudo/chokidar-2@npm:2.1.8-no-fsevents.2":
version: 2.1.8-no-fsevents.2
resolution: "@nicolo-ribaudo/chokidar-2@npm:2.1.8-no-fsevents.2"
@@ -5742,6 +5757,7 @@ __metadata:
"@emotion/react": ^11
"@mui/icons-material": ^5
"@mui/material": ^5
+ "@mui/utils": ^5
react: ^17
react-dom: ^17
languageName: unknown
@@ -5828,6 +5844,7 @@ __metadata:
"@applitools/eyes-storybook": ^3.27.6
"@babel/core": ^7.15.0
"@mui/material": ^5.8.2
+ "@mui/utils": ^5.8.2
"@okta/odyssey-babel-loader": ^0.14.1
"@okta/odyssey-design-tokens": ^0.14.1
"@okta/odyssey-lifecycle": ^0.14.1
From 01cef5c3decf4eb55be90597848d25269b99f8e9 Mon Sep 17 00:00:00 2001
From: Odyssey Okta <103765464+odyssey-okta@users.noreply.github.com>
Date: Wed, 22 Jun 2022 12:45:09 -0400
Subject: [PATCH 06/22] build(odyssey-react-mui): update peer deps for react 18
and jsx transform
---
packages/odyssey-react-mui/babel.config.cjs | 6 ------
packages/odyssey-react-mui/package.json | 5 ++---
packages/odyssey-react-mui/src/components/Link/Link.tsx | 2 +-
.../src/components/PasswordInput/PasswordInput.test.tsx | 1 -
.../src/components/PasswordInput/PasswordInput.tsx | 2 +-
packages/odyssey-react-mui/tsconfig.json | 5 ++++-
packages/odyssey-react-mui/tsconfig.production.json | 3 ++-
packages/odyssey-storybook/tsconfig.json | 5 ++++-
yarn.lock | 5 ++---
9 files changed, 16 insertions(+), 18 deletions(-)
diff --git a/packages/odyssey-react-mui/babel.config.cjs b/packages/odyssey-react-mui/babel.config.cjs
index e5c6ecc63b..227a4fe6cc 100644
--- a/packages/odyssey-react-mui/babel.config.cjs
+++ b/packages/odyssey-react-mui/babel.config.cjs
@@ -16,9 +16,6 @@ module.exports = {
"@okta/odyssey-babel-preset",
{
odyssey: false,
- react: {
- runtime: "classic",
- },
},
],
],
@@ -75,9 +72,6 @@ module.exports = {
env: {
modules: false,
},
- react: {
- runtime: "classic",
- },
},
],
],
diff --git a/packages/odyssey-react-mui/package.json b/packages/odyssey-react-mui/package.json
index 0f888caa9a..3beefbac75 100644
--- a/packages/odyssey-react-mui/package.json
+++ b/packages/odyssey-react-mui/package.json
@@ -55,9 +55,8 @@
"@emotion/react": "^11",
"@mui/icons-material": "^5",
"@mui/material": "^5",
- "@mui/utils": "^5",
- "react": "^17",
- "react-dom": "^17"
+ "react": ">=17 <19",
+ "react-dom": ">=17 <19"
},
"scripts": {
"lint": "eslint .",
diff --git a/packages/odyssey-react-mui/src/components/Link/Link.tsx b/packages/odyssey-react-mui/src/components/Link/Link.tsx
index 29ac1d6bd5..82c3e2b6cb 100644
--- a/packages/odyssey-react-mui/src/components/Link/Link.tsx
+++ b/packages/odyssey-react-mui/src/components/Link/Link.tsx
@@ -10,7 +10,7 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React, { forwardRef, ReactElement } from "react";
+import { forwardRef, ReactElement } from "react";
import { Link as MuiLink, SvgIcon } from "@mui/material";
import type { LinkProps as MuiLinkProps } from "@mui/material";
diff --git a/packages/odyssey-react-mui/src/components/PasswordInput/PasswordInput.test.tsx b/packages/odyssey-react-mui/src/components/PasswordInput/PasswordInput.test.tsx
index 334707f59c..a9a1e6c35f 100644
--- a/packages/odyssey-react-mui/src/components/PasswordInput/PasswordInput.test.tsx
+++ b/packages/odyssey-react-mui/src/components/PasswordInput/PasswordInput.test.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import { render, screen } from "@testing-library/react";
import { a11yCheck } from "../../../test";
import { PasswordInput } from ".";
diff --git a/packages/odyssey-react-mui/src/components/PasswordInput/PasswordInput.tsx b/packages/odyssey-react-mui/src/components/PasswordInput/PasswordInput.tsx
index 07a01c54e2..a873bffff5 100644
--- a/packages/odyssey-react-mui/src/components/PasswordInput/PasswordInput.tsx
+++ b/packages/odyssey-react-mui/src/components/PasswordInput/PasswordInput.tsx
@@ -10,7 +10,7 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React, { forwardRef, useState, useMemo } from "react";
+import { forwardRef, useState, useMemo } from "react";
import type { Ref, ChangeEvent, MouseEvent } from "react";
import type { OutlinedInputProps, TooltipProps } from "@mui/material";
import {
diff --git a/packages/odyssey-react-mui/tsconfig.json b/packages/odyssey-react-mui/tsconfig.json
index b03efe2688..4b8b858e23 100644
--- a/packages/odyssey-react-mui/tsconfig.json
+++ b/packages/odyssey-react-mui/tsconfig.json
@@ -1,3 +1,6 @@
{
- "extends": "@okta/odyssey-typescript/tsconfig.react.json"
+ "extends": "@okta/odyssey-typescript/tsconfig.react.json",
+ "compilerOptions": {
+ "jsx": "react-jsx"
+ }
}
diff --git a/packages/odyssey-react-mui/tsconfig.production.json b/packages/odyssey-react-mui/tsconfig.production.json
index b8e153ab91..c04175b842 100644
--- a/packages/odyssey-react-mui/tsconfig.production.json
+++ b/packages/odyssey-react-mui/tsconfig.production.json
@@ -1,7 +1,8 @@
{
"extends": "@okta/odyssey-typescript/tsconfig.react.types.json",
"compilerOptions": {
- "outDir": "dist"
+ "outDir": "dist",
+ "jsx": "react-jsx"
},
"exclude": ["./test", "**/*.test.**", "**/dist/**/*"]
}
diff --git a/packages/odyssey-storybook/tsconfig.json b/packages/odyssey-storybook/tsconfig.json
index b03efe2688..4b8b858e23 100644
--- a/packages/odyssey-storybook/tsconfig.json
+++ b/packages/odyssey-storybook/tsconfig.json
@@ -1,3 +1,6 @@
{
- "extends": "@okta/odyssey-typescript/tsconfig.react.json"
+ "extends": "@okta/odyssey-typescript/tsconfig.react.json",
+ "compilerOptions": {
+ "jsx": "react-jsx"
+ }
}
diff --git a/yarn.lock b/yarn.lock
index 239bf08ae8..ddef183f14 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5757,9 +5757,8 @@ __metadata:
"@emotion/react": ^11
"@mui/icons-material": ^5
"@mui/material": ^5
- "@mui/utils": ^5
- react: ^17
- react-dom: ^17
+ react: ">=17 <19"
+ react-dom: ">=17 <19"
languageName: unknown
linkType: soft
From be5fd4f31d523606011b2fe947a87bc5eccffd6c Mon Sep 17 00:00:00 2001
From: Odyssey Okta <103765464+odyssey-okta@users.noreply.github.com>
Date: Wed, 22 Jun 2022 11:14:24 -0400
Subject: [PATCH 07/22] chore(odyssey-react-mui): use tokens for palette theme
---
.../src/themes/odyssey/palette.ts | 57 +++++++++----------
1 file changed, 28 insertions(+), 29 deletions(-)
diff --git a/packages/odyssey-react-mui/src/themes/odyssey/palette.ts b/packages/odyssey-react-mui/src/themes/odyssey/palette.ts
index adfcfb78c0..f142016322 100644
--- a/packages/odyssey-react-mui/src/themes/odyssey/palette.ts
+++ b/packages/odyssey-react-mui/src/themes/odyssey/palette.ts
@@ -11,48 +11,49 @@
*/
import type { ThemeOptions } from "@mui/material";
+import * as Tokens from "@okta/odyssey-design-tokens";
export const palette: ThemeOptions["palette"] = {
mode: "light",
common: {
- black: "#1d1d21",
- white: "#ffffff",
+ black: Tokens.ColorNeutralDark,
+ white: Tokens.ColorPaletteNeutralWhite,
},
primary: {
- light: "#a7b5ec",
- main: "#1662dd",
- dark: "#00297a",
- contrastText: "#ffffff",
+ light: Tokens.ColorPrimaryLight,
+ main: Tokens.ColorPrimaryBase,
+ dark: Tokens.ColorPrimaryDark,
+ contrastText: Tokens.ColorTextBodyInverse,
},
secondary: {
light: "#80C7CA",
- main: "#2D8C9E",
+ main: Tokens.ColorPaletteTurquoise500,
dark: "#004650",
- contrastText: "#ffffff",
+ contrastText: Tokens.ColorTextBodyInverse,
},
error: {
- light: "#f88c90",
- main: "#da372c",
- dark: "#640019",
- contrastText: "#ffffff",
+ light: Tokens.ColorBackgroundDangerBase,
+ main: Tokens.ColorDangerBase,
+ dark: Tokens.ColorDangerDark,
+ contrastText: Tokens.ColorTextBodyInverse,
},
warning: {
- light: "#f9dc77",
- main: "#ffc61c",
- dark: "#663800",
- contrastText: "#1d1d21",
+ light: Tokens.ColorCautionLight,
+ main: Tokens.ColorCautionBase,
+ dark: Tokens.ColorCautionDark,
+ contrastText: Tokens.ColorTextBody,
},
info: {
- light: "#a7b5ec",
- main: "#1662dd",
- dark: "#00297a",
- contrastText: "#ffffff",
+ light: Tokens.ColorPrimaryLight,
+ main: Tokens.ColorPrimaryBase,
+ dark: Tokens.ColorPrimaryDark,
+ contrastText: Tokens.ColorTextBodyInverse,
},
success: {
light: "#84d2b1",
main: "#00b478",
dark: "#00503c",
- contrastText: "#ffffff",
+ contrastText: Tokens.ColorTextBodyInverse,
},
grey: {
50: "#f5f5f6",
@@ -72,16 +73,14 @@ export const palette: ThemeOptions["palette"] = {
A700: "#585862",
},
text: {
- primary: "#1d1d21",
- secondary: "#6e6e78",
- // We do not currently have a unique disabled color.
- disabled: "#6e6e78",
+ primary: Tokens.ColorNeutralDark,
+ secondary: Tokens.ColorNeutralBase,
+ disabled: Tokens.ColorNeutralBase, // We do not currently have a unique disabled color.
},
- // Currently mapping this to ColorBorderDisplay.
- divider: "#d7d7dc",
+ divider: Tokens.ColorBorderDisplay,
background: {
- paper: "#ffffff",
- default: "#ffffff",
+ paper: Tokens.ColorBackgroundBase,
+ default: Tokens.ColorBackgroundBase,
},
action: {
// We have no equivalents here. It's likely we will update these as their uses are discovered.
From 661e6a1e59d6fec0ed3a39a60c6e26421f5b8be5 Mon Sep 17 00:00:00 2001
From: Odyssey Okta <103765464+odyssey-okta@users.noreply.github.com>
Date: Sat, 25 Jun 2022 18:57:46 -0400
Subject: [PATCH 08/22] chore(odyssey-storybook): update JSX imports
---
.../.storybook/components/Markdown.tsx | 10 ++++------
.../.storybook/components/MuiThemeDecorator.tsx | 1 -
.../.storybook/components/ThemeTable.tsx | 1 -
.../.storybook/components/TokenTables.tsx | 2 +-
.../src/components/MuiButton/MuiButton.stories.tsx | 1 -
.../src/components/MuiLink/MuiLink.stories.tsx | 1 -
.../odyssey-legacy/Banner/Banner.stories.tsx | 1 -
.../src/components/odyssey-legacy/Box/Box.docgen.tsx | 2 +-
.../src/components/odyssey-legacy/Box/Box.stories.tsx | 2 +-
.../odyssey-legacy/Button/Button.stories.tsx | 1 -
.../odyssey-legacy/Checkbox/Checkbox.stories.tsx | 2 +-
.../CircularLoadIndicator.stories.tsx | 1 -
.../components/odyssey-legacy/Field/Field.stories.tsx | 1 -
.../odyssey-legacy/FieldGroup/FieldGroup.stories.tsx | 1 -
.../components/odyssey-legacy/Form/Form.stories.tsx | 1 -
.../odyssey-legacy/Heading/Heading.stories.tsx | 1 -
.../components/odyssey-legacy/Icon/Icon.stories.tsx | 1 -
.../odyssey-legacy/Infobox/Infobox.stories.tsx | 1 -
.../components/odyssey-legacy/Link/Link.stories.tsx | 1 -
.../components/odyssey-legacy/List/List.stories.tsx | 1 -
.../components/odyssey-legacy/Modal/Modal.stories.tsx | 1 -
.../NativeSelect/NativeSelect.stories.tsx | 1 -
.../components/odyssey-legacy/Radio/Radio.stories.tsx | 1 -
.../ScreenReaderText/ScreenReaderText.stories.tsx | 1 -
.../odyssey-legacy/Select/Select.stories.tsx | 1 -
.../odyssey-legacy/Status/Status.stories.tsx | 1 -
.../components/odyssey-legacy/Table/Table.stories.tsx | 1 -
.../components/odyssey-legacy/Tabs/Tabs.stories.tsx | 1 -
.../odyssey-legacy/TagList/TagList.stories.tsx | 1 -
.../odyssey-legacy/Text/TextElements.stories.tsx | 1 -
.../odyssey-legacy/Text/TextStyles.stories.tsx | 1 -
.../odyssey-legacy/TextArea/TextArea.stories.tsx | 1 -
.../odyssey-legacy/TextInput/TextInput.stories.tsx | 1 -
.../components/odyssey-legacy/Toast/Toast.stories.tsx | 1 -
.../odyssey-legacy/Tooltip/Tooltip.stories.tsx | 1 -
.../odyssey-mui/Checkbox/Checkbox.stories.tsx | 1 -
.../CircularProgress/CircularProgress.stories.tsx | 1 -
.../PasswordInput/PasswordInput.stories.tsx | 2 +-
.../src/components/odyssey-mui/Radio/Radio.stories.tsx | 1 -
.../odyssey-mui/Typography/Typography.stories.tsx | 1 -
40 files changed, 9 insertions(+), 45 deletions(-)
diff --git a/packages/odyssey-storybook/.storybook/components/Markdown.tsx b/packages/odyssey-storybook/.storybook/components/Markdown.tsx
index 01cd1ac4c3..9e5c1f2ab3 100644
--- a/packages/odyssey-storybook/.storybook/components/Markdown.tsx
+++ b/packages/odyssey-storybook/.storybook/components/Markdown.tsx
@@ -1,4 +1,4 @@
-import React from "react";
+import type { ReactNode } from "react";
import { default as MarkdownToJSX } from "markdown-to-jsx";
import { components } from "@storybook/components";
@@ -14,8 +14,6 @@ const overrides = Object.entries(components).reduce(
Object.create(null)
);
-export const Markdown = ({
- content,
-}: {
- content: string & React.ReactNode;
-}) => ;
+export const Markdown = ({ content }: { content: string & ReactNode }) => (
+
+);
diff --git a/packages/odyssey-storybook/.storybook/components/MuiThemeDecorator.tsx b/packages/odyssey-storybook/.storybook/components/MuiThemeDecorator.tsx
index f638d908ad..af54ca36ec 100644
--- a/packages/odyssey-storybook/.storybook/components/MuiThemeDecorator.tsx
+++ b/packages/odyssey-storybook/.storybook/components/MuiThemeDecorator.tsx
@@ -1,4 +1,3 @@
-import React from "react";
import { ThemeProvider as MuiThemeProvider } from "@mui/material/styles";
import { CssBaseline } from "@mui/material";
import { ThemeProvider } from "@storybook/theming";
diff --git a/packages/odyssey-storybook/.storybook/components/ThemeTable.tsx b/packages/odyssey-storybook/.storybook/components/ThemeTable.tsx
index 8613b37cc9..192afdec42 100644
--- a/packages/odyssey-storybook/.storybook/components/ThemeTable.tsx
+++ b/packages/odyssey-storybook/.storybook/components/ThemeTable.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import type { ReactNode } from "react";
import type { Theme, ThemeReducer } from "@okta/odyssey-react-theme";
import { tokens } from "@okta/odyssey-react-theme/dist/ThemeProvider/context";
diff --git a/packages/odyssey-storybook/.storybook/components/TokenTables.tsx b/packages/odyssey-storybook/.storybook/components/TokenTables.tsx
index 234fb2e41f..aec7e54532 100644
--- a/packages/odyssey-storybook/.storybook/components/TokenTables.tsx
+++ b/packages/odyssey-storybook/.storybook/components/TokenTables.tsx
@@ -10,7 +10,7 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React, { useState, useEffect } from "react";
+import { useState, useEffect } from "react";
import type { ReactNode } from "react";
import * as Tokens from "@okta/odyssey-design-tokens";
import { Table, Text } from "@okta/odyssey-react";
diff --git a/packages/odyssey-storybook/src/components/MuiButton/MuiButton.stories.tsx b/packages/odyssey-storybook/src/components/MuiButton/MuiButton.stories.tsx
index a4a6ffd5d2..b834c98e5f 100644
--- a/packages/odyssey-storybook/src/components/MuiButton/MuiButton.stories.tsx
+++ b/packages/odyssey-storybook/src/components/MuiButton/MuiButton.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import type { Story } from "@storybook/react";
import { Button } from "@mui/material";
diff --git a/packages/odyssey-storybook/src/components/MuiLink/MuiLink.stories.tsx b/packages/odyssey-storybook/src/components/MuiLink/MuiLink.stories.tsx
index f2544bf7f8..33f6c38a06 100644
--- a/packages/odyssey-storybook/src/components/MuiLink/MuiLink.stories.tsx
+++ b/packages/odyssey-storybook/src/components/MuiLink/MuiLink.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import type { Story } from "@storybook/react";
import { MuiThemeDecorator } from "../../../.storybook/components/MuiThemeDecorator";
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/Banner/Banner.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Banner/Banner.stories.tsx
index 827eff5067..3d9954a9fd 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/Banner/Banner.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Banner/Banner.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import { Story } from "@storybook/react";
import { useArgs } from "@storybook/client-api";
import { Banner, BannerProps, Link } from "../../../../../odyssey-react/src";
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/Box/Box.docgen.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Box/Box.docgen.tsx
index c9b335fef5..dfb9a42ec4 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/Box/Box.docgen.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Box/Box.docgen.tsx
@@ -10,7 +10,7 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React, { forwardRef } from "react";
+import { forwardRef } from "react";
import type { BoxProps } from "../../../../../odyssey-react/src";
export const BoxDocGen = forwardRef(() => <>>);
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/Box/Box.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Box/Box.stories.tsx
index a87f9d2d17..ae2ca883bd 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/Box/Box.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Box/Box.stories.tsx
@@ -10,7 +10,7 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React, { ReactElement } from "react";
+import { ReactElement } from "react";
import { Story } from "@storybook/react";
import { BoxDocGen } from "./Box.docgen";
import { Box, BoxProps, Heading, Text } from "../../../../../odyssey-react/src";
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/Button/Button.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Button/Button.stories.tsx
index af54f55f9b..4ac9eac57a 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/Button/Button.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Button/Button.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import { Story } from "@storybook/react";
import {
Button,
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/Checkbox/Checkbox.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Checkbox/Checkbox.stories.tsx
index 141d8d751f..ee19e55622 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/Checkbox/Checkbox.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Checkbox/Checkbox.stories.tsx
@@ -10,7 +10,7 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React, { useEffect } from "react";
+import { useEffect } from "react";
import type { Story } from "@storybook/react";
import {
Checkbox,
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/CircularLoadIndicator/CircularLoadIndicator.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/CircularLoadIndicator/CircularLoadIndicator.stories.tsx
index 5bbf140620..8a2ef0296d 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/CircularLoadIndicator/CircularLoadIndicator.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/CircularLoadIndicator/CircularLoadIndicator.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import type { Story } from "@storybook/react";
import {
CircularLoadIndicator,
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/Field/Field.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Field/Field.stories.tsx
index b228450f7a..e48eaa01ef 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/Field/Field.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Field/Field.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import { Story } from "@storybook/react";
import { FieldDocGen } from "./Field.docgen";
import {
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/FieldGroup/FieldGroup.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/FieldGroup/FieldGroup.stories.tsx
index 8ef3afd318..9c3dbab031 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/FieldGroup/FieldGroup.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/FieldGroup/FieldGroup.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import { Story } from "@storybook/react";
import {
FieldGroup,
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/Form/Form.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Form/Form.stories.tsx
index 16103bb1b4..bc76a7c53e 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/Form/Form.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Form/Form.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import { Story } from "@storybook/react";
import {
Form,
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/Heading/Heading.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Heading/Heading.stories.tsx
index 97a0f71a71..a388e6faa7 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/Heading/Heading.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Heading/Heading.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import { Story } from "@storybook/react";
import { Heading, HeadingProps } from "../../../../../odyssey-react/src";
import HeadingMdx from "./Heading.mdx";
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/Icon/Icon.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Icon/Icon.stories.tsx
index 09415c0674..b130aeb044 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/Icon/Icon.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Icon/Icon.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import { Story } from "@storybook/react";
import * as IconIndex from "../../../../../odyssey-react/src/components/Icon";
import { Icon, Table } from "../../../../../odyssey-react/src";
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/Infobox/Infobox.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Infobox/Infobox.stories.tsx
index bf2e7e7222..25800e0988 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/Infobox/Infobox.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Infobox/Infobox.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import { Story } from "@storybook/react";
import {
Infobox,
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/Link/Link.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Link/Link.stories.tsx
index 054d532087..73c7c80bba 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/Link/Link.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Link/Link.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import type { Story } from "@storybook/react";
import {
Link,
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/List/List.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/List/List.stories.tsx
index f49044d39a..b6389b353b 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/List/List.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/List/List.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import type { ReactElement, ReactText, KeyboardEvent } from "react";
import type { Story } from "@storybook/react";
import {
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/Modal/Modal.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Modal/Modal.stories.tsx
index 8e1d641f09..4a82766919 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/Modal/Modal.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Modal/Modal.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import { Story } from "@storybook/react";
import { useArgs } from "@storybook/client-api";
import {
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/NativeSelect/NativeSelect.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/NativeSelect/NativeSelect.stories.tsx
index 583dfca871..d8d3a6bbde 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/NativeSelect/NativeSelect.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/NativeSelect/NativeSelect.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import type { Story } from "@storybook/react";
import {
NativeSelect,
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/Radio/Radio.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Radio/Radio.stories.tsx
index 118bd5fbaf..aaf60f80f7 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/Radio/Radio.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Radio/Radio.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import type { Story } from "@storybook/react";
import { Radio, RadioGroupProps } from "../../../../../odyssey-react/src";
import RadioMdx from "./Radio.mdx";
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/ScreenReaderText/ScreenReaderText.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/ScreenReaderText/ScreenReaderText.stories.tsx
index ff767f38c9..5e7a7269dc 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/ScreenReaderText/ScreenReaderText.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/ScreenReaderText/ScreenReaderText.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import type { Story } from "@storybook/react";
import {
ScreenReaderText,
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/Select/Select.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Select/Select.stories.tsx
index 524cc48d55..b9b23b8f1c 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/Select/Select.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Select/Select.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import type { Story } from "@storybook/react";
import type { ReactElement } from "react";
import { Select, SelectProps } from "../../../../../odyssey-react/src";
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/Status/Status.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Status/Status.stories.tsx
index d2f8a438b0..7eee072c56 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/Status/Status.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Status/Status.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import type { Story } from "@storybook/react";
import { Status, StatusProps } from "../../../../../odyssey-react/src";
import StatusMdx from "./Status.mdx";
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/Table/Table.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Table/Table.stories.tsx
index 9616599dea..d393183bbe 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/Table/Table.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Table/Table.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import type { Story } from "@storybook/react";
import type { ReactElement } from "react";
import {
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/Tabs/Tabs.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Tabs/Tabs.stories.tsx
index 6243db3d9c..6a3dc4e05e 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/Tabs/Tabs.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Tabs/Tabs.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import { Story } from "@storybook/react";
import { Tabs, TabsProps } from "../../../../../odyssey-react/src";
import TabsMdx from "./Tabs.mdx";
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/TagList/TagList.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/TagList/TagList.stories.tsx
index 8efcaac8f5..6ca24399a9 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/TagList/TagList.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/TagList/TagList.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import type { Story } from "@storybook/react";
import { TagList, TagListProps } from "../../../../../odyssey-react/src";
import TagListMdx from "./TagList.mdx";
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/Text/TextElements.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Text/TextElements.stories.tsx
index f7dbc67575..e4c70ebc41 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/Text/TextElements.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Text/TextElements.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import { Story } from "@storybook/react";
import {
Text,
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/Text/TextStyles.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Text/TextStyles.stories.tsx
index 1b74949dde..ea139208e8 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/Text/TextStyles.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Text/TextStyles.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import { Story } from "@storybook/react";
import { Text, TextProps } from "../../../../../odyssey-react/src";
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/TextArea/TextArea.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/TextArea/TextArea.stories.tsx
index c05addc331..475f879c8e 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/TextArea/TextArea.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/TextArea/TextArea.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import type { Story } from "@storybook/react";
import { TextArea, TextAreaProps } from "../../../../../odyssey-react/src";
import TextAreaMdx from "./TextArea.mdx";
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/TextInput/TextInput.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/TextInput/TextInput.stories.tsx
index d7170e752c..8488c4b4eb 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/TextInput/TextInput.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/TextInput/TextInput.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import type { Story } from "@storybook/react";
import { TextInput, TextInputProps } from "../../../../../odyssey-react/src";
import TextInputMdx from "./TextInput.mdx";
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/Toast/Toast.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Toast/Toast.stories.tsx
index d44f7d09e8..82ab0cdb8d 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/Toast/Toast.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Toast/Toast.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import { Story } from "@storybook/react";
import { FormEventHandler } from "react";
import {
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/Tooltip/Tooltip.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Tooltip/Tooltip.stories.tsx
index a249bec252..83380f23bd 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/Tooltip/Tooltip.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Tooltip/Tooltip.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import type { Story } from "@storybook/react";
import { action } from "@storybook/addon-actions";
import {
diff --git a/packages/odyssey-storybook/src/components/odyssey-mui/Checkbox/Checkbox.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-mui/Checkbox/Checkbox.stories.tsx
index 306cdb3878..eb92e98639 100644
--- a/packages/odyssey-storybook/src/components/odyssey-mui/Checkbox/Checkbox.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-mui/Checkbox/Checkbox.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import { Story } from "@storybook/react";
import {
Checkbox,
diff --git a/packages/odyssey-storybook/src/components/odyssey-mui/CircularProgress/CircularProgress.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-mui/CircularProgress/CircularProgress.stories.tsx
index 8bf0b4570d..c035623aba 100644
--- a/packages/odyssey-storybook/src/components/odyssey-mui/CircularProgress/CircularProgress.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-mui/CircularProgress/CircularProgress.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import { Story } from "@storybook/react";
import { CircularProgress, CircularProgressProps } from "@mui/material";
import { MuiThemeDecorator } from "../../../../.storybook/components";
diff --git a/packages/odyssey-storybook/src/components/odyssey-mui/PasswordInput/PasswordInput.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-mui/PasswordInput/PasswordInput.stories.tsx
index 2623bdeb9c..74e7ceb1b5 100644
--- a/packages/odyssey-storybook/src/components/odyssey-mui/PasswordInput/PasswordInput.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-mui/PasswordInput/PasswordInput.stories.tsx
@@ -10,7 +10,7 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React, { ReactElement } from "react";
+import { ReactElement } from "react";
import type { Story } from "@storybook/react";
import { PasswordInput, PasswordInputProps } from "@okta/odyssey-react-mui";
import {
diff --git a/packages/odyssey-storybook/src/components/odyssey-mui/Radio/Radio.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-mui/Radio/Radio.stories.tsx
index 473c823eac..3a6efab503 100644
--- a/packages/odyssey-storybook/src/components/odyssey-mui/Radio/Radio.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-mui/Radio/Radio.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import { Story } from "@storybook/react";
import {
FormControl,
diff --git a/packages/odyssey-storybook/src/components/odyssey-mui/Typography/Typography.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-mui/Typography/Typography.stories.tsx
index fc88e6c2f2..e55713c24c 100644
--- a/packages/odyssey-storybook/src/components/odyssey-mui/Typography/Typography.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-mui/Typography/Typography.stories.tsx
@@ -10,7 +10,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React from "react";
import { Story } from "@storybook/react";
import { Typography, TypographyProps } from "@mui/material";
import { MuiThemeDecorator } from "../../../../.storybook/components";
From 9f2aaa2bf8af744391ce36945f2731052af19665 Mon Sep 17 00:00:00 2001
From: Odyssey Okta <103765464+odyssey-okta@users.noreply.github.com>
Date: Sat, 25 Jun 2022 21:07:20 -0400
Subject: [PATCH 09/22] build(odyssey-storybook): support classic jsx transform
for odyssey-react
---
packages/odyssey-react/tsconfig.production.json | 4 +++-
packages/odyssey-storybook/.storybook/main.js | 11 ++++++++++-
packages/odyssey-storybook/tsconfig.json | 1 +
3 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/packages/odyssey-react/tsconfig.production.json b/packages/odyssey-react/tsconfig.production.json
index aa23b1c239..7b94c60a7c 100644
--- a/packages/odyssey-react/tsconfig.production.json
+++ b/packages/odyssey-react/tsconfig.production.json
@@ -1,7 +1,9 @@
{
"extends": "@okta/odyssey-typescript/tsconfig.react.types.json",
"compilerOptions": {
- "outDir": "dist"
+ "outDir": "dist",
+ "composite": true,
+ "jsx": "react"
},
"exclude": ["**/*.test.**", "**/dist/**/*"]
}
diff --git a/packages/odyssey-storybook/.storybook/main.js b/packages/odyssey-storybook/.storybook/main.js
index 408cc52484..2593dee55f 100644
--- a/packages/odyssey-storybook/.storybook/main.js
+++ b/packages/odyssey-storybook/.storybook/main.js
@@ -67,7 +67,16 @@ function buildRules(rules) {
loader: "@okta/odyssey-babel-loader",
options: {
cacheDirectory: false,
- presets: ["@okta/odyssey-babel-preset"],
+ presets: [
+ [
+ "@okta/odyssey-babel-preset",
+ {
+ react: {
+ runtime: "classic",
+ },
+ },
+ ],
+ ],
},
});
}
diff --git a/packages/odyssey-storybook/tsconfig.json b/packages/odyssey-storybook/tsconfig.json
index 4b8b858e23..915fb4a45d 100644
--- a/packages/odyssey-storybook/tsconfig.json
+++ b/packages/odyssey-storybook/tsconfig.json
@@ -1,5 +1,6 @@
{
"extends": "@okta/odyssey-typescript/tsconfig.react.json",
+ "references": [{ "path": "../odyssey-react/tsconfig.production.json" }],
"compilerOptions": {
"jsx": "react-jsx"
}
From fe5a934cd085ec18c8a691a761ac67c4f65d63d9 Mon Sep 17 00:00:00 2001
From: Odyssey Okta <103765464+odyssey-okta@users.noreply.github.com>
Date: Tue, 28 Jun 2022 09:57:19 -0400
Subject: [PATCH 10/22] build: fix tsconfig composite configuration
---
.gitignore | 5 +++--
.prettierignore | 5 +++--
packages/odyssey-eslint-config/src/index.js | 2 +-
packages/odyssey-react-mui/babel.config.cjs | 6 ++++++
packages/odyssey-react/package.json | 2 +-
packages/odyssey-react/tsconfig.composite.json | 8 ++++++++
packages/odyssey-react/tsconfig.production.json | 6 ++----
packages/odyssey-storybook/tsconfig.json | 2 +-
8 files changed, 25 insertions(+), 11 deletions(-)
create mode 100644 packages/odyssey-react/tsconfig.composite.json
diff --git a/.gitignore b/.gitignore
index bf25ec00fa..52eb23d4d6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,9 +1,10 @@
.DS_Store
-dist
+dist/
+dist-composite/
node_modules/
npm-debug.log
package-lock.json
-storybook-static
+storybook-static/
yarn-error.log
**/coverage
.pnp.*
diff --git a/.prettierignore b/.prettierignore
index 6625fd8d96..5eb7606ff8 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1,9 +1,10 @@
.DS_Store
-dist
+dist/
+dist-composite/
node_modules/
npm-debug.log
package-lock.json
-storybook-static
+storybook-static/
yarn-error.log
**/coverage
.pnp.*
diff --git a/packages/odyssey-eslint-config/src/index.js b/packages/odyssey-eslint-config/src/index.js
index aaf47696e3..8e1c0d54eb 100644
--- a/packages/odyssey-eslint-config/src/index.js
+++ b/packages/odyssey-eslint-config/src/index.js
@@ -23,7 +23,7 @@ module.exports = {
ecmaVersion: 2018,
sourceType: "module",
},
- ignorePatterns: ["node_modules", "dist"],
+ ignorePatterns: ["node_modules", "dist", "dist-composite"],
plugins: ["header", "import", "@okta/odyssey"],
rules: {
"header/header": [
diff --git a/packages/odyssey-react-mui/babel.config.cjs b/packages/odyssey-react-mui/babel.config.cjs
index 227a4fe6cc..bb99b3f068 100644
--- a/packages/odyssey-react-mui/babel.config.cjs
+++ b/packages/odyssey-react-mui/babel.config.cjs
@@ -16,6 +16,9 @@ module.exports = {
"@okta/odyssey-babel-preset",
{
odyssey: false,
+ react: {
+ runtime: "automatic",
+ },
},
],
],
@@ -72,6 +75,9 @@ module.exports = {
env: {
modules: false,
},
+ react: {
+ runtime: "automatic",
+ },
},
],
],
diff --git a/packages/odyssey-react/package.json b/packages/odyssey-react/package.json
index 00e63fdb19..4bae68d2bb 100644
--- a/packages/odyssey-react/package.json
+++ b/packages/odyssey-react/package.json
@@ -67,7 +67,7 @@
"typecheck": "tsc",
"build": "yarn build:clean && yarn build:types && yarn build:source",
"build:clean": "rm -rf dist",
- "build:types": "tsc --project tsconfig.production.json",
+ "build:types": "tsc --project tsconfig.composite.json && tsc --project tsconfig.production.json",
"build:source": "./scripts/buildSource",
"build-icons": "svgr $(node ./scripts/resolveIconSrcPath.cjs) --out-dir ./src/components/Icon/",
"prepack": "yarn exec prepack"
diff --git a/packages/odyssey-react/tsconfig.composite.json b/packages/odyssey-react/tsconfig.composite.json
new file mode 100644
index 0000000000..ae9a0e8b28
--- /dev/null
+++ b/packages/odyssey-react/tsconfig.composite.json
@@ -0,0 +1,8 @@
+{
+ "extends": "@okta/odyssey-typescript/tsconfig.react.types.json",
+ "compilerOptions": {
+ "outDir": "dist-composite",
+ "composite": true
+ },
+ "exclude": ["**/*.test.**", "**/dist/**/*", "**/dist-composite/**/*"]
+}
diff --git a/packages/odyssey-react/tsconfig.production.json b/packages/odyssey-react/tsconfig.production.json
index 7b94c60a7c..eeffa169a8 100644
--- a/packages/odyssey-react/tsconfig.production.json
+++ b/packages/odyssey-react/tsconfig.production.json
@@ -1,9 +1,7 @@
{
"extends": "@okta/odyssey-typescript/tsconfig.react.types.json",
"compilerOptions": {
- "outDir": "dist",
- "composite": true,
- "jsx": "react"
+ "outDir": "dist"
},
- "exclude": ["**/*.test.**", "**/dist/**/*"]
+ "exclude": ["**/*.test.**", "**/dist/**/*", "**/dist-composite-/**/*"]
}
diff --git a/packages/odyssey-storybook/tsconfig.json b/packages/odyssey-storybook/tsconfig.json
index 915fb4a45d..c84cdd0f78 100644
--- a/packages/odyssey-storybook/tsconfig.json
+++ b/packages/odyssey-storybook/tsconfig.json
@@ -1,6 +1,6 @@
{
"extends": "@okta/odyssey-typescript/tsconfig.react.json",
- "references": [{ "path": "../odyssey-react/tsconfig.production.json" }],
+ "references": [{ "path": "../odyssey-react/tsconfig.composite.json" }],
"compilerOptions": {
"jsx": "react-jsx"
}
From 970acab56ef7a85904f2e3759590f60c384b7e68 Mon Sep 17 00:00:00 2001
From: Edbury Enegren <36284167+edburyenegren-okta@users.noreply.github.com>
Date: Mon, 27 Jun 2022 09:47:44 -0700
Subject: [PATCH 11/22] chore: add @kamronbatmanghelich-okta to codeowners
---
.github/CODEOWNERS | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 42b2d9b3c5..04181d6541 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -9,4 +9,4 @@
# Resources
# - [CODEOWNERS] https://help.github.com/articles/about-codeowners
-* @okta/design-system @ganeshsomasundaram-okta @KevinGhadyani-Okta @odyssey-okta
+* @okta/design-system @ganeshsomasundaram-okta @KevinGhadyani-Okta @odyssey-okta @kamronbatmanghelich-okta
\ No newline at end of file
From d44a241537fa84fcf7679b7e96e52655d83d846f Mon Sep 17 00:00:00 2001
From: Sunny Little
Date: Sun, 10 Apr 2022 18:32:30 -0700
Subject: [PATCH 12/22] feat(odyssey-icons): add eye and eye off icons
---
.prettierignore | 8 +-
package.json | 4 +-
packages/odyssey-icons/figma/eye-off.svg | 3 +
packages/odyssey-icons/figma/eye.svg | 3 +
packages/odyssey-icons/src/eye-off.svg | 1 +
packages/odyssey-icons/src/eye.svg | 1 +
packages/odyssey-lint-staged/src/index.js | 2 +-
.../src/components/Button/Button.module.scss | 25 +++
.../src/components/Button/Button.theme.ts | 12 ++
.../src/components/Button/Button.tsx | 12 +-
.../odyssey-react/src/components/Icon/Eye.tsx | 38 +++++
.../src/components/Icon/EyeOff.tsx | 40 +++++
.../src/components/Icon/index.tsx | 8 +
.../PasswordInput/PasswordInput.test.tsx | 50 ++++++
.../PasswordInput/PasswordInput.tsx | 98 ++++++++++++
.../src/components/PasswordInput/index.ts | 13 ++
.../SearchInput/SearchInput.module.scss | 21 +++
.../SearchInput/SearchInput.test.tsx | 78 +++++++++
.../SearchInput/SearchInput.theme.ts | 15 ++
.../components/SearchInput/SearchInput.tsx | 130 +++++++++++++++
.../src/components/SearchInput/index.ts | 13 ++
.../src/components/TextInput/Affix.tsx | 46 ++++++
.../TextInput/TextInput.module.scss | 77 ++++++---
.../components/TextInput/TextInput.test.tsx | 45 ++++--
.../components/TextInput/TextInput.theme.ts | 2 +-
.../src/components/TextInput/TextInput.tsx | 150 +++++++++++-------
.../odyssey-react/src/components/index.ts | 2 +
.../odyssey-legacy/Button/Button.stories.tsx | 8 +
.../FieldGroup/FieldGroup.stories.tsx | 4 +-
.../odyssey-legacy/Icon/Icon.stories.tsx | 2 +
.../Infobox/Infobox.stories.tsx | 9 +-
.../PasswordInput/PasswordInput.mdx | 45 ++++++
.../PasswordInput/PasswordInput.stories.tsx | 63 ++++++++
.../SearchInput/SearchInput.mdx | 49 ++++++
.../SearchInput/SearchInput.stories.tsx | 71 +++++++++
.../TextInput/TextInput.stories.tsx | 38 +++--
36 files changed, 1072 insertions(+), 114 deletions(-)
create mode 100644 packages/odyssey-icons/figma/eye-off.svg
create mode 100644 packages/odyssey-icons/figma/eye.svg
create mode 100644 packages/odyssey-icons/src/eye-off.svg
create mode 100644 packages/odyssey-icons/src/eye.svg
create mode 100644 packages/odyssey-react/src/components/Icon/Eye.tsx
create mode 100644 packages/odyssey-react/src/components/Icon/EyeOff.tsx
create mode 100644 packages/odyssey-react/src/components/PasswordInput/PasswordInput.test.tsx
create mode 100644 packages/odyssey-react/src/components/PasswordInput/PasswordInput.tsx
create mode 100644 packages/odyssey-react/src/components/PasswordInput/index.ts
create mode 100644 packages/odyssey-react/src/components/SearchInput/SearchInput.module.scss
create mode 100644 packages/odyssey-react/src/components/SearchInput/SearchInput.test.tsx
create mode 100644 packages/odyssey-react/src/components/SearchInput/SearchInput.theme.ts
create mode 100644 packages/odyssey-react/src/components/SearchInput/SearchInput.tsx
create mode 100644 packages/odyssey-react/src/components/SearchInput/index.ts
create mode 100644 packages/odyssey-react/src/components/TextInput/Affix.tsx
create mode 100644 packages/odyssey-storybook/src/components/odyssey-legacy/PasswordInput/PasswordInput.mdx
create mode 100644 packages/odyssey-storybook/src/components/odyssey-legacy/PasswordInput/PasswordInput.stories.tsx
create mode 100644 packages/odyssey-storybook/src/components/odyssey-legacy/SearchInput/SearchInput.mdx
create mode 100644 packages/odyssey-storybook/src/components/odyssey-legacy/SearchInput/SearchInput.stories.tsx
diff --git a/.prettierignore b/.prettierignore
index 5eb7606ff8..8488355786 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -9,4 +9,10 @@ yarn-error.log
**/coverage
.pnp.*
.yarn/*
-.git/*
+!.yarn/patches
+!.yarn/plugins
+!.yarn/releases
+!.yarn/sdks
+!.yarn/versions
+packages/odyssey-react/src/components/PasswordInput/PasswordInput.tsx
+packages/odyssey-react/src/components/SearchInput/SearchInput.tsx
\ No newline at end of file
diff --git a/package.json b/package.json
index 196f1ab12d..2d521b8109 100644
--- a/package.json
+++ b/package.json
@@ -19,8 +19,8 @@
"lerna-version": "lerna version --no-git-tag-version --include-merged-tags --conventional-commits --no-push --force-publish",
"lerna-publish": "lerna publish from-package --no-push --force-publish --no-verify-access --no-verify-registry",
"lint": "yarn eslint && yarn stylelint && yarn prettier-check",
- "prettier-check": "prettier --no-config --ignore-unknown --loglevel warn --check .",
- "prettier-write": "prettier --no-config --ignore-unknown --loglevel warn --write .",
+ "prettier-check": "prettier --ignore-unknown --loglevel warn --check .",
+ "prettier-write": "prettier --ignore-unknown --loglevel warn --write .",
"eslint": "eslint . --ext .js,.jsx,.ts,.tsx",
"stylelint": "stylelint **/*.scss",
"test": "lerna run test",
diff --git a/packages/odyssey-icons/figma/eye-off.svg b/packages/odyssey-icons/figma/eye-off.svg
new file mode 100644
index 0000000000..25bb430fd2
--- /dev/null
+++ b/packages/odyssey-icons/figma/eye-off.svg
@@ -0,0 +1,3 @@
+
diff --git a/packages/odyssey-icons/figma/eye.svg b/packages/odyssey-icons/figma/eye.svg
new file mode 100644
index 0000000000..941a63f537
--- /dev/null
+++ b/packages/odyssey-icons/figma/eye.svg
@@ -0,0 +1,3 @@
+
diff --git a/packages/odyssey-icons/src/eye-off.svg b/packages/odyssey-icons/src/eye-off.svg
new file mode 100644
index 0000000000..48b3c4e79c
--- /dev/null
+++ b/packages/odyssey-icons/src/eye-off.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/odyssey-icons/src/eye.svg b/packages/odyssey-icons/src/eye.svg
new file mode 100644
index 0000000000..eb807bb54b
--- /dev/null
+++ b/packages/odyssey-icons/src/eye.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/odyssey-lint-staged/src/index.js b/packages/odyssey-lint-staged/src/index.js
index a496a2590d..488a3bae69 100644
--- a/packages/odyssey-lint-staged/src/index.js
+++ b/packages/odyssey-lint-staged/src/index.js
@@ -11,7 +11,7 @@
*/
module.exports = {
- "*": "prettier --no-config --ignore-unknown --loglevel warn --write",
+ "*": "prettier --ignore-unknown --loglevel warn --write",
"*.scss": "stylelint",
"*.{js,jsx,ts,tsx}": "eslint",
};
diff --git a/packages/odyssey-react/src/components/Button/Button.module.scss b/packages/odyssey-react/src/components/Button/Button.module.scss
index 6dc49dfe7a..5764190c45 100644
--- a/packages/odyssey-react/src/components/Button/Button.module.scss
+++ b/packages/odyssey-react/src/components/Button/Button.module.scss
@@ -150,6 +150,31 @@
}
}
+.affixVariant {
+ border: 0;
+ background-color: var(--AffixBackgroundColor);
+ color: var(--AffixTextColor);
+ line-height: 1;
+ padding-block: var(--AffixPadding);
+ padding-inline: var(--AffixPadding);
+
+ &:hover {
+ border-color: var(--AffixHoverBorderColor);
+ background-color: var(--AffixHoverBackgroundColor);
+ color: var(--AffixHoverTextColor);
+ }
+
+ &:focus {
+ background-color: var(--AffixFocusBackgroundColor);
+ color: var(--AffixFocusTextColor);
+ }
+
+ &:disabled {
+ background-color: var(--AffixDisabledBackgroundColor);
+ color: var(--AffixDisabledTextColor);
+ }
+}
+
/* Layouts */
.wideLayout {
diff --git a/packages/odyssey-react/src/components/Button/Button.theme.ts b/packages/odyssey-react/src/components/Button/Button.theme.ts
index a6bc42dd36..4a24d1f8e8 100644
--- a/packages/odyssey-react/src/components/Button/Button.theme.ts
+++ b/packages/odyssey-react/src/components/Button/Button.theme.ts
@@ -83,6 +83,18 @@ export const theme: ThemeReducer = (theme) => ({
FloatingHoverBackgroundColor: "rgba(29, 29, 33, 0.1)",
FloatingDisabledBackgroundColor: "rgba(235, 235, 237, 0.6)",
+ // Affix Variant
+ AffixBackgroundColor: "transparent",
+ AffixDisabledBackgroundColor: "transparent",
+ AffixDisabledTextColor: theme.ColorPaletteNeutral500,
+ AffixFocusBackgroundColor: theme.ColorPaletteNeutral200,
+ AffixFocusTextColor: theme.ColorTextBody,
+ AffixHoverBackgroundColor: theme.ColorPaletteNeutral200,
+ AffixHoverBorderColor: "transparent",
+ AffixHoverTextColor: theme.ColorTextBody,
+ AffixPadding: theme.SpaceScale0,
+ AffixTextColor: theme.ColorTextBody,
+
// Wide Layout
WideLayoutMarginBlock: 0,
WideLayoutMarginBlockEnd: theme.SpaceScale3,
diff --git a/packages/odyssey-react/src/components/Button/Button.tsx b/packages/odyssey-react/src/components/Button/Button.tsx
index 407c706c36..7a0903cf30 100644
--- a/packages/odyssey-react/src/components/Button/Button.tsx
+++ b/packages/odyssey-react/src/components/Button/Button.tsx
@@ -43,7 +43,7 @@ interface CommonProps
* The visual variant to be displayed to the user.
* @default primary
*/
- variant?: "primary" | "secondary" | "danger" | "floating";
+ variant?: "primary" | "secondary" | "danger" | "floating" | "affix";
/**
* Extends the width of the button to that of its' parent.
@@ -59,7 +59,15 @@ interface IconProps extends CommonProps {
icon: ReactElement;
}
-export type ButtonProps = IconProps | ChildrenProps;
+interface AffixProps
+ extends Omit {
+ variant: "affix";
+ children: never;
+ icon: ReactElement;
+ size: "s";
+}
+
+export type ButtonProps = IconProps | ChildrenProps | AffixProps;
/**
* A clickable button used for form submissions and most in-page interactions.
diff --git a/packages/odyssey-react/src/components/Icon/Eye.tsx b/packages/odyssey-react/src/components/Icon/Eye.tsx
new file mode 100644
index 0000000000..e548f5ee11
--- /dev/null
+++ b/packages/odyssey-react/src/components/Icon/Eye.tsx
@@ -0,0 +1,38 @@
+/*!
+ * Copyright (c) 2022-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.
+ */
+
+// Code automatically generated by svgr; DO NOT EDIT.
+
+import React, { forwardRef } from "react";
+import { useOmit } from "../../utils";
+import { SvgIcon } from "./SvgIcon";
+import type { SvgIconNoChildrenProps } from "./types";
+
+export type EyeIconProps = SvgIconNoChildrenProps;
+
+export const EyeIcon = forwardRef((props, ref) => {
+ const omitProps = useOmit(props);
+ return (
+
+
+
+ );
+});
+
+EyeIcon.displayName = "EyeIcon";
diff --git a/packages/odyssey-react/src/components/Icon/EyeOff.tsx b/packages/odyssey-react/src/components/Icon/EyeOff.tsx
new file mode 100644
index 0000000000..acc2a824fb
--- /dev/null
+++ b/packages/odyssey-react/src/components/Icon/EyeOff.tsx
@@ -0,0 +1,40 @@
+/*!
+ * Copyright (c) 2022-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.
+ */
+
+// Code automatically generated by svgr; DO NOT EDIT.
+
+import React, { forwardRef } from "react";
+import { useOmit } from "../../utils";
+import { SvgIcon } from "./SvgIcon";
+import type { SvgIconNoChildrenProps } from "./types";
+
+export type EyeOffIconProps = SvgIconNoChildrenProps;
+
+export const EyeOffIcon = forwardRef(
+ (props, ref) => {
+ const omitProps = useOmit(props);
+ return (
+
+
+
+ );
+ }
+);
+
+EyeOffIcon.displayName = "EyeOffIcon";
diff --git a/packages/odyssey-react/src/components/Icon/index.tsx b/packages/odyssey-react/src/components/Icon/index.tsx
index 21dc0032ee..17d8581e8c 100644
--- a/packages/odyssey-react/src/components/Icon/index.tsx
+++ b/packages/odyssey-react/src/components/Icon/index.tsx
@@ -83,6 +83,12 @@ export * from "./Edit";
import { ExternalLinkIcon } from "./ExternalLink";
export * from "./ExternalLink";
+import { EyeOffIcon } from "./EyeOff";
+export * from "./EyeOff";
+
+import { EyeIcon } from "./Eye";
+export * from "./Eye";
+
import { FilterIcon } from "./Filter";
export * from "./Filter";
@@ -146,6 +152,8 @@ export const iconDictionary = {
"drag-handle": DragHandleIcon,
edit: EditIcon,
"external-link": ExternalLinkIcon,
+ "eye-off": EyeOffIcon,
+ eye: EyeIcon,
filter: FilterIcon,
globe: GlobeIcon,
home: HomeIcon,
diff --git a/packages/odyssey-react/src/components/PasswordInput/PasswordInput.test.tsx b/packages/odyssey-react/src/components/PasswordInput/PasswordInput.test.tsx
new file mode 100644
index 0000000000..f98f55670d
--- /dev/null
+++ b/packages/odyssey-react/src/components/PasswordInput/PasswordInput.test.tsx
@@ -0,0 +1,50 @@
+/*!
+ * Copyright (c) 2022-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 React from "react";
+import { render, screen } from "@testing-library/react";
+import { PasswordInput } from ".";
+
+const label = "Password";
+const tooltipOnLabel = "Show password";
+const tooltipOffLabel = "Hide password";
+
+describe("PasswordInput", () => {
+ it("renders into the document", () => {
+ render();
+ expect(screen.getByLabelText(label)).toBeVisible();
+ });
+
+ it("has a button that changes the type when clicked", () => {
+ const tooltipLabel = (isHidden: boolean) => {
+ return isHidden ? tooltipOnLabel : tooltipOffLabel;
+ };
+ render(
+
+ );
+ const inputElement = screen.getByLabelText(label);
+ expect(inputElement).toHaveValue("Imma password");
+ expect(inputElement).toHaveAttribute("type", "password");
+ const eyeButton = screen.getByRole("button");
+ expect(eyeButton).toBeInTheDocument();
+ eyeButton.click();
+ expect(inputElement).toHaveAttribute("type", "text");
+ });
+
+ a11yCheck(() =>
+ render()
+ );
+});
diff --git a/packages/odyssey-react/src/components/PasswordInput/PasswordInput.tsx b/packages/odyssey-react/src/components/PasswordInput/PasswordInput.tsx
new file mode 100644
index 0000000000..58e98c2f88
--- /dev/null
+++ b/packages/odyssey-react/src/components/PasswordInput/PasswordInput.tsx
@@ -0,0 +1,98 @@
+/*!
+ * Copyright (c) 2022-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 React, { forwardRef, useMemo, useState } from "react";
+import { useOmit } from "../../utils";
+import { TextInput, TextInputProps } from "../TextInput";
+import { EyeIcon, EyeOffIcon } from "../Icon";
+import { Button } from "../Button";
+import { Tooltip } from "../Tooltip";
+import type { TooltipProps } from "../Tooltip";
+
+export interface PasswordInputProps
+ extends Omit<
+ TextInputProps,
+ | "type"
+ | "PrefixButton"
+ | "PrefixIcon"
+ | "PrefixText"
+ | "SuffixButton"
+ | "SuffixIcon"
+ | "SuffixText"
+ > {
+ type?: never;
+ tooltipLabel:
+ | TooltipProps["label"]
+ | ((isHidden: boolean) => TooltipProps["label"]);
+ tooltipPosition?: TooltipProps["position"];
+ PrefixButton?: never;
+ PrefixIcon?: never;
+ PrefixText?: never;
+ SuffixButton?: never;
+ SuffixIcon?: never;
+ SuffixText?: never;
+}
+
+/**
+ * Password inputs exposes hide/show capability
+ */
+export const PasswordInput = forwardRef(
+ (props, ref) => {
+ const { name, label, tooltipLabel, tooltipPosition, ...rest } = props;
+
+ const omitProps = useOmit(rest);
+ const [internalType, setInternalType] = useState<"password" | "text">(
+ "password"
+ );
+
+ const onHideShowPasswordClick = () => {
+ setInternalType(internalType === "password" ? "text" : "password");
+ };
+
+ const _tooltipLabel = useMemo(() => {
+ if (typeof tooltipLabel === "function") {
+ return tooltipLabel(internalType === "password");
+ }
+ return tooltipLabel;
+ }, [internalType, tooltipLabel]);
+
+ return (
+ <>
+ {/*
+ @ts-expect-error using a type="password" intentionally here */}
+
+ :
+ }
+ onClick={onHideShowPasswordClick}
+ />
+
+ }
+ />
+ >
+ );
+ }
+);
+
+PasswordInput.displayName = "PasswordInput";
diff --git a/packages/odyssey-react/src/components/PasswordInput/index.ts b/packages/odyssey-react/src/components/PasswordInput/index.ts
new file mode 100644
index 0000000000..adf93d1109
--- /dev/null
+++ b/packages/odyssey-react/src/components/PasswordInput/index.ts
@@ -0,0 +1,13 @@
+/*!
+ * Copyright (c) 2022-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.
+ */
+
+export * from "./PasswordInput";
diff --git a/packages/odyssey-react/src/components/SearchInput/SearchInput.module.scss b/packages/odyssey-react/src/components/SearchInput/SearchInput.module.scss
new file mode 100644
index 0000000000..8355c1b6d0
--- /dev/null
+++ b/packages/odyssey-react/src/components/SearchInput/SearchInput.module.scss
@@ -0,0 +1,21 @@
+/*!
+ * Copyright (c) 2022-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.
+ */
+.clear {
+ opacity: 0;
+}
+
+.search {
+ &:hover .clear,
+ &:focus-within .clear {
+ opacity: 1;
+ }
+}
diff --git a/packages/odyssey-react/src/components/SearchInput/SearchInput.test.tsx b/packages/odyssey-react/src/components/SearchInput/SearchInput.test.tsx
new file mode 100644
index 0000000000..0a96178597
--- /dev/null
+++ b/packages/odyssey-react/src/components/SearchInput/SearchInput.test.tsx
@@ -0,0 +1,78 @@
+/*!
+ * Copyright (c) 2022-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 React from "react";
+import { render, screen } from "@testing-library/react";
+import { SearchInput } from ".";
+
+const searchBox = "searchbox";
+const label = "Destination";
+
+describe("SearchInput", () => {
+ beforeEach(() => {
+ jest
+ .spyOn(window, "requestAnimationFrame")
+ .mockImplementation((callback: FrameRequestCallback): number => {
+ callback(0);
+ return 0;
+ });
+ });
+
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it("renders into the document", () => {
+ render();
+
+ expect(screen.getByRole(searchBox)).toBeVisible();
+ });
+
+ it("clears the search input when the clear button is clicked", () => {
+ render(
+
+ );
+ const inputElement = screen.getByRole(searchBox);
+ expect(inputElement).toHaveValue("Default uncontrolled value");
+ inputElement.focus();
+ const clearButton = screen.getByRole("button");
+ clearButton.click();
+ expect(screen.getByRole(searchBox)).toHaveValue("");
+ });
+
+ it("There is a clear button when the value is controlled and non empty", () => {
+ render();
+ const inputElement = screen.getByRole(searchBox);
+ expect(inputElement).toHaveValue("controlled value");
+ inputElement.focus();
+ expect(screen.queryByRole("button")).toBeInTheDocument();
+ });
+
+ it("calls onchange with empty value when clear button is clicked", () => {
+ const onChange = jest.fn();
+ render(
+
+ );
+ const inputElement = screen.getByRole(searchBox);
+ expect(inputElement).toHaveValue("a value");
+ inputElement.focus();
+ const clearButton = screen.getByRole("button");
+ clearButton.click();
+ expect(onChange).toHaveBeenCalledTimes(1);
+ expect(onChange).toHaveBeenLastCalledWith(
+ expect.objectContaining({ type: "change" }),
+ ""
+ );
+ });
+
+ a11yCheck(() => render());
+});
diff --git a/packages/odyssey-react/src/components/SearchInput/SearchInput.theme.ts b/packages/odyssey-react/src/components/SearchInput/SearchInput.theme.ts
new file mode 100644
index 0000000000..4bdc7fd5e8
--- /dev/null
+++ b/packages/odyssey-react/src/components/SearchInput/SearchInput.theme.ts
@@ -0,0 +1,15 @@
+/*!
+ * Copyright (c) 2022-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 type { ThemeReducer } from "@okta/odyssey-react-theme";
+
+export const theme: ThemeReducer = () => ({});
diff --git a/packages/odyssey-react/src/components/SearchInput/SearchInput.tsx b/packages/odyssey-react/src/components/SearchInput/SearchInput.tsx
new file mode 100644
index 0000000000..44f1ccc1f6
--- /dev/null
+++ b/packages/odyssey-react/src/components/SearchInput/SearchInput.tsx
@@ -0,0 +1,130 @@
+/*!
+ * Copyright (c) 2022-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 React, { forwardRef, useEffect, useState } from "react";
+import type { ChangeEvent } from "react";
+import { withTheme } from "@okta/odyssey-react-theme";
+import { useOmit, useSharedRef } from "../../utils";
+import { TextInput, TextInputProps } from "../TextInput";
+import { CloseCircleFilledIcon, SearchIcon } from "../Icon";
+import { Button } from "../Button";
+import { theme } from "./SearchInput.theme";
+import styles from "./SearchInput.module.scss";
+
+export interface SearchInputProps
+ extends Omit<
+ TextInputProps,
+ | "type"
+ | "PrefixButton"
+ | "PrefixIcon"
+ | "PrefixText"
+ | "SuffixButton"
+ | "SuffixIcon"
+ | "SuffixText"
+ > {
+ type?: never;
+ PrefixButton?: never;
+ PrefixIcon?: never;
+ PrefixText?: never;
+ SuffixButton?: never;
+ SuffixIcon?: never;
+ SuffixText?: never;
+}
+/**
+ * Search inputs allow users to enter text search criteria
+ */
+export const SearchInput = withTheme(
+ theme,
+ styles
+)(
+ forwardRef((props, ref) => {
+ const { defaultValue, onChange, label, labelHidden, name, value, ...rest } =
+ props;
+
+ const omitProps = useOmit(rest);
+ const internalRef = useSharedRef(ref);
+ const [isControlled, setIsControlled] = useState(
+ typeof value !== "undefined"
+ );
+ const [canShowClearButton, setCanShowClearButton] = useState(
+ isControlled ? !!value : !!defaultValue
+ );
+
+ useEffect(() => {
+ if (typeof value === "undefined") {
+ setIsControlled(false);
+ } else {
+ setIsControlled(true);
+ setCanShowClearButton(!!value);
+ }
+ }, [value]);
+
+ const setFocus = () => {
+ requestAnimationFrame(() => {
+ internalRef.current?.focus();
+ });
+ };
+
+ const onClear = () => {
+ if (internalRef.current) {
+ setFocus();
+ const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
+ window?.HTMLInputElement?.prototype,
+ "value"
+ )?.set;
+ if (nativeInputValueSetter) {
+ nativeInputValueSetter.call(internalRef.current, "");
+ const aChangeEvent = new Event("change", { bubbles: true });
+ internalRef.current.dispatchEvent(aChangeEvent);
+ }
+ }
+ };
+
+ const internalOnChange = (event: ChangeEvent) => {
+ if (!isControlled) {
+ setCanShowClearButton(!!event.target.value);
+ }
+ onChange?.(event, event.target.value);
+ };
+
+ return (
+
+ {/*
+ @ts-expect-error using a type="search" intentionally here */}
+ }
+ SuffixButton={
+ canShowClearButton ? (
+
+ }
+ onClick={onClear}
+ />
+
+ ) : undefined
+ }
+ />
+
+ );
+ })
+);
+
+SearchInput.displayName = "SearchInput";
diff --git a/packages/odyssey-react/src/components/SearchInput/index.ts b/packages/odyssey-react/src/components/SearchInput/index.ts
new file mode 100644
index 0000000000..98e37dba88
--- /dev/null
+++ b/packages/odyssey-react/src/components/SearchInput/index.ts
@@ -0,0 +1,13 @@
+/*!
+ * Copyright (c) 2022-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.
+ */
+
+export * from "./SearchInput";
diff --git a/packages/odyssey-react/src/components/TextInput/Affix.tsx b/packages/odyssey-react/src/components/TextInput/Affix.tsx
new file mode 100644
index 0000000000..582ba35171
--- /dev/null
+++ b/packages/odyssey-react/src/components/TextInput/Affix.tsx
@@ -0,0 +1,46 @@
+/*!
+ * Copyright (c) 2022-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 React from "react";
+import type { ReactElement, RefObject, ReactNode } from "react";
+
+export interface AffixProps {
+ AffixButton?: ReactNode;
+ AffixIcon?: ReactNode;
+ AffixText?: string;
+ className: string;
+ sharedRef: RefObject;
+}
+
+export function Affix(props: AffixProps): ReactElement {
+ const { AffixButton, AffixIcon, AffixText, className, sharedRef } = props;
+
+ const setFocus = () => {
+ requestAnimationFrame(() => {
+ if (sharedRef.current) {
+ sharedRef.current.focus();
+ }
+ });
+ };
+
+ return (
+ <>
+ {AffixText || AffixIcon ? (
+
+ {AffixText || AffixIcon}
+
+ ) : (
+ AffixButton && {AffixButton}
+ )}
+ >
+ );
+}
diff --git a/packages/odyssey-react/src/components/TextInput/TextInput.module.scss b/packages/odyssey-react/src/components/TextInput/TextInput.module.scss
index ae003e3e21..e6e335ceee 100644
--- a/packages/odyssey-react/src/components/TextInput/TextInput.module.scss
+++ b/packages/odyssey-react/src/components/TextInput/TextInput.module.scss
@@ -18,8 +18,6 @@
max-width: var(--MaxWidth);
margin-block: var(--MarginBlock);
margin-inline: var(--MarginInline);
- padding-block: calc(var(--PaddingBlock) - var(--BorderWidth));
- padding-inline: calc(var(--PaddingInline) - var(--BorderWidth));
transition-property: border-color, background-color;
transition-duration: var(--TransitionDuration);
transition-timing-function: var(--TransitionTimingFunction);
@@ -33,33 +31,17 @@
line-height: var(--LineHeight);
&:hover,
- &:focus-within {
+ &.focus {
border-color: var(--HoverFocusBorderColor);
}
- &:focus-within {
+ &.focus {
outline-color: var(--FocusOutlineColor);
outline-offset: var(--FocusOutlineOffset);
outline-style: var(--FocusOutlineStyle);
outline-width: var(--FocusOutlineWidth);
}
- &:disabled {
- opacity: 1;
- color: var(--DisabledTextColor);
- cursor: not-allowed;
- }
-
- &:disabled,
- &[readonly] {
- border-color: var(--DisabledBorderColor);
- background-color: var(--DisabledBackgroundColor);
-
- &:hover {
- border-color: var(--DisabledBorderColor);
- }
- }
-
&::placeholder {
color: var(--PlaceholderTextColor);
}
@@ -72,23 +54,49 @@
}
}
- &.invalid:focus-within {
+ // stylelint-disable-next-line selector-max-class
+ &.invalid.focus {
outline-color: var(--InvalidFocusOutlineColor);
}
+
+ &.disabled {
+ opacity: 1;
+ color: var(--DisabledTextColor);
+ cursor: not-allowed;
+ }
+
+ &.disabled,
+ &.readonly {
+ border-color: var(--DisabledBorderColor);
+ background-color: var(--DisabledBackgroundColor);
+
+ &:hover {
+ border-color: var(--DisabledBorderColor);
+ }
+ }
}
.prefix,
.suffix {
+ padding-block: calc(var(--PaddingBlock) - var(--BorderWidth));
color: var(--AffixTextColor);
cursor: default;
}
.prefix {
- padding-inline-end: var(--AffixPaddingInline);
+ padding-inline-start: var(--PaddingInline);
}
.suffix {
- padding-inline-start: var(--AffixPaddingInline);
+ padding-inline-end: var(--PaddingInline);
+}
+
+.affixFull {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding-block: var(--AffixPadding);
+ padding-inline-end: var(--AffixPadding);
}
.affixIcon {
@@ -101,12 +109,31 @@
flex: 1;
margin-block: 0;
margin-inline: 0;
- padding-block: 0;
- padding-inline: 0;
+ padding-block: calc(var(--PaddingBlock) - var(--BorderWidth));
+ padding-inline: var(--PaddingInline);
border: 0;
+ background-color: transparent;
font: inherit;
&:focus {
outline: 0;
}
+
+ &:disabled {
+ cursor: not-allowed;
+ }
+
+ &[type="search"] {
+ &::-webkit-search-decoration,
+ &::-webkit-search-cancel-button,
+ &::-webkit-search-results-button,
+ &::-webkit-search-results-decoration {
+ display: none;
+ }
+
+ &::-ms-clear,
+ &::-ms-reveal {
+ display: none;
+ }
+ }
}
diff --git a/packages/odyssey-react/src/components/TextInput/TextInput.test.tsx b/packages/odyssey-react/src/components/TextInput/TextInput.test.tsx
index f91644e16e..ce803f8b2d 100644
--- a/packages/odyssey-react/src/components/TextInput/TextInput.test.tsx
+++ b/packages/odyssey-react/src/components/TextInput/TextInput.test.tsx
@@ -96,16 +96,33 @@ describe("TextInput", () => {
).toBeVisible();
});
- it.each([["disabled"], ["readonly"], ["required"]])(
- "renders %s attribute",
- (attr: string) => {
- const { getByRole } = render(
-
- );
+ it("renders required attribute", () => {
+ render();
- expect(getByRole(textBox)).toHaveAttribute(attr);
- }
- );
+ expect(screen.getByRole(textBox)).toHaveAttribute("required");
+ });
+
+ it("renders disabled attribute with correct style", () => {
+ const handle = jest.fn();
+
+ render();
+
+ const textBoxElement = screen.getByRole(textBox);
+ expect(textBoxElement).toHaveAttribute("disabled");
+ expect(textBoxElement.parentElement).toBeInTheDocument();
+ expect(textBoxElement.parentElement?.className).toContain("disabled");
+ });
+
+ it("renders readonly attribute with correct style", () => {
+ const handle = jest.fn();
+
+ render();
+
+ const textBoxElement = screen.getByRole(textBox);
+ expect(textBoxElement).toHaveAttribute("readonly");
+ expect(textBoxElement.parentElement).toBeInTheDocument();
+ expect(textBoxElement.parentElement?.className).toContain("readonly");
+ });
it.each<[TextInputProps["type"]]>([
[undefined],
@@ -113,8 +130,6 @@ describe("TextInput", () => {
["email"],
["url"],
["tel"],
- ["search"],
- ["password"],
])("renders %s input type", (type) => {
render();
@@ -167,21 +182,21 @@ describe("TextInput", () => {
});
it("renders the prefix", () => {
- render();
+ render();
const prefixElement = screen.getByText("test prefix");
expect(prefixElement).toBeInTheDocument();
expect(prefixElement.className).toContain("prefix");
});
it("renders the suffix", () => {
- render();
+ render();
const suffixElement = screen.getByText("test suffix");
expect(suffixElement).toBeInTheDocument();
expect(suffixElement.className).toContain("suffix");
});
it("gives the input focus when prefix is clicked", () => {
- render();
+ render();
const prefixElement = screen.getByText("test prefix");
prefixElement.click();
const inputElement = screen.getByRole(textBox);
@@ -189,7 +204,7 @@ describe("TextInput", () => {
});
it("gives the input focus when suffix is clicked", () => {
- render();
+ render();
const prefixElement = screen.getByText("test suffix");
prefixElement.click();
const inputElement = screen.getByRole(textBox);
diff --git a/packages/odyssey-react/src/components/TextInput/TextInput.theme.ts b/packages/odyssey-react/src/components/TextInput/TextInput.theme.ts
index 95fa6731d5..ca424c4c34 100644
--- a/packages/odyssey-react/src/components/TextInput/TextInput.theme.ts
+++ b/packages/odyssey-react/src/components/TextInput/TextInput.theme.ts
@@ -29,7 +29,7 @@ export const theme: ThemeReducer = (theme) => ({
TransitionDuration: theme.TransitionDurationBase,
TransitionTimingFunction: theme.TransitionTimingBase,
- AffixPaddingInline: theme.SpaceScale1,
+ AffixPadding: theme.SpaceScale0,
AffixTextColor: theme.ColorTextSub,
DisabledBackgroundColor: theme.ColorBackgroundDisabled,
diff --git a/packages/odyssey-react/src/components/TextInput/TextInput.tsx b/packages/odyssey-react/src/components/TextInput/TextInput.tsx
index 0734f58ab2..e3248f5b51 100644
--- a/packages/odyssey-react/src/components/TextInput/TextInput.tsx
+++ b/packages/odyssey-react/src/components/TextInput/TextInput.tsx
@@ -10,8 +10,9 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
-import React, { forwardRef, useEffect, useState } from "react";
+import React, { forwardRef, ReactNode, useEffect, useState } from "react";
import type {
+ FocusEvent,
FocusEventHandler,
ComponentPropsWithRef,
ChangeEvent,
@@ -19,20 +20,20 @@ import type {
} from "react";
import { withTheme } from "@okta/odyssey-react-theme";
import { useOid, useOmit, useCx, useSharedRef } from "../../utils";
-import { SearchIcon } from "../Icon";
import { Field } from "../Field";
import type { CommonFieldProps } from "../Field/types";
+import { Affix } from "./Affix";
import { theme } from "./TextInput.theme";
import styles from "./TextInput.module.scss";
function checkInputValidity(inputRef: RefObject) {
- return inputRef.current ? inputRef.current?.checkValidity() : true;
+ return inputRef.current ? inputRef.current.checkValidity() : true;
}
-interface CommonProps
+export interface TextInputProps
extends CommonFieldProps,
Omit<
ComponentPropsWithRef<"input">,
- "style" | "className" | "color" | "onChange" | "prefix"
+ "style" | "className" | "color" | "onChange" | "readOnly"
> {
/**
* The underlying input element id attribute. Automatically generated if not provided
@@ -43,7 +44,7 @@ interface CommonProps
* The underlying input element type
* @default text
*/
- type?: "text" | "email" | "url" | "tel" | "password";
+ type?: "text" | "email" | "url" | "tel";
/**
* The underlying input element name attribute
@@ -68,14 +69,40 @@ interface CommonProps
placeholder?: string;
/**
- * An optional string prefix displayed before the input
+ * An optional prefix button displayed before the input
+ * Only one of PrefixButton, PrefixIcon, PrefixText can be set
*/
- prefix?: string;
+ PrefixButton?: ReactNode;
/**
- * An optional string suffix displayed after the input
+ * An optional prefix icon displayed before the input
+ * Only one of PrefixButton, PrefixIcon, PrefixText can be set
*/
- suffix?: string;
+ PrefixIcon?: ReactNode;
+
+ /**
+ * An optional prefix text displayed before the input
+ * Only one of PrefixButton, PrefixIcon, PrefixText can be set
+ */
+ PrefixText?: string;
+
+ /**
+ * An optional suffix button displayed before the input
+ * Only one of SuffixButton, SuffixIcon, SuffixText can be set
+ */
+ SuffixButton?: ReactNode;
+
+ /**
+ * An optional suffix icon displayed before the input
+ * Only one of SuffixButton, SuffixIcon, SuffixText can be set
+ */
+ SuffixIcon?: ReactNode;
+
+ /**
+ * An optional suffix text displayed before the input
+ * Only one of SuffixButton, SuffixIcon, SuffixText can be set
+ */
+ SuffixText?: string;
/**
* The input element value for controlled components
@@ -107,14 +134,6 @@ interface CommonProps
onFocus?: FocusEventHandler;
}
-interface SearchProps extends Omit {
- type: "search";
- prefix?: never;
- suffix?: never;
-}
-
-export type TextInputProps = CommonProps | SearchProps;
-
/**
* Text inputs allow users to edit and input data.
*/
@@ -135,35 +154,51 @@ export const TextInput = withTheme(
readonly = false,
required,
type = "text",
- prefix,
- suffix,
+ SuffixButton,
+ SuffixIcon,
+ SuffixText,
+ PrefixButton,
+ PrefixIcon,
+ PrefixText,
value,
error,
hint,
label,
+ labelHidden,
optionalLabel,
...rest
} = props;
- const isSearchTextInput = type === "search";
-
const oid = useOid(id);
const omitProps = useOmit(rest);
const internalRef = useSharedRef(ref);
- const [isValid, setIsValid] = useState(checkInputValidity(internalRef));
+ const [isValid, setIsValid] = useState(true);
+ const [hasFocus, setHasFocus] = useState(false);
useEffect(() => {
- setIsValid(checkInputValidity(internalRef));
- }, [internalRef, required, type, value]);
+ if (internalRef.current) {
+ setIsValid(checkInputValidity(internalRef));
+ }
+ }, [internalRef, required]);
+
+ const internalOnFocus = (event: FocusEvent) => {
+ setHasFocus(true);
+ onFocus?.(event);
+ };
- const setFocus = () => {
- requestAnimationFrame(() => {
- internalRef.current?.focus();
- });
+ const internalOnBlur = (event: FocusEvent) => {
+ setHasFocus(false);
+ onBlur?.(event);
};
const handleChange = (event: ChangeEvent) => {
- setIsValid(checkInputValidity(internalRef));
+ if (
+ typeof value === "undefined" ||
+ value === internalRef.current?.value
+ ) {
+ // not a controlled value, check validity on change
+ setIsValid(checkInputValidity(internalRef));
+ }
onChange?.(event, event.target.value);
};
@@ -179,12 +214,25 @@ export const TextInput = withTheme(
}
: {};
+ const rootStyles = useCx(
+ styles.root,
+ !isValid && styles.invalid,
+ hasFocus && styles.focus,
+ disabled && styles.disabled,
+ readonly && styles.readonly
+ );
+
const prefixStyles = useCx(
styles.prefix,
- isSearchTextInput && styles.affixIcon
+ PrefixButton ? styles.affixFull : undefined,
+ PrefixIcon ? styles.affixIcon : undefined
);
- const rootStyles = useCx(styles.root, !isValid && styles.invalid);
+ const suffixStyles = useCx(
+ styles.suffix,
+ SuffixButton ? styles.affixFull : undefined,
+ SuffixIcon ? styles.affixIcon : undefined
+ );
return (
- {(prefix || isSearchTextInput) && (
-
- {isSearchTextInput ? : prefix}
-
- )}
+
- {suffix && !isSearchTextInput && (
-
- {suffix}
-
- )}
+
);
diff --git a/packages/odyssey-react/src/components/index.ts b/packages/odyssey-react/src/components/index.ts
index bf524aa75a..b27a237c10 100644
--- a/packages/odyssey-react/src/components/index.ts
+++ b/packages/odyssey-react/src/components/index.ts
@@ -26,7 +26,9 @@ export * from "./Link";
export * from "./List";
export * from "./Modal";
export * from "./NativeSelect";
+export * from "./PasswordInput";
export * from "./Radio";
+export * from "./SearchInput";
export * from "./ScreenReaderText";
export * from "./Select";
export * from "./Status";
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/Button/Button.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Button/Button.stories.tsx
index 4ac9eac57a..b690996795 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/Button/Button.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Button/Button.stories.tsx
@@ -14,6 +14,7 @@ import { Story } from "@storybook/react";
import {
Button,
ButtonProps,
+ CloseCircleFilledIcon,
SettingsIcon,
} from "../../../../../odyssey-react/src";
import { ThemeProvider } from "@okta/odyssey-react-theme";
@@ -95,6 +96,13 @@ IconOnly.args = {
children: undefined,
};
+export const Affix = Template.bind({});
+Affix.args = {
+ variant: "affix",
+ icon: ,
+ children: undefined,
+};
+
export const Theme: Story<
ButtonProps & {
PrimaryBackgroundColor: string;
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/FieldGroup/FieldGroup.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/FieldGroup/FieldGroup.stories.tsx
index 9c3dbab031..dff08be425 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/FieldGroup/FieldGroup.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/FieldGroup/FieldGroup.stories.tsx
@@ -16,7 +16,7 @@ import {
FieldGroupProps,
Infobox,
Select,
- TextInput,
+ SearchInput,
} from "../../../../../odyssey-react/src";
import FieldGroupMdx from "./FieldGroup.mdx";
@@ -58,7 +58,7 @@ const Template: Story = ({ legend, desc }) => (
-
+
);
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/Icon/Icon.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Icon/Icon.stories.tsx
index b130aeb044..6ad2a5dc3c 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/Icon/Icon.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Icon/Icon.stories.tsx
@@ -133,6 +133,8 @@ const meta = [
classname: "ExternalLinkIcon",
use: "UI indicator - external link",
},
+ { name: "eye", classname: "EyeIcon", use: "To show something" },
+ { name: "eye-off", classname: "EyeOffIcon", use: "To hide something" },
{ name: "filter", classname: "FilterIcon", use: "To filter results" },
{ name: "globe", classname: "GlobeIcon", use: "" },
{ name: "home", classname: "HomeIcon", use: "" },
diff --git a/packages/odyssey-storybook/src/components/odyssey-legacy/Infobox/Infobox.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-legacy/Infobox/Infobox.stories.tsx
index 25800e0988..382660b1c0 100644
--- a/packages/odyssey-storybook/src/components/odyssey-legacy/Infobox/Infobox.stories.tsx
+++ b/packages/odyssey-storybook/src/components/odyssey-legacy/Infobox/Infobox.stories.tsx
@@ -19,6 +19,7 @@ import {
Link,
Table,
TextInput,
+ PasswordInput,
} from "../../../../../odyssey-react/src";
import InfoboxMdx from "./Infobox.mdx";
@@ -77,7 +78,13 @@ const FormTemplate: Story = ({
actions={actions}
/>
-
+
+ isHidden ? "show password" : "hide password"
+ }
+ label="Authorization code"
+ disabled
+ />