Commit cb616f80 by Moorthy G

refactor: update stories layout

parent e4f424b4
# MAF CORPORATE WEBSITE
# NEXTJS STARTER TEMPLATE
## Tools Configured
......
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from "@heroui/button";
import type { ButtonProps } from "@heroui/button";
const meta: Meta<typeof Button> = {
title: 'Basic/Button',
component: Button,
tags: ['autodocs']
};
export default meta;
type Story = StoryObj<typeof meta>;
type TemplateProps = {
color: ButtonProps['color'];
};
const Template = ({ color }: TemplateProps) => {
return (
<div>
<h6 className="mb-2 font-semibold">Size</h6>
<div className="flex gap-5 mb-4 flex-wrap items-center">
<Button color={color} size="sm">
Small button
</Button>
<Button color={color} size="md">
Medium button
</Button>
<Button color={color} size="lg">
Large button
</Button>
<Button color={color} size="sm" variant="ghost">
Small Outline
</Button>
<Button color={color} size="md" variant="ghost">
Medium Outline
</Button>
<Button color={color} size="lg" variant="ghost">
Large Outline
</Button>
</div>
<h6 className="mb-2 font-semibold">Loading</h6>
<div className="flex gap-5 mb-4 flex-wrap items-center">
<Button color={color} size="sm" isLoading>
Small button
</Button>
<Button color={color} size="md" isLoading>
Medium button
</Button>
<Button color={color} size="lg" isLoading>
Large button
</Button>
<Button color={color} size="sm" variant="ghost" isLoading>
Small Outline
</Button>
<Button color={color} size="md" variant="ghost" isLoading>
Medium Outline
</Button>
<Button color={color} size="lg" variant="ghost" isLoading>
Large Outline
</Button>
</div>
<h6 className="mb-2 font-semibold">Disabled</h6>
<div className="flex gap-5 mb-4 flex-wrap items-center">
<Button color={color} size="sm" isDisabled>
Small button
</Button>
<Button color={color} size="md" isDisabled>
Medium button
</Button>
<Button color={color} size="lg" isDisabled>
Large button
</Button>
<Button color={color} size="sm" variant="ghost" isDisabled>
Small Outline
</Button>
<Button color={color} size="md" variant="ghost" isDisabled>
Medium Outline
</Button>
<Button color={color} size="lg" variant="ghost" isDisabled>
Large Outline
</Button>
</div>
<h6 className="mb-2 font-semibold">Full Width</h6>
<div className="flex flex-col gap-5">
<Button color={color} size="sm" fullWidth>
Small button
</Button>
<Button color={color} size="md" fullWidth>
Medium button
</Button>
<Button color={color} size="lg" fullWidth>
Large button
</Button>
<Button color={color} size="sm" variant="ghost" fullWidth>
Small Outline
</Button>
<Button color={color} size="md" variant="ghost" fullWidth>
Medium Outline
</Button>
<Button color={color} size="lg" variant="ghost" fullWidth>
Large Outline
</Button>
</div>
</div>
);
};
export const Default: Story = {
render: () => <Template color="default" />
};
export const Primary: Story = {
render: () => <Template color="primary" />
};
export const Secondary: Story = {
render: () => <Template color="secondary" />
};
export const Success: Story = {
render: () => <Template color="success" />
};
export const Warning: Story = {
render: () => <Template color="warning" />
};
export const Danger: Story = {
render: () => <Template color="danger" />
};
import type { Meta, StoryObj } from '@storybook/nextjs';
import { Button, type ButtonProps } from '@heroui/button';
const meta: Meta<typeof Button> = {
title: 'Basic/Button',
component: Button,
tags: ['autodocs']
};
export default meta;
type Story = StoryObj<typeof meta>;
type TemplateProps = {
color: ButtonProps['color'];
};
const Template = ({ color }: TemplateProps) => {
return (
<div>
<h6 className="mb-2 font-semibold">Size</h6>
<div className="flex gap-5 mb-4 flex-wrap items-center">
<Button color={color} size="sm">
Small button
</Button>
<Button color={color} size="md">
Medium button
</Button>
<Button color={color} size="lg">
Large button
</Button>
</div>
<h6 className="mb-2 font-semibold">Variants</h6>
<div className="flex gap-5 mb-4 flex-wrap items-center">
<Button color={color} variant="solid">
Solid Button
</Button>
<Button color={color} variant="faded">
Faded Button
</Button>
<Button color={color} variant="bordered">
Bordered Button
</Button>
<Button color={color} variant="light">
Light Button
</Button>
<Button color={color} variant="flat">
Flat Button
</Button>
<Button color={color} variant="ghost">
Ghost Button
</Button>
<Button color={color} variant="shadow">
Shadow Button
</Button>
</div>
<h6 className="mb-2 font-semibold">Loading Variants</h6>
<div className="flex gap-5 mb-4 flex-wrap items-center">
<Button color={color} variant="solid">
Solid Button
</Button>
<Button color={color} variant="faded" isLoading>
Faded Button
</Button>
<Button color={color} variant="bordered" isLoading>
Bordered Button
</Button>
<Button color={color} variant="light" isLoading>
Light Button
</Button>
<Button color={color} variant="flat" isLoading>
Flat Button
</Button>
<Button color={color} variant="ghost" isLoading>
Ghost Button
</Button>
<Button color={color} variant="shadow" isLoading>
Shadow Button
</Button>
</div>
<h6 className="mb-2 font-semibold">Disabled Variants</h6>
<div className="flex gap-5 mb-4 flex-wrap items-center">
<Button color={color} variant="solid" isDisabled>
Solid Button
</Button>
<Button color={color} variant="faded" isDisabled>
Faded Button
</Button>
<Button color={color} variant="bordered" isDisabled>
Bordered Button
</Button>
<Button color={color} variant="light" isDisabled>
Light Button
</Button>
<Button color={color} variant="flat" isDisabled>
Flat Button
</Button>
<Button color={color} variant="ghost" isDisabled>
Ghost Button
</Button>
<Button color={color} variant="shadow" isDisabled>
Shadow Button
</Button>
</div>
</div>
);
};
export const Default: Story = {
render: () => <Template color="default" />
};
export const Primary: Story = {
render: () => <Template color="primary" />
};
export const Secondary: Story = {
render: () => <Template color="secondary" />
};
......@@ -11,21 +11,21 @@
"analyze": "cross-env ANALYZE=true next build"
},
"dependencies": {
"@heroui/react": "2.8.0-beta.4",
"@storybook/react": "^9.0.15",
"@heroui/react": "2.8.0-beta.15",
"@storybook/react": "^9.0.16",
"@tailwindcss/postcss": "^4.1.11",
"@types/node": "^24.0.10",
"@types/node": "^24.0.13",
"@types/react": "^19.1.8",
"autoprefixer": "^10.4.21",
"classnames": "^2.5.1",
"clsx": "^2.1.1",
"color2k": "^2.0.3",
"framer-motion": "^12.23.0",
"framer-motion": "^12.23.3",
"next": "^15.3.5",
"postcss": "^8.5.6",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"sharp": "^0.34.2",
"sharp": "^0.34.3",
"tailwindcss": "^4.1.11",
"typescript": "^5.8.3"
},
......@@ -33,19 +33,19 @@
"@commitlint/cli": "^19.8.1",
"@commitlint/config-conventional": "^19.8.1",
"@next/bundle-analyzer": "^15.3.5",
"@storybook/addon-links": "^9.0.15",
"@storybook/addon-themes": "^9.0.15",
"@storybook/nextjs": "^9.0.15",
"@storybook/addon-links": "^9.0.16",
"@storybook/addon-themes": "^9.0.16",
"@storybook/nextjs": "^9.0.16",
"@types/eslint": "^9.6.1",
"cross-env": "^7.0.3",
"cz-conventional-changelog": "^3.3.0",
"eslint": "^9.30.1",
"eslint-config-next": "^15.3.5",
"eslint-plugin-storybook": "^9.0.15",
"eslint-plugin-storybook": "^9.0.16",
"husky": "^9.1.7",
"prettier": "^3.6.2",
"pretty-quick": "^4.2.2",
"storybook": "^9.0.15"
"storybook": "^9.0.16"
},
"packageManager": "pnpm@10.6.5+sha256.47c8bca42b4b48534b5b1b28d573c506773937b02f68e52992fbd8269131c5c8"
}
This source diff could not be displayed because it is too large. You can view the blob instead.
import React from 'react';
import { Meta } from '@storybook/react';
import { parseToRgba, readableColor } from 'color2k';
type ColorsItem = {
color: string;
className?: string;
textClassName?: string;
};
type SwatchColors = {
title: string;
items: ColorsItem[];
};
type SwatchSetProps = {
colors: SwatchColors[];
isSemantic?: boolean;
};
const Swatch = ({ color }: { color: string }) => {
const colorText = color
? `#${parseToRgba(color)
.slice(0, 3)
.map((x) => x.toString(16).padStart(2, '0'))
.join('')
.toUpperCase()}`
: 'N/A';
return (
<div
className="flex flex-col items-center justify-center w-28 h-28 m-2 rounded-xl shadow-lg"
style={{
backgroundColor: color
}}>
<span
style={{
color: readableColor(color)
}}>
{colorText}
</span>
</div>
);
};
const SemanticSwatch = ({
color,
className,
textClassName
}: {
color: string;
className?: string;
textClassName?: string;
}) => {
return (
<div
className={`${className} flex flex-col items-center justify-center w-28 h-28 m-2 rounded-xl shadow-lg`}>
<span className={`${textClassName} text-sm`}>{color}</span>
</div>
);
};
const SwatchSet = ({ colors, isSemantic = false }: SwatchSetProps) => (
<div className="flex flex-row flex-wrap items-center justify-center w-full h-full p-2">
{colors.map(({ title, items }) => (
<div key={title} className="flex flex-col items-start w-full h-full">
<h2 className="text-xl font-bold text-foreground">{title}</h2>
<div className="flex flex-row flex-wrap items-center justify-start w-full h-full p-4">
{items.map((c, index) =>
isSemantic ? (
<SemanticSwatch
key={`${c.color}-${index}`}
className={c.className}
color={c.color}
textClassName={c.textClassName}
/>
) : (
<Swatch key={`${c.color}-${index}`} color={c.color} />
)
)}
</div>
</div>
))}
</div>
);
export default {
title: 'Foundations/SemanticColors',
component: SwatchSet,
argTypes: {
isSemantic: {
control: false
}
}
} as Meta<typeof SwatchSet>;
export const SemanticColors = {
args: {
isSemantic: true,
colors: [
{
title: 'Layout',
items: [
{
color: 'background',
className: 'bg-background',
textClassName: 'text-foreground'
},
{
color: 'foreground',
className: 'bg-foreground',
textClassName: 'text-background'
},
{
color: 'divider',
className: 'bg-divider',
textClassName: 'text-foreground'
},
{
color: 'focus',
className: 'bg-focus',
textClassName: 'text-primary-foreground'
}
]
},
{
title: 'Content',
items: [
{
color: 'content1',
className: 'bg-content1',
textClassName: 'text-content1-foreground'
},
{
color: 'content2',
className: 'bg-content2',
textClassName: 'text-content2-foreground'
},
{
color: 'content3',
className: 'bg-content3',
textClassName: 'text-content3-foreground'
},
{
color: 'content4',
className: 'bg-content4',
textClassName: 'text-content4-foreground'
}
]
},
{
title: 'Base',
items: [
{
color: 'default',
className: 'bg-default',
textClassName: 'text-default-foreground'
},
{
color: 'primary',
className: 'bg-primary',
textClassName: 'text-primary-foreground'
},
{
color: 'secondary',
className: 'bg-secondary',
textClassName: 'text-secondary-foreground'
},
{
color: 'success',
className: 'bg-success',
textClassName: 'text-success-foreground'
},
{
color: 'warning',
className: 'bg-warning',
textClassName: 'text-warning-foreground'
},
{
color: 'danger',
className: 'bg-danger',
textClassName: 'text-danger-foreground'
}
]
},
{
title: 'Default',
items: [
{
color: 'default-50',
className: 'bg-default-50',
textClassName: 'text-default-900'
},
{
color: 'default-100',
className: 'bg-default-100',
textClassName: 'text-default-900'
},
{
color: 'default-200',
className: 'bg-default-200',
textClassName: 'text-default-800'
},
{
color: 'default-300',
className: 'bg-default-300',
textClassName: 'text-default-800'
},
{
color: 'default-400',
className: 'bg-default-400',
textClassName: 'text-default-800'
},
{
color: 'default-500',
className: 'bg-default-500',
textClassName: 'text-default-foreground'
},
{
color: 'default-600',
className: 'bg-default-600',
textClassName: 'text-default-50'
},
{
color: 'default-700',
className: 'bg-default-700',
textClassName: 'text-default-100'
},
{
color: 'default-800',
className: 'bg-default-800',
textClassName: 'text-default-100'
},
{
color: 'default-900',
className: 'bg-default-900',
textClassName: 'text-default-100'
}
]
},
{
title: 'Primary',
items: [
{
color: 'primary-50',
className: 'bg-primary-50',
textClassName: 'text-primary-900'
},
{
color: 'primary-100',
className: 'bg-primary-100',
textClassName: 'text-primary-900'
},
{
color: 'primary-200',
className: 'bg-primary-200',
textClassName: 'text-primary-800'
},
{
color: 'primary-300',
className: 'bg-primary-300',
textClassName: 'text-primary-800'
},
{
color: 'primary-400',
className: 'bg-primary-400',
textClassName: 'text-primary-800'
},
{
color: 'primary-500',
className: 'bg-primary-500',
textClassName: 'text-primary-foreground'
},
{
color: 'primary-600',
className: 'bg-primary-600',
textClassName: 'text-primary-50'
},
{
color: 'primary-700',
className: 'bg-primary-700',
textClassName: 'text-primary-100'
},
{
color: 'primary-800',
className: 'bg-primary-800',
textClassName: 'text-primary-100'
},
{
color: 'primary-900',
className: 'bg-primary-900',
textClassName: 'text-primary-100'
}
]
},
{
title: 'Secondary',
items: [
{
color: 'secondary-50',
className: 'bg-secondary-50',
textClassName: 'text-secondary-900'
},
{
color: 'secondary-100',
className: 'bg-secondary-100',
textClassName: 'text-secondary-900'
},
{
color: 'secondary-200',
className: 'bg-secondary-200',
textClassName: 'text-secondary-800'
},
{
color: 'secondary-300',
className: 'bg-secondary-300',
textClassName: 'text-secondary-800'
},
{
color: 'secondary-400',
className: 'bg-secondary-400',
textClassName: 'text-secondary-800'
},
{
color: 'secondary-500',
className: 'bg-secondary-500',
textClassName: 'text-secondary-foreground'
},
{
color: 'secondary-600',
className: 'bg-secondary-600',
textClassName: 'text-secondary-50'
},
{
color: 'secondary-700',
className: 'bg-secondary-700',
textClassName: 'text-secondary-100'
},
{
color: 'secondary-800',
className: 'bg-secondary-800',
textClassName: 'text-secondary-100'
},
{
color: 'secondary-900',
className: 'bg-secondary-900',
textClassName: 'text-secondary-100'
}
]
},
{
title: 'Success',
items: [
{
color: 'success-50',
className: 'bg-success-50',
textClassName: 'text-success-900'
},
{
color: 'success-100',
className: 'bg-success-100',
textClassName: 'text-success-900'
},
{
color: 'success-200',
className: 'bg-success-200',
textClassName: 'text-success-800'
},
{
color: 'success-300',
className: 'bg-success-300',
textClassName: 'text-success-800'
},
{
color: 'success-400',
className: 'bg-success-400',
textClassName: 'text-success-800'
},
{
color: 'success-500',
className: 'bg-success-500',
textClassName: 'text-success-foreground'
},
{
color: 'success-600',
className: 'bg-success-600',
textClassName: 'text-success-50'
},
{
color: 'success-700',
className: 'bg-success-700',
textClassName: 'text-success-100'
},
{
color: 'success-800',
className: 'bg-success-800',
textClassName: 'text-success-100'
},
{
color: 'success-900',
className: 'bg-success-900',
textClassName: 'text-success-100'
}
]
},
{
title: 'Warning',
items: [
{
color: 'warning-50',
className: 'bg-warning-50',
textClassName: 'text-warning-900'
},
{
color: 'warning-100',
className: 'bg-warning-100',
textClassName: 'text-warning-900'
},
{
color: 'warning-200',
className: 'bg-warning-200',
textClassName: 'text-warning-800'
},
{
color: 'warning-300',
className: 'bg-warning-300',
textClassName: 'text-warning-800'
},
{
color: 'warning-400',
className: 'bg-warning-400',
textClassName: 'text-warning-800'
},
{
color: 'warning-500',
className: 'bg-warning-500',
textClassName: 'text-warning-foreground'
},
{
color: 'warning-600',
className: 'bg-warning-600',
textClassName: 'text-warning-50'
},
{
color: 'warning-700',
className: 'bg-warning-700',
textClassName: 'text-warning-100'
},
{
color: 'warning-800',
className: 'bg-warning-800',
textClassName: 'text-warning-100'
},
{
color: 'warning-900',
className: 'bg-warning-900',
textClassName: 'text-warning-100'
}
]
},
{
title: 'Danger',
items: [
{
color: 'danger-50',
className: 'bg-danger-50',
textClassName: 'text-danger-900'
},
{
color: 'danger-100',
className: 'bg-danger-100',
textClassName: 'text-danger-900'
},
{
color: 'danger-200',
className: 'bg-danger-200',
textClassName: 'text-danger-800'
},
{
color: 'danger-300',
className: 'bg-danger-300',
textClassName: 'text-danger-800'
},
{
color: 'danger-400',
className: 'bg-danger-400',
textClassName: 'text-danger-800'
},
{
color: 'danger-500',
className: 'bg-danger-500',
textClassName: 'text-danger-foreground'
},
{
color: 'danger-600',
className: 'bg-danger-600',
textClassName: 'text-danger-50'
},
{
color: 'danger-700',
className: 'bg-danger-700',
textClassName: 'text-danger-100'
},
{
color: 'danger-800',
className: 'bg-danger-800',
textClassName: 'text-danger-100'
},
{
color: 'danger-900',
className: 'bg-danger-900',
textClassName: 'text-danger-100'
}
]
}
]
}
};
import React from 'react';
import { Meta } from '@storybook/nextjs';
type ColorsItem = {
color: string;
className?: string;
textClassName?: string;
};
type SwatchColors = {
title: string;
items: ColorsItem[];
};
type SwatchSetProps = {
colors: SwatchColors[];
};
const SemanticSwatch = ({
color,
className,
textClassName
}: {
color: string;
className?: string;
textClassName?: string;
}) => {
return (
<div
className={`${className} ${textClassName} text-sm flex flex-col items-center justify-center w-24 h-24 m-1 rounded shadow-lg`}>
<span>{color}</span>
</div>
);
};
const SwatchSet = ({ colors }: SwatchSetProps) => (
<div className="flex flex-row flex-wrap items-center justify-center w-full h-full py-2">
{colors.map(({ title, items }) => (
<div key={title} className="flex flex-col items-start w-full h-full">
<h2 className="text-xl font-bold text-foreground">{title}</h2>
<div className="flex flex-row flex-wrap items-center justify-start w-full h-full py-4">
{items.map((c, index) => (
<SemanticSwatch
key={`${c.color}-${index}`}
className={c.className}
color={c.color}
textClassName={c.textClassName}
/>
))}
</div>
</div>
))}
</div>
);
// Background color key -> Text color value mapping
/** we need it for tailwind to detect the color */
const COLOR_CLASS_MAP = {
layout: {
'bg-background': 'text-foreground',
'bg-foreground': 'text-background',
'bg-divider': 'text-foreground',
'bg-focus': 'text-primary-foreground'
},
base: {
'bg-default': 'text-default-foreground',
'bg-primary': 'text-primary-foreground',
'bg-secondary': 'text-secondary-foreground',
'bg-danger': 'text-danger-foreground',
'bg-warning': 'text-warning-foreground',
'bg-success': 'text-success-foreground'
},
default: {
'bg-default-50': 'text-default-900',
'bg-default-100': 'text-default-900',
'bg-default-200': 'text-default-800',
'bg-default-300': 'text-default-800',
'bg-default-400': 'text-default-800',
'bg-default-500': 'text-default-foreground',
'bg-default-600': 'text-default-50',
'bg-default-700': 'text-default-100',
'bg-default-800': 'text-default-100',
'bg-default-900': 'text-default-100'
},
primary: {
'bg-primary-50': 'text-primary-900',
'bg-primary-100': 'text-primary-900',
'bg-primary-200': 'text-primary-800',
'bg-primary-300': 'text-primary-800',
'bg-primary-400': 'text-primary-800',
'bg-primary-500': 'text-primary-foreground',
'bg-primary-600': 'text-primary-50',
'bg-primary-700': 'text-primary-100',
'bg-primary-800': 'text-primary-100',
'bg-primary-900': 'text-primary-100'
},
secondary: {
'bg-secondary-50': 'text-secondary-900',
'bg-secondary-100': 'text-secondary-700',
'bg-secondary-200': 'text-secondary-700',
'bg-secondary-300': 'text-secondary-700',
'bg-secondary-400': 'text-secondary-700',
'bg-secondary-500': 'text-secondary-50',
'bg-secondary-600': 'text-secondary-50',
'bg-secondary-700': 'text-secondary-100',
'bg-secondary-800': 'text-secondary-100',
'bg-secondary-900': 'text-secondary-100'
}
};
const generateColorScale = (colorName: string): ColorsItem[] => {
const colorMap = COLOR_CLASS_MAP[colorName as keyof typeof COLOR_CLASS_MAP];
if (!colorMap) return [];
return Object.keys(colorMap).map((bgClassName) => {
// Extract color name from bg class (e.g., 'bg-default-50' -> 'default-50')
const colorDisplayName = bgClassName.replace('bg-', '');
return {
color: colorDisplayName,
className: bgClassName,
textClassName: colorMap[bgClassName as keyof typeof colorMap]
};
});
};
const generateColorSections = (): SwatchColors[] => {
const colorNames = Object.keys(COLOR_CLASS_MAP);
return colorNames.map((colorName) => ({
title: colorName.charAt(0).toUpperCase() + colorName.slice(1),
items: generateColorScale(colorName)
}));
};
export default {
title: 'Foundations/01-SemanticColors',
component: SwatchSet
} as Meta<typeof SwatchSet>;
export const SemanticColors = {
args: {
colors: generateColorSections()
}
};
export default {
title: 'Foundations/Typography'
};
export const Typography = () => (
<div className="container">
<div className="flex flex-col gap-4 mb-5">
<div className="text-9xl font-bold">Heading</div>
<div className="text-8xl font-bold">Heading</div>
<div className="text-7xl font-bold">Heading</div>
<div className="text-6xl font-bold">Heading</div>
<div className="text-5xl font-bold">Heading</div>
<div className="text-4xl font-bold">Heading</div>
<div className="text-3xl font-bold">Heading</div>
<div className="text-2xl font-bold">Heading</div>
<div className="text-xl font-bold">Heading</div>
</div>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Nemo et quae
consequuntur voluptatum quibusdam, autem velit quidem laborum, dignissimos
doloremque ullam eos fugit repellendus maiores eveniet repellat dolor eius
perspiciatis? Lorem ipsum dolor sit amet, consectetur adipisicing elit.
</p>
<p>
Quasi aliquam impedit magnam tempora doloribus voluptatibus, at ea dolores
facilis et quod hic, cumque repellendus quidem expedita explicabo
architecto, possimus minima!
</p>
</div>
);
export default {
title: 'Foundations/02-Typography'
};
export const Typography = () => (
<div className="container">
<div className="flex flex-col gap-4 mb-5">
<div className="text-9xl font-bold">Heading</div>
<div className="text-8xl font-bold">Heading</div>
<div className="text-7xl font-bold">Heading</div>
<div className="text-6xl font-bold">Heading</div>
<div className="text-5xl font-bold">Heading</div>
<div className="text-4xl font-bold">Heading</div>
<div className="text-3xl font-bold">Heading</div>
<div className="text-2xl font-bold">Heading</div>
<div className="text-xl font-bold">Heading</div>
</div>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Nemo et quae
consequuntur voluptatum quibusdam, autem velit quidem laborum, dignissimos
doloremque ullam eos fugit repellendus maiores eveniet repellat dolor eius
perspiciatis? Lorem ipsum dolor sit amet, consectetur adipisicing elit.
</p>
<p>
Quasi aliquam impedit magnam tempora doloribus voluptatibus, at ea dolores
facilis et quod hic, cumque repellendus quidem expedita explicabo
architecto, possimus minima!
</p>
</div>
);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment