Skip to content

Commit

Permalink
feat(ui): Add the SectionCard Component (#2697)
Browse files Browse the repository at this point in the history
  • Loading branch information
sstraatemans authored Nov 27, 2024
1 parent 5c5c747 commit 4c684a2
Show file tree
Hide file tree
Showing 14 changed files with 1,099 additions and 97 deletions.
5 changes: 5 additions & 0 deletions .changeset/healthy-trainers-film.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@kadena/kode-ui': minor
---

add the SectionCard Component
24 changes: 24 additions & 0 deletions packages/libs/kode-ui/src/patterns/SectionCard/IconWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { FC } from 'react';
import React from 'react';
import { Stack } from './../../components';
import { LoaderIcon } from './LoaderIcon';
import type { ISectionCardProps } from './SectionCard';
import { iconWrapperClass, loadingIconClass } from './style.css';

interface IIconsProps {
icon: ISectionCardProps['icon'];
intent: ISectionCardProps['intent'];
variant: ISectionCardProps['variant'];
isLoading: boolean;
}

export const IconWrapper: FC<IIconsProps> = ({ icon, intent, isLoading }) => {
if (!icon) return null;

return (
<Stack className={iconWrapperClass({ intent, isLoading })}>
{icon}
{isLoading && <LoaderIcon className={loadingIconClass({ intent })} />}
</Stack>
);
};
34 changes: 34 additions & 0 deletions packages/libs/kode-ui/src/patterns/SectionCard/LoaderIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react';
export const LoaderIcon = ({ ...props }) => {
return (
<svg
data-style="animated"
xmlns="http://www.w3.org/2000/svg"
width={40}
height={40}
fill="none"
viewBox="20 20 40 40"
style={{
animation: 'rotate 2s linear infinite',
transformOrigin: 'center center',
}}
{...props}
>
<defs>
<style>
{
'\n .loader-path {\n stroke-dasharray: 150,200;\n stroke-dashoffset: -10;\n animation: dash 1.5s ease-in-out infinite, color 6s ease-in-out infinite;\n stroke-linecap: round;\n }\n\n @-webkit-keyframes rotate { 100% { transform: rotate(360deg); } }\n @keyframes rotate { 100% { transform: rotate(360deg); } }\n @-webkit-keyframes dash { 0% { stroke-dasharray: 1,200; stroke-dashoffset: 0; } 50% { stroke-dasharray: 89,200; stroke-dashoffset: -35; } 100% { stroke-dasharray: 89,200; stroke-dashoffset: -124; } }\n @keyframes dash { 0% { stroke-dasharray: 1,200; stroke-dashoffset: 0; } 50% { stroke-dasharray: 89,200; stroke-dashoffset: -35; } 100% { stroke-dasharray: 89,200; stroke-dashoffset: -124; } }\n @-webkit-keyframes color { 0% { stroke: currentColor; } 40% { stroke: currentColor; } 66% { stroke: currentColor; } 80%, 90% { stroke: currentColor; } }\n @keyframes color { 0% { stroke: currentColor; } 40% { stroke: currentColor; } 66% { stroke: currentColor; } 80%, 90% { stroke: currentColor; } }\n\n '
}
</style>
</defs>
<circle
className="loader-path"
cx={40}
cy={40}
r={19}
fill="none"
strokeWidth={2}
/>
</svg>
);
};
298 changes: 298 additions & 0 deletions packages/libs/kode-ui/src/patterns/SectionCard/SectionCard.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,298 @@
import { MonoAccessAlarm, MonoAdd } from '@kadena/kode-icons/system';
import type { Meta, StoryObj } from '@storybook/react';
import React from 'react';
import { Button, Stack, Text } from './../../components';
import { getVariants } from './../../storyDecorators';
import type { ISectionCardProps } from './SectionCard';
import { SectionCard } from './SectionCard';
import type { ISectionCardBodyProps } from './SectionCardBody';
import { SectionCardBody } from './SectionCardBody';
import { SectionCardContentBlock } from './SectionCardContentBlock';
import type { ISectionCardHeaderProps } from './SectionCardHeader';
import { SectionCardHeader } from './SectionCardHeader';
import { iconWrapperClass } from './style.css';

const intentVariants = getVariants(iconWrapperClass);

interface IProps
extends ISectionCardHeaderProps,
ISectionCardProps,
ISectionCardBodyProps {}

const meta: Meta<IProps> = {
title: 'Patterns/SectionCard',
parameters: {
status: { type: 'stable' },
docs: {
description: {
component:
'The card can have multiple sections, a title and content section. `Buttons` in the actions prop have to be compact variants',
},
},
},
argTypes: {
intent: {
options: intentVariants.intent,
control: {
type: 'select',
},
description: 'intent color',
table: {
type: { summary: intentVariants.intent.join(' | ') },
defaultValue: { summary: 'default' },
},
},
title: {
control: {
type: 'text',
},
description: 'Card Title',
},
description: {
description: 'Card description',
control: {
type: 'text',
},
},
stack: {
options: ['horizontal', 'vertical'],
control: {
type: 'select',
},
},
children: {
control: {
type: 'text',
},
description: 'The main content for the card',
},
},
};

export default meta;
type Story = StoryObj<IProps>;

const Actions = () => {
return (
<Button variant="outlined" isCompact endVisual={<MonoAdd />}>
add
</Button>
);
};

export const Primary: Story = {
name: 'SectionCard basecard',
args: {
title: 'Our section',
description: <>Our section is awesome</>,
actions: <Actions />,
children: 'This is the content for our section',
},
render: ({ stack, title, description, children, actions, intent }) => {
return (
<Stack width="100%" padding="lg">
<SectionCard stack={stack} intent={intent}>
<SectionCardContentBlock>
<SectionCardBody
title="Content title"
description="small description"
>
{children}
</SectionCardBody>
<SectionCardHeader
title={title}
description={description}
actions={actions}
/>
<div>sdfsdf</div>
</SectionCardContentBlock>
</SectionCard>
</Stack>
);
},
};

export const main: Story = {
name: 'SectionCard mainCard',
args: {
title: 'Our section',
description: <>Our section is awesome</>,
actions: <Actions />,
children: 'This is the content for our section',
},
render: ({ stack, title, description, children, actions, intent }) => {
return (
<Stack width="100%" padding="lg">
<SectionCard stack={stack} variant="main" intent={intent}>
<SectionCardContentBlock>
<SectionCardBody
title="Content title"
description="small description"
>
{children}
<Text>this is content</Text>
<Text>this is content</Text>
<Text>this is content</Text>
<Text>this is content</Text>
<Text>this is content</Text>
</SectionCardBody>
<SectionCardHeader
title={title}
description={description}
actions={actions}
/>
</SectionCardContentBlock>
</SectionCard>
</Stack>
);
},
};

export const withIcon: Story = {
name: 'SectionCard card with Icon',
args: {
title: 'Our section',
description: <>Our section is awesome</>,
actions: <Actions />,
children: 'This is the content for our section',
},
render: ({ stack, title, description, children, actions, intent }) => {
return (
<Stack width="100%" padding="lg">
<SectionCard stack={stack} icon={<MonoAccessAlarm />} intent={intent}>
<SectionCardContentBlock>
<SectionCardBody
title="Content title"
description="small description"
>
{children}
<Text>this is content</Text>
<Text>this is content</Text>
<Text>this is content</Text>
<Text>this is content</Text>
<Text>this is content</Text>
</SectionCardBody>
<SectionCardHeader
title={title}
description={description}
actions={actions}
/>
</SectionCardContentBlock>
</SectionCard>
</Stack>
);
},
};

export const withIconIsLoading: Story = {
name: 'SectionCard loading state',
args: {
title: 'Our section',
description: <>Our section is awesome</>,
actions: <Actions />,
children: 'This is the content for our section',
intent: 'info',
},
render: ({ stack, title, description, children, actions, intent }) => {
return (
<Stack width="100%" padding="lg">
<SectionCard
stack={stack}
icon={<MonoAccessAlarm />}
intent={intent}
isLoading
>
<SectionCardContentBlock>
<SectionCardBody
title="Content title"
description="small description"
>
{children}
<Text>this is content</Text>
<Text>this is content</Text>
<Text>this is content</Text>
<Text>this is content</Text>
<Text>this is content</Text>
</SectionCardBody>
<SectionCardHeader
title={title}
description={description}
actions={actions}
/>
</SectionCardContentBlock>
</SectionCard>
</Stack>
);
},
};

export const reverseBackground: Story = {
name: 'SectionCard Reversed background',
args: {
title: 'Our section',
description: <>Our section is awesome</>,
actions: <Actions />,
children: 'This is the content for our section',
},
render: ({ stack, title, description, children, actions, intent }) => {
return (
<Stack width="100%" padding="lg">
<SectionCard background="reversed" stack={stack}>
<SectionCardContentBlock>
<SectionCardBody
title="Content title"
description="small description"
>
{children}
<Text>this is content</Text>
<Text>this is content</Text>
<Text>this is content</Text>
<Text>this is content</Text>
<Text>this is content</Text>
</SectionCardBody>
<SectionCardHeader
title={title}
description={description}
actions={actions}
/>
</SectionCardContentBlock>
</SectionCard>
</Stack>
);
},
};
export const noBackground: Story = {
name: 'SectionCard No background',
args: {
title: 'Our section',
description: <>Our section is awesome</>,
actions: <Actions />,
children: 'This is the content for our section',
},
render: ({ stack, title, description, children, actions, intent }) => {
return (
<Stack width="100%" padding="lg">
<SectionCard background="none" stack={stack}>
<SectionCardContentBlock>
<SectionCardBody
title="Content title"
description="small description"
>
{children}
<Text>this is content</Text>
<Text>this is content</Text>
<Text>this is content</Text>
<Text>this is content</Text>
<Text>this is content</Text>
</SectionCardBody>
<SectionCardHeader
title={title}
description={description}
actions={actions}
/>
</SectionCardContentBlock>
</SectionCard>
</Stack>
);
},
};
Loading

0 comments on commit 4c684a2

Please sign in to comment.