diff --git a/packages/primitives/src/icons/clone-16.svg b/packages/primitives/src/icons/clone-16.svg new file mode 100644 index 00000000..7985c2dc --- /dev/null +++ b/packages/primitives/src/icons/clone-16.svg @@ -0,0 +1,23 @@ + + + + + diff --git a/packages/primitives/src/icons/globe-16.svg b/packages/primitives/src/icons/globe-16.svg new file mode 100644 index 00000000..674746bb --- /dev/null +++ b/packages/primitives/src/icons/globe-16.svg @@ -0,0 +1,23 @@ + + + + + diff --git a/packages/react/.storybook/story-config.ts b/packages/react/.storybook/story-config.ts index aec76ee6..dd875484 100644 --- a/packages/react/.storybook/story-config.ts +++ b/packages/react/.storybook/story-config.ts @@ -32,6 +32,7 @@ enum StorybookCategories { Utils = 'Utils' } +// NOTE: Please keep the stories in alphabetical order. export type Stories = | 'Accordion' | 'AccordionDetails' @@ -46,34 +47,36 @@ export type Stories = | 'Avatar' | 'Backdrop' | 'Badge' - | 'Breadcrumbs' | 'Box' + | 'Breadcrumbs' | 'Button' - | 'CircularProgress' | 'Card' | 'CardActions' | 'CardContent' | 'CardHeader' | 'Carousel' | 'Checkbox' - | 'CircularProgressAvatar' | 'Chip' + | 'CircularProgress' + | 'CircularProgressAvatar' | 'Code' + | 'Colors' + | 'Collapse' | 'CollapsibleNavbarItem' | 'ColorModeToggle' - | 'Colors' | 'Container' + | 'CountryFlag' | 'DataGrid' + | 'Dialog' | 'Divider' | 'Drawer' - | 'CountryFlag' | 'Fab' | 'Footer' + | 'FormControl' | 'FormControlLabel' | 'FormGroup' - | 'FormLabel' | 'FormHelperText' - | 'FormControl' + | 'FormLabel' | 'Grid' | 'Header' | 'IconButton' @@ -92,19 +95,19 @@ export type Stories = | 'ListItemText' | 'Menu' | 'MenuItem' - | 'UserDropdownMenu' | 'Navbar' | 'NavbarItem' | 'OutlinedInput' | 'Paper' - | 'Popover' | 'PhoneNumberInput' + | 'Popover' | 'Radio' | 'RadioGroup' | 'Select' | 'SignIn' | 'Skeleton' | 'Snackbar' + | 'Stack' | 'Stepper' | 'Switch' | 'Tab' @@ -215,6 +218,9 @@ const StoryConfig: StorybookConfig = { Code: { hierarchy: `${StorybookCategories.DataDisplay}/Code`, }, + Collapse: { + hierarchy: `${StorybookCategories.Utils}/Collapse`, + }, CollapsibleNavbarItem: { hierarchy: `${StorybookCategories.Navigation}/Collapsible Navbar Item`, }, @@ -230,6 +236,9 @@ const StoryConfig: StorybookConfig = { DataGrid: { hierarchy: `${StorybookCategories.DataDisplay}/DataGrid`, }, + Dialog: { + hierarchy: `${StorybookCategories.Feedback}/Dialog`, + }, Divider: { hierarchy: `${StorybookCategories.DataDisplay}/Divider`, }, @@ -358,6 +367,9 @@ const StoryConfig: StorybookConfig = { Snackbar: { hierarchy: `${StorybookCategories.Feedback}/Snackbar`, }, + Stack: { + hierarchy: `${StorybookCategories.Layout}/Stack`, + }, Stepper: { hierarchy: `${StorybookCategories.Surfaces}/Stepper`, }, diff --git a/packages/react/src/components/AlertTitle/AlertTitle.tsx b/packages/react/src/components/AlertTitle/AlertTitle.tsx index da223461..56800731 100644 --- a/packages/react/src/components/AlertTitle/AlertTitle.tsx +++ b/packages/react/src/components/AlertTitle/AlertTitle.tsx @@ -17,7 +17,7 @@ */ import MuiAlertTitle from '@mui/material/AlertTitle'; -import type {AlertTitleProps, AlertTitleProps as MuiAlertTitleProps} from '@mui/material/AlertTitle'; +import type {AlertTitleProps as MuiAlertTitleProps} from '@mui/material/AlertTitle'; import type {OverridableComponent} from '@mui/material/OverridableComponent'; import clsx from 'clsx'; import {forwardRef} from 'react'; @@ -25,7 +25,7 @@ import type {ReactElement, ElementType, Ref} from 'react'; import type {TypographyTypeMap} from '../Typography'; import './alert-title.scss'; -export type AlertProps = { +export type AlertTitleProps = { /** * The component used for the root node. Either a string to use a HTML element or a component. */ @@ -57,7 +57,7 @@ export type AlertProps = { */ const AlertTitle: OverridableComponent> = forwardRef( ( - {className, ...rest}: AlertProps, + {className, ...rest}: AlertTitleProps, ref: Ref, ): ReactElement => { const classes: string = clsx('oxygen-alert-title', className); diff --git a/packages/react/src/components/Autocomplete/__tests__/__snapshots__/Autocomplete.test.tsx.snap b/packages/react/src/components/Autocomplete/__tests__/__snapshots__/Autocomplete.test.tsx.snap index 838729e4..c7c23a16 100644 --- a/packages/react/src/components/Autocomplete/__tests__/__snapshots__/Autocomplete.test.tsx.snap +++ b/packages/react/src/components/Autocomplete/__tests__/__snapshots__/Autocomplete.test.tsx.snap @@ -18,10 +18,10 @@ exports[`Alert should match the snapshot 1`] = ` Movie
+ +export const Template = ({...args}) => { + const [runtimeArgs, updateArgs] = useArgs(); + const {in: checked} = runtimeArgs; + return ( + + + updateArgs({...runtimeArgs, in: !checked})} />} + label="Show" + /> + + + + + + ); +}; + +# Collapse + +- [Overview](#overview) +- [Props](#props) +- [Usage](#usage) + +## Overview + +Expand from the start edge of the child element. Use the `orientation` prop if you need a horizontal collapse. The +`collapsedSize` prop can be used to set the minimum width/height when not expanded. + + + + {Template.bind({})} + + + +## Props + + + +## Usage + +Import and use the `Collapse` component in your components as follows. + + + ); +}`} +/> diff --git a/packages/react/src/components/Collapse/Collapse.tsx b/packages/react/src/components/Collapse/Collapse.tsx new file mode 100644 index 00000000..441545a3 --- /dev/null +++ b/packages/react/src/components/Collapse/Collapse.tsx @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with 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 MuiCollapse from '@mui/material/Collapse'; +import type {CollapseProps as MuiCollapseProps} from '@mui/material/Collapse'; +import type {OverridableComponent, OverridableTypeMap} from '@mui/material/OverridableComponent'; +import type {TransitionProps} from '@mui/material/transitions'; +import clsx from 'clsx'; +import {forwardRef} from 'react'; +import type {ReactElement, Ref, ElementType} from 'react'; + +export type CollapseProps> = { + /** + * The component used for the root node. Either a string to use a HTML element or a component. + */ + component?: C; +} & Omit; + +/** + * A Transition component to expand from the start edge of the child element. + * + * Demos: + * + * - [Card (Oxygen UI)](https://wso2.github.io/oxygen-ui/react/?path=/docs/surfaces-card) + * - [Card (MUI)](https://mui.com/material-ui/react-card/) + * - [Lists (Oxygen UI)](https://wso2.github.io/oxygen-ui/react/?path=/docs/data-display-list) + * - [Lists (MUI)](https://mui.com/material-ui/react-list/) + * - [Collapse (Oxygen UI)](https://wso2.github.io/oxygen-ui/react/?path=/docs/utils-collapse) + * - [Transitions (MUI)](https://mui.com/material-ui/transitions/) + * + * API: + * + * - [Collapse API](https://mui.com/material-ui/api/collapse/) + * - inherits [Transition API](http://reactcommunity.org/react-transition-group/transition/#Transition-props) + * + * @remarks + * - ✔️ Props of the [Transition](https://mui.com/material-ui/transitions/) component are also available. + * - ✅ `component` prop is supported. + * - ✅ The `ref` is forwarded to the root element. + * + * @template C - The type of the component. + * @param props - The props for the Collapse component. + * @param ref - The ref to be forwarded to the MuiCollapse component. + * @returns The rendered Collapse component. + */ +const Collapse: OverridableComponent = forwardRef( + ({className, ...rest}: CollapseProps>, ref: Ref): ReactElement => ( + + ), +) as OverridableComponent; + +export default Collapse; diff --git a/packages/react/src/components/Collapse/__tests__/Collapse.test.tsx b/packages/react/src/components/Collapse/__tests__/Collapse.test.tsx new file mode 100644 index 00000000..c040bf31 --- /dev/null +++ b/packages/react/src/components/Collapse/__tests__/Collapse.test.tsx @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with 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 {render} from '@unit-testing'; +import Collapse from '../Collapse'; + +describe('Collapse', () => { + it('should render successfully', () => { + const {baseElement} = render(); + expect(baseElement).toBeTruthy(); + }); + + it('should match the snapshot', () => { + const {baseElement} = render(); + expect(baseElement).toMatchSnapshot(); + }); +}); diff --git a/packages/react/src/components/Collapse/__tests__/__snapshots__/Collapse.test.tsx.snap b/packages/react/src/components/Collapse/__tests__/__snapshots__/Collapse.test.tsx.snap new file mode 100644 index 00000000..ba7832bf --- /dev/null +++ b/packages/react/src/components/Collapse/__tests__/__snapshots__/Collapse.test.tsx.snap @@ -0,0 +1,20 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Collapse should match the snapshot 1`] = ` + +
+
+
+
+
+
+
+ +`; diff --git a/packages/react/src/components/Collapse/index.ts b/packages/react/src/components/Collapse/index.ts new file mode 100644 index 00000000..518ee59a --- /dev/null +++ b/packages/react/src/components/Collapse/index.ts @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with 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 {default} from './Collapse'; +export * from './Collapse'; diff --git a/packages/react/src/components/Dialog/Dialog.stories.mdx b/packages/react/src/components/Dialog/Dialog.stories.mdx new file mode 100644 index 00000000..8324dadd --- /dev/null +++ b/packages/react/src/components/Dialog/Dialog.stories.mdx @@ -0,0 +1,119 @@ +import {XMarkIcon} from '@oxygen-ui/react-icons'; +import {ArgsTable, Source, Story, Canvas, Meta} from '@storybook/addon-docs'; +import {useArgs} from '@storybook/client-api'; +import dedent from 'ts-dedent'; +import Dialog from './Dialog.tsx'; +import StoryConfig from '../../../.storybook/story-config.ts'; +import Box from '../Box/Box.tsx'; +import Button from '../Button/Button.tsx'; +import DialogActions from '../DialogActions/DialogActions.tsx'; +import DialogContent from '../DialogContent/DialogContent.tsx'; +import DialogContentText from '../DialogContentText/DialogContentText.tsx'; +import DialogTitle from '../DialogTitle/DialogTitle.tsx'; +import IconButton from '../IconButton/IconButton.tsx'; + +export const meta = { + component: Dialog, + title: StoryConfig.Dialog.hierarchy, +}; + + + +export const Template = ({...args}) => { + const [runtimeArgs, updateArgs] = useArgs(); + const {open} = runtimeArgs; + const handleOpen = () => updateArgs({...runtimeArgs, open: true}); + const handleClose = () => updateArgs({...runtimeArgs, open: false}); + return ( + + + + + Modal title + + ({ + color: theme.palette.grey[500], + position: 'absolute', + right: 8, + top: 8, + })} + > + + + + + Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget + quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. + + + Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet + rutrum faucibus dolor auctor. + + + Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl + consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla. + + + + + + + + ); +}; + +# Dialog + +- [Overview](#overview) +- [Props](#props) +- [Usage](#usage) + +## Overview + +A Dialog is a type of `modal` window that appears in front of app content to provide critical information or ask for a +decision. Dialogs disable all app functionality when they appear, and remain on screen until confirmed, dismissed, or a +required action has been taken. + +Dialogs are purposefully interruptive, so they should be used sparingly. + + + + {Template.bind({})} + + + +## Props + + + +## Usage + +Import and use the `Dialog` component in your components as follows. + + + {/* Content */} + + ); +}`} +/> diff --git a/packages/react/src/components/Dialog/Dialog.tsx b/packages/react/src/components/Dialog/Dialog.tsx new file mode 100644 index 00000000..1dc5f4cf --- /dev/null +++ b/packages/react/src/components/Dialog/Dialog.tsx @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). All Rights Reserved. + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with 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 MuiDialog from '@mui/material/Dialog'; +import type {DialogProps as MuiDialogProps} from '@mui/material/Dialog'; +import type {ModalTypeMap} from '@mui/material/Modal'; +import {OverridableComponent} from '@mui/material/OverridableComponent'; +import clsx from 'clsx'; +import {forwardRef} from 'react'; +import type {ElementType, ReactElement, Ref} from 'react'; + +export type DialogProps = { + /** + * The component used for the root node. Either a string to use a HTML element or a component. + */ + component?: C; +} & Omit; + +/** + * Dialogs inform users about a task and can contain critical information, require decisions, or involve multiple tasks. + * + * Demos: + * + * - [Dialog (Oxygen UI)](https://wso2.github.io/oxygen-ui/react/?path=/docs/feedback-dialog) + * - [Dialog (MUI)](https://mui.com/material-ui/react-dialog/) + * + * API: + * + * - [Dialog API](https://mui.com/material-ui/api/dialog/) + * - inherits [Modal API](https://mui.com/material-ui/api/modal/) + * + * @remarks + * - ✔️ Props of the [Modal](https://mui.com/material-ui/api/modal/) component are also available. + * - ✅ `component` prop is supported. + * - ✅ The `ref` is forwarded to the root element. + * + * @template C - The type of the component. + * @param props - The props for the Dialog component. + * @param ref - The ref to be forwarded to the MuiDialog component. + * @returns The rendered Dialog component. + */ +const Dialog: OverridableComponent> = forwardRef( + ( + {className, ...rest}: DialogProps, + ref: Ref, + ): ReactElement => , +) as OverridableComponent>; + +export default Dialog; diff --git a/packages/react/src/components/Dialog/__tests__/Dialog.test.tsx b/packages/react/src/components/Dialog/__tests__/Dialog.test.tsx new file mode 100644 index 00000000..da0f5fe4 --- /dev/null +++ b/packages/react/src/components/Dialog/__tests__/Dialog.test.tsx @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with 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 {render} from '@unit-testing'; +import Dialog from '../Dialog'; + +describe('Dialog', () => { + it('should render successfully', () => { + const {baseElement} = render( + +
+
, + ); + expect(baseElement).toBeTruthy(); + }); + + it('should match the snapshot', () => { + const {baseElement} = render( + +
+
, + ); + expect(baseElement).toMatchSnapshot(); + }); +}); diff --git a/packages/react/src/components/Dialog/__tests__/__snapshots__/Dialog.test.tsx.snap b/packages/react/src/components/Dialog/__tests__/__snapshots__/Dialog.test.tsx.snap new file mode 100644 index 00000000..3cd8d56c --- /dev/null +++ b/packages/react/src/components/Dialog/__tests__/__snapshots__/Dialog.test.tsx.snap @@ -0,0 +1,43 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Dialog should match the snapshot 1`] = ` + +