-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #394 from beda-software/update-app-layout
Update app layout
- Loading branch information
Showing
93 changed files
with
3,138 additions
and
1,952 deletions.
There are no files selected for viewing
170 changes: 170 additions & 0 deletions
170
src/components/BaseLayout/PageContainer/PageContainer.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
import { CalendarOutlined, MailOutlined, PhoneOutlined, PlusOutlined } from '@ant-design/icons'; | ||
import { Meta, StoryObj } from '@storybook/react'; | ||
import { Button, Input } from 'antd'; | ||
import styled from 'styled-components'; | ||
|
||
import { Table } from 'src/components/Table'; | ||
import { Tabs } from 'src/components/Tabs'; | ||
import { Text } from 'src/components/Typography'; | ||
import { withColorSchemeDecorator } from 'src/storybook/decorators'; | ||
|
||
import { PageContainer, PageContainerProps } from './index'; | ||
|
||
const content = ( | ||
<> | ||
<Text> | ||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In suscipit magna sed pretium maximus. Duis | ||
bibendum a lacus ut commodo. Nam eget justo tristique, tincidunt ligula vel, accumsan odio. Morbi purus | ||
ante, bibendum vitae arcu eget, ultrices faucibus dolor. Sed fermentum blandit malesuada. Duis fringilla ac | ||
tortor ut convallis. Fusce iaculis arcu dui. Ut non neque rhoncus, tincidunt ipsum in, lobortis magna. Donec | ||
aliquet leo tellus. Proin pulvinar lacus sodales tortor eleifend rhoncus. Praesent varius maximus pulvinar. | ||
</Text> | ||
</> | ||
); | ||
|
||
const table = ( | ||
<Table | ||
bordered | ||
dataSource={[]} | ||
columns={[ | ||
{ | ||
title: 'Patient', | ||
dataIndex: 'patient', | ||
key: 'patient', | ||
width: '50%', | ||
render: () => '-', | ||
}, | ||
{ | ||
title: 'Practitioner', | ||
dataIndex: 'practitioner', | ||
key: 'practitioner', | ||
width: '50%', | ||
render: () => '-', | ||
}, | ||
]} | ||
/> | ||
); | ||
|
||
const tabs = ( | ||
<Tabs | ||
boxShadow={false} | ||
items={[ | ||
{ | ||
label: 'Tab', | ||
key: 'tab1', | ||
}, | ||
{ | ||
label: 'Tab', | ||
key: 'tab2', | ||
}, | ||
{ | ||
label: 'Tab', | ||
key: 'tab3', | ||
}, | ||
{ | ||
label: 'Tab', | ||
key: 'tab4', | ||
}, | ||
]} | ||
activeKey={'tab1'} | ||
/> | ||
); | ||
|
||
const S = { | ||
Container: styled.div` | ||
background-color: ${({ theme }) => theme.neutralPalette.gray_2}; | ||
`, | ||
CustomRightColumn: styled.div` | ||
display: flex; | ||
align-items: center; | ||
gap: 0 16px; | ||
`, | ||
Item: styled.div` | ||
display: flex; | ||
align-items: center; | ||
gap: 0 4px; | ||
color: ${({ theme }) => theme.neutral.secondaryText}; | ||
`, | ||
}; | ||
|
||
const rightColumn1 = ( | ||
<S.CustomRightColumn> | ||
<S.Item> | ||
<CalendarOutlined /> | ||
<Text>05/12/1955 • 66 y.o.</Text> | ||
</S.Item> | ||
<S.Item> | ||
<PhoneOutlined /> | ||
<Text>+972-222-3333</Text> | ||
</S.Item> | ||
<S.Item> | ||
<MailOutlined /> | ||
<Text>cooper@gmail.com</Text> | ||
</S.Item> | ||
</S.CustomRightColumn> | ||
); | ||
|
||
const rightColumn2 = ( | ||
<> | ||
<Input.Search placeholder="Search by email or phone" style={{ width: 328 }} /> | ||
<Button type="primary" icon={<PlusOutlined />}> | ||
Add patient | ||
</Button> | ||
</> | ||
); | ||
|
||
const meta: Meta<typeof PageContainer> = { | ||
title: 'Layout / PageContainer', | ||
component: PageContainer, | ||
// @ts-ignore | ||
decorators: [withColorSchemeDecorator], | ||
args: { | ||
title: 'Patients', | ||
children: content, | ||
}, | ||
render: (args) => { | ||
return ( | ||
<S.Container> | ||
<PageContainer {...args} /> | ||
</S.Container> | ||
); | ||
}, | ||
}; | ||
|
||
export default meta; | ||
|
||
type Story = StoryObj<PageContainerProps>; | ||
|
||
export const Default: Story = { | ||
args: { | ||
title: 'Madison Cooper', | ||
titleRightElement: rightColumn1, | ||
}, | ||
}; | ||
|
||
export const WithTable: Story = { | ||
args: { | ||
layoutVariant: 'with-table', | ||
children: table, | ||
titleRightElement: rightColumn2, | ||
}, | ||
}; | ||
|
||
export const WithTabs: Story = { | ||
args: { | ||
layoutVariant: 'with-tabs', | ||
headerContent: tabs, | ||
}, | ||
}; | ||
|
||
export const FullWidth: Story = { | ||
args: { | ||
maxWidth: '100%', | ||
}, | ||
}; | ||
|
||
export const CustomWidth: Story = { | ||
args: { | ||
maxWidth: 500, | ||
}, | ||
}; |
15 changes: 15 additions & 0 deletions
15
src/components/BaseLayout/PageContainer/PageContainerContent/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { S } from "./styles"; | ||
|
||
export type PageContainerContentProps = React.HTMLAttributes<HTMLDivElement> & { | ||
maxWidth?: number | string; | ||
}; | ||
|
||
export function PageContainerContent(props: PageContainerContentProps) { | ||
const { maxWidth, ...rest } = props; | ||
|
||
return ( | ||
<S.PageContentContainer> | ||
<S.PageContent {...rest} $maxWidth={maxWidth} /> | ||
</S.PageContentContainer> | ||
); | ||
} |
22 changes: 22 additions & 0 deletions
22
src/components/BaseLayout/PageContainer/PageContainerContent/styles.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import styled from 'styled-components'; | ||
|
||
import { maxWidthStyles } from '../PageContainerHeader/styles'; | ||
|
||
export const S = { | ||
PageContentContainer: styled.div` | ||
padding: 0 24px; | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
`, | ||
PageContent: styled.div<{ $maxWidth?: number | string }>` | ||
flex: 1; | ||
display: flex; | ||
flex-direction: column; | ||
padding: 32px 0; | ||
gap: 24px 0; | ||
width: 100%; | ||
${maxWidthStyles} | ||
`, | ||
}; |
15 changes: 15 additions & 0 deletions
15
src/components/BaseLayout/PageContainer/PageContainerHeader/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { S } from "./styles"; | ||
|
||
export type PageContainerHeaderProps = React.HTMLAttributes<HTMLDivElement> & { | ||
maxWidth?: number | string; | ||
}; | ||
|
||
export function PageContainerHeader(props: PageContainerHeaderProps) { | ||
const { maxWidth, ...rest } = props; | ||
|
||
return ( | ||
<S.PageHeaderContainer> | ||
<S.PageHeader {...rest} $maxWidth={maxWidth} /> | ||
</S.PageHeaderContainer> | ||
); | ||
} |
42 changes: 42 additions & 0 deletions
42
src/components/BaseLayout/PageContainer/PageContainerHeader/styles.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { isNumber, isString } from 'lodash'; | ||
import styled, { css } from 'styled-components'; | ||
|
||
export const maxWidthStyles = css<{ $maxWidth?: number | string }>` | ||
${({ $maxWidth }) => { | ||
if (isNumber($maxWidth)) { | ||
return css` | ||
max-width: ${() => `${$maxWidth}px`}; | ||
`; | ||
} | ||
if (isString($maxWidth)) { | ||
return css` | ||
max-width: ${() => `${$maxWidth}`}; | ||
`; | ||
} | ||
return css` | ||
max-width: 1080px; | ||
`; | ||
}} | ||
`; | ||
|
||
export const S = { | ||
PageHeaderContainer: styled.div` | ||
background-color: ${({ theme }) => theme.neutralPalette.gray_1}; | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
padding: 0 24px; | ||
`, | ||
PageHeader: styled.div<{ $maxWidth?: number | string }>` | ||
flex: 1; | ||
display: flex; | ||
flex-direction: column; | ||
padding: 24px 0; | ||
gap: 32px 0; | ||
width: 100%; | ||
${maxWidthStyles} | ||
`, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { S } from './styles'; | ||
|
||
export interface PageContainerProps { | ||
/** | ||
* The layout variant for the page. | ||
* Options: 'default', 'with-table', 'with-tabs'. | ||
*/ | ||
layoutVariant?: 'default' | 'with-table' | 'with-tabs'; | ||
|
||
/** | ||
* Maximum width of the page header and content area. | ||
* Accepts a number (in pixels) or a string (e.g., "100%"). | ||
*/ | ||
maxWidth?: number | string; | ||
|
||
/** | ||
* The main title of the page. | ||
* Can be a string or any ReactNode for custom rendering. | ||
*/ | ||
title?: React.ReactNode; | ||
|
||
/** | ||
* Content displayed to the left of the title. | ||
* Example: a back button. | ||
*/ | ||
titleLeftElement?: React.ReactNode; | ||
|
||
/** | ||
* Content displayed to the right of the title row. | ||
* Example: an action button or user details. | ||
*/ | ||
titleRightElement?: React.ReactNode; | ||
|
||
/** | ||
* Additional content displayed below the title in the header. | ||
* Example: a search bar or tabs. | ||
*/ | ||
headerContent?: React.ReactNode; | ||
|
||
/** | ||
* The main content of the page. | ||
* Typically includes the primary content to render below the header. | ||
*/ | ||
children?: React.ReactNode; | ||
} | ||
|
||
export function PageContainer(props: PageContainerProps = {}) { | ||
const { | ||
layoutVariant = 'default', | ||
title, | ||
headerContent, | ||
children, | ||
maxWidth, | ||
titleLeftElement, | ||
titleRightElement, | ||
} = props; | ||
|
||
return ( | ||
<> | ||
<S.HeaderContainer maxWidth={maxWidth} $variant={layoutVariant}> | ||
<S.Header> | ||
<S.HeaderLeftColumn> | ||
{titleLeftElement ? ( | ||
titleLeftElement | ||
) : ( | ||
<>{title && <PageContainerTitle>{title}</PageContainerTitle>}</> | ||
)} | ||
</S.HeaderLeftColumn> | ||
{titleRightElement && <S.HeaderRightColumn>{titleRightElement}</S.HeaderRightColumn>} | ||
</S.Header> | ||
{headerContent} | ||
</S.HeaderContainer> | ||
<S.ContentContainer $variant={layoutVariant} maxWidth={maxWidth}> | ||
{children} | ||
</S.ContentContainer> | ||
</> | ||
); | ||
} | ||
|
||
export function PageContainerTitle(props: React.HTMLAttributes<HTMLHeadingElement>) { | ||
return <S.Title level={3} {...props} />; | ||
} |
Oops, something went wrong.