Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions .storybook/adapters/PlainComponentAdapter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,15 @@ export const PlainComponentAdapter: ComponentsContextType = {
)
},

Box: ({ children, footer, className }: BoxProps) => {
return (
<div className={`box ${className || ''}`}>
<div className="box-body">{children}</div>
{footer && <div className="box-footer">{footer}</div>}
Box: ({ children, header, footer, withPadding = true, className }: BoxProps) => (
<div className={`box ${className || ''}`}>
{header && <div className="box-header">{header}</div>}
<div className="box-body" style={withPadding ? undefined : { padding: 0 }}>
{children}
</div>
)
},
{footer && <div className="box-footer">{footer}</div>}
</div>
),

TextInput: ({
label,
Expand Down Expand Up @@ -1117,10 +1118,15 @@ export const PlainComponentAdapter: ComponentsContextType = {
className,
'aria-label': ariaLabel,
emptyState,
variant,
...props
}: TableProps) => {
const embeddedStyles =
variant === 'embedded'
? { border: 'none', borderRadius: 0, boxShadow: 'none', background: 'transparent' }
: undefined
return (
<table className={className} aria-label={ariaLabel} {...props}>
<table className={className} aria-label={ariaLabel} style={embeddedStyles} {...props}>
<thead>
<tr>
{headers.map((header: TableData) => (
Expand Down
23 changes: 17 additions & 6 deletions docs/component-adapter/component-inventory.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- [BannerProps](#bannerprops)
- [BaseListProps](#baselistprops)
- [BoxProps](#boxprops)
- [BoxSectionProps](#boxsectionprops)
- [BreadcrumbsProps](#breadcrumbsprops)
- [Breadcrumb](#breadcrumb)
- [ButtonIconProps](#buttoniconprops)
Expand Down Expand Up @@ -97,11 +98,21 @@

## BoxProps

| Prop | Type | Required | Description |
| ------------- | ----------------- | -------- | ------------------------------------------------------------------------- |
| **children** | `React.ReactNode` | Yes | Content to be displayed inside the box |
| **footer** | `React.ReactNode` | No | Content rendered at the bottom of the box with an edge-to-edge top border |
| **className** | `string` | No | CSS className to be applied |
| Prop | Type | Required | Description |
| --------------- | ----------------- | -------- | ----------- |
| **children** | `React.ReactNode` | Yes | - |
| **header** | `React.ReactNode` | No | - |
| **footer** | `React.ReactNode` | No | - |
| **withPadding** | `boolean` | No | - |
| **className** | `string` | No | - |

## BoxSectionProps

| Prop | Type | Required | Description |
| ------------- | ---------------------- | -------- | ----------- |
| **children** | `React.ReactNode` | Yes | - |
| **className** | `string` | No | - |
| **variant** | `"default" \| "flush"` | No | - |

## BreadcrumbsProps

Expand Down Expand Up @@ -575,7 +586,7 @@ type PaginationItemsPerPage = 5 | 10 | 50
| **rows** | [TableRow](#tablerow)[] | Yes | Array of rows to be displayed in the table |
| **footer** | [TableData](#tabledata)[] | No | Array of footer cells for the table |
| **emptyState** | `React.ReactNode` | No | Content to display when the table has no rows |
| **variant** | `"default" \| "minimal"` | No | Visual style variant of the table |
| **variant** | `"default" \| "minimal" \| "embedded"` | No | Visual style variant of the table |
| **hasCheckboxColumn** | `boolean` | No | Whether the first column contains checkboxes (affects which column gets leading variant) |
| **className** | `string` | No | - |
| **id** | `string` | No | - |
Expand Down
15 changes: 12 additions & 3 deletions src/components/Common/UI/Box/Box.module.scss
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
.boxContainer {
.root {
width: 100%;
background-color: var(--g-colorBody);
box-shadow: var(--g-shadowResting);
border-radius: var(--g-boxRadius);
border: 1px solid var(--g-colorBorderSecondary);
}

.boxBody {
.header {
padding: toRem(20);
border-bottom: 1px solid var(--g-colorBorderSecondary);
}

.boxFooter {
.content {
padding: toRem(20);
}

.contentFlush {
padding: 0;
}

.footer {
padding: toRem(20);
border-top: 1px solid var(--g-colorBorderSecondary);
}
120 changes: 113 additions & 7 deletions src/components/Common/UI/Box/Box.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import type { StoryObj } from '@storybook/react-vite'
import type { BoxProps } from './BoxTypes'
import { useComponentContext } from '@/contexts/ComponentAdapter/useComponentContext'
import { Flex } from '@/components/Common/Flex'
import PlusCircleIcon from '@/assets/icons/plus-circle.svg?react'

const BoxWrapper = (args: Omit<BoxProps, 'children'>) => {
const BoxWrapper = () => {
const Components = useComponentContext()
return (
<Components.Box {...args}>
<Components.Box>
<Components.Text>This is content inside a box.</Components.Text>
</Components.Box>
)
Expand All @@ -18,8 +19,17 @@ export default {

type Story = StoryObj<typeof BoxWrapper>

export const Default: Story = {
args: {},
export const Default: Story = {}

export const WithHeader: Story = {
render: () => {
const Components = useComponentContext()
return (
<Components.Box header={<Components.Heading as="h3">Box Header</Components.Heading>}>
<Components.Text>This is the main content area with padding.</Components.Text>
</Components.Box>
)
},
}

export const WithFooter: Story = {
Expand All @@ -39,6 +49,38 @@ export const WithFooter: Story = {
},
}

export const WithAllSections: Story = {
render: () => {
const Components = useComponentContext()
return (
<Components.Box
header={
<Flex flexDirection="row" gap={16} justifyContent="space-between" alignItems="center">
<Flex flexDirection="column" gap={4}>
<Components.Heading as="h3">Box Header</Components.Heading>
<Components.Text variant="supporting">
This is a super cool description of the box header.
</Components.Text>
</Flex>
<Components.Button variant="secondary" onClick={() => {}}>
<PlusCircleIcon />
Do a thing
</Components.Button>
</Flex>
}
footer={
<Components.Button variant="secondary" onClick={() => {}}>
Add another something
</Components.Button>
}
>
<Components.Alert label="Woah! Check it out! An alert inside a box!" status="info" />
There is so much we can do here!
</Components.Box>
)
},
}

export const WithCustomClassName: Story = {
decorators: [
Story => (
Expand All @@ -48,7 +90,71 @@ export const WithCustomClassName: Story = {
</>
),
],
args: {
className: 'custom-box',
render: () => {
const Components = useComponentContext()
return (
<Components.Box className="custom-box">
<Components.Text>This box has a custom className applied.</Components.Text>
</Components.Box>
)
},
}

export const FlushContent: Story = {
render: () => {
const Components = useComponentContext()
return (
<Components.Box withPadding={false}>
<Components.Text>This content has no padding (flush variant).</Components.Text>
</Components.Box>
)
},
}

export const WithEmbeddedTable: Story = {
render: () => {
const Components = useComponentContext()
return (
<Components.Box
header={<Components.Heading as="h3">Team Members</Components.Heading>}
withPadding={false}
>
<Components.Table
aria-label="Team members"
variant="embedded"
headers={[
{ key: 'name', content: 'Name' },
{ key: 'role', content: 'Role' },
{ key: 'status', content: 'Status' },
]}
rows={[
{
key: '1',
data: [
{ key: 'name', content: 'Alice Johnson' },
{ key: 'role', content: 'Engineer' },
{ key: 'status', content: 'Active' },
],
},
{
key: '2',
data: [
{ key: 'name', content: 'Bob Smith' },
{ key: 'role', content: 'Designer' },
{ key: 'status', content: 'Active' },
],
},
{
key: '3',
data: [
{ key: 'name', content: 'Carol Davis' },
{ key: 'role', content: 'Manager' },
{ key: 'status', content: 'On Leave' },
],
},
]}
/>
</Components.Box>
)
},
}
Loading
Loading