From 6b869ec3756699bea8c2baefe855f8118cd8ab2c Mon Sep 17 00:00:00 2001 From: Muhammed Mustafa Date: Wed, 19 Apr 2023 16:37:13 +0200 Subject: [PATCH] feat(tools): add panel component (#49398) * run panel gen code * add the default style * add tthe styles for the panel * create context of bsStyle * add panel heading * add panel title * add panel body * create the story for the panel * typo hiding the border * border doesn't work for some reason * only border-3 works in tailwind * change for border-1 for better visual indication * fix: bsStyle not applying to the panel * add html props to the elements * remove the info colors for our info colors * fix heading style * add Panel test * use to have Class instead * fix type * component disregarding default attributes? * remove duplication in the test * use compound components * clean the old logic for the bsStyle * clean the exports * add heading and bsstyle control * fix the classes * check for title body render * remove extra types --------- Co-authored-by: Ahmad Abdolsaheb --- tools/ui-components/src/panel/index.ts | 2 + .../ui-components/src/panel/panel.stories.tsx | 55 +++++++++++ tools/ui-components/src/panel/panel.test.tsx | 25 +++++ tools/ui-components/src/panel/panel.tsx | 94 +++++++++++++++++++ tools/ui-components/src/panel/types.ts | 5 + 5 files changed, 181 insertions(+) create mode 100644 tools/ui-components/src/panel/index.ts create mode 100644 tools/ui-components/src/panel/panel.stories.tsx create mode 100644 tools/ui-components/src/panel/panel.test.tsx create mode 100644 tools/ui-components/src/panel/panel.tsx create mode 100644 tools/ui-components/src/panel/types.ts diff --git a/tools/ui-components/src/panel/index.ts b/tools/ui-components/src/panel/index.ts new file mode 100644 index 00000000000..0a3fa400bdc --- /dev/null +++ b/tools/ui-components/src/panel/index.ts @@ -0,0 +1,2 @@ +export { Panel } from './panel'; +export type { PanelProps } from './types'; diff --git a/tools/ui-components/src/panel/panel.stories.tsx b/tools/ui-components/src/panel/panel.stories.tsx new file mode 100644 index 00000000000..22a9d90793c --- /dev/null +++ b/tools/ui-components/src/panel/panel.stories.tsx @@ -0,0 +1,55 @@ +import React from 'react'; +import { Story } from '@storybook/react'; +import { Panel, PanelProps } from '.'; + +const story = { + title: 'Example/Panel', + component: Panel, + parameters: { + controls: { + include: ['className', 'bsStyle'] + } + }, + argType: { + className: { control: { type: 'text' } }, + bsStyle: { option: ['primary', 'danger', 'info', undefined] } + } +}; + +const Child = () => { + return ( + <> + + Here is panel Heading + + Here is Panel body + + ); +}; + +const Template: Story = args => ; + +export const Default = Template.bind({}); +Default.args = { + children: +}; + +export const Primary = Template.bind({}); +Primary.args = { + children: , + bsStyle: 'primary' +}; + +export const Info = Template.bind({}); +Info.args = { + children: , + bsStyle: 'info' +}; + +export const Danger = Template.bind({}); +Danger.args = { + children: , + bsStyle: 'danger' +}; + +export default story; diff --git a/tools/ui-components/src/panel/panel.test.tsx b/tools/ui-components/src/panel/panel.test.tsx new file mode 100644 index 00000000000..4e626c368d0 --- /dev/null +++ b/tools/ui-components/src/panel/panel.test.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; + +import { Panel } from '.'; + +describe('', () => { + it('PanelTitle should render', () => { + render(Test Title); + const title = screen.getByText('Test Title'); + expect(title).toBeInTheDocument(); + }); + it('PanelHead should inherit bsStyle', () => { + render( + + Test + TestBody + + ); + expect(screen.getByRole('article')).toBeInTheDocument(); + expect(screen.getByText('Test')).toHaveClass( + 'border-b-1 border-solid border-foreground-primary text-foreground-primary' + ); + expect(screen.getByText('TestBody')).toBeInTheDocument(); + }); +}); diff --git a/tools/ui-components/src/panel/panel.tsx b/tools/ui-components/src/panel/panel.tsx new file mode 100644 index 00000000000..5c14fc37ed7 --- /dev/null +++ b/tools/ui-components/src/panel/panel.tsx @@ -0,0 +1,94 @@ +import React, { createContext, useContext } from 'react'; + +import { PanelProps } from './types'; + +type PanelContextProps = Pick; +const PanelContext = createContext({}); + +const styles = 'border-1 border-solid shadow-sm mb-6'; +const defaultBorder = 'border-background-tertiary'; +const primaryBorder = 'border-foreground-primary'; +const dangerBorder = 'border-foreground-danger'; +const infoBorder = 'border-foreground-info'; +const defaultHeadingStyle = + 'border-b-1 border-solid border-background-tertiary'; +const primaryHeadingStyle = + 'border-b-1 border-solid border-foreground-primary text-foreground-primary'; +const infoHeadingStyle = 'text-background-info bg-foreground-info'; +const dangerHeadingStyle = 'text-background-danger bg-foreground-danger'; +const headingPadding = 'px-2.5 py-3.5 '; + +let bsStyleClass = defaultBorder; +let headingStyles = headingPadding + defaultHeadingStyle; + +const Body = ({ + children, + props +}: { + children?: React.ReactNode; + props?: React.ComponentProps<'div'>; +}): JSX.Element => { + return ( +
+ {children} +
+ ); +}; + +export const Heading = ({ + children, + props +}: { + children?: React.ReactNode; + props?: React.ComponentProps<'div'>; +}): JSX.Element => { + const { bsStyle } = useContext(PanelContext); + if (bsStyle === 'primary') headingStyles = primaryHeadingStyle; + else if (bsStyle === 'danger') headingStyles = dangerHeadingStyle; + else if (bsStyle === 'info') headingStyles = infoHeadingStyle; + + return ( +
+ {children} +
+ ); +}; + +export const Title = ({ + children, + props +}: { + children?: React.ReactNode; + props?: React.ComponentProps<'h3'>; +}): JSX.Element => { + return ( +

+ {children} +

+ ); +}; + +export const Panel = ({ + children, + className, + bsStyle, + ...restProps +}: PanelProps): JSX.Element => { + if (bsStyle === 'primary') bsStyleClass = primaryBorder; + else if (bsStyle === 'danger') bsStyleClass = dangerBorder; + else if (bsStyle === 'info') bsStyleClass = infoBorder; + + const panelClassed = [styles, bsStyleClass, className].join(' '); + + return ( + +
+ {children} +
+
+ ); +}; + +Panel.Body = Body; +Panel.Heading = Heading; +Panel.Title = Title; diff --git a/tools/ui-components/src/panel/types.ts b/tools/ui-components/src/panel/types.ts new file mode 100644 index 00000000000..ab25dc6ed62 --- /dev/null +++ b/tools/ui-components/src/panel/types.ts @@ -0,0 +1,5 @@ +import React from 'react'; + +export interface PanelProps extends React.HTMLAttributes { + bsStyle?: 'primary' | 'info' | 'danger'; +}