Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Un 538 new accordion #463

Merged
merged 6 commits into from
Dec 18, 2024
Merged
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
1 change: 1 addition & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { GlobalStyle } from "./stories/shared/globalStyle";

// --- Accordions ---
export * from "./stories/accordions";
export * from "./stories/accordion-new";

// --- Alerts ---
export * from "./stories/notifications/alerts";
Expand Down
68 changes: 68 additions & 0 deletions src/stories/accordion-new/AccordionHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { Accordion as ZendeskAccordion } from "@zendeskgarden/react-accordions";
import { Checkbox, Field, Label } from "@zendeskgarden/react-forms";
import { forwardRef, useEffect, useState } from "react";
import styled from "styled-components";
import { theme } from "../theme";

export interface AccordionHeaderArgs extends React.HTMLAttributes<HTMLDivElement> {
hasCheckbox?: boolean;
checkboxProps?: React.ComponentProps<typeof Checkbox>;
isSelected?: boolean;
isLarge?: boolean;
icon?: React.ReactNode;
}

const StyledAccordionHeader = styled(ZendeskAccordion.Header)`
padding: ${theme.space.md};
display: flex;
gap: ${theme.space.xs};
align-items: flex-start;
[data-garden-id="accordions.rotate_icon"] {
padding: 0;
}
.accordion-header-inner-wrapper {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: ${theme.space.xs};
width: 100%;
}
`;

export const AccordionHeader = forwardRef<HTMLDivElement, AccordionHeaderArgs>(({
children,
isSelected,
hasCheckbox,
checkboxProps,
icon,
...rest
}, ref) => {
const handleCheckboxChange = (e: React.ChangeEvent<HTMLInputElement>) => {
e.stopPropagation();
if (typeof checkboxProps?.onChange === "function") {
checkboxProps.onChange(e);
}
return false;
}

return (
<StyledAccordionHeader ref={ref} {...rest}>
{hasCheckbox &&
<Field onChange={handleCheckboxChange}>
<Checkbox
{...checkboxProps}
onChange={handleCheckboxChange}
>
{checkboxProps?.["aria-label"]}
<Label hidden>
{checkboxProps?.["aria-label"]}
</Label>
</Checkbox>
</Field>}
{icon}
<div className="accordion-header-inner-wrapper">
{children}
</div>
</StyledAccordionHeader>
)
});
40 changes: 40 additions & 0 deletions src/stories/accordion-new/AccordionLabel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Accordion as ZendeskAccordion } from "@zendeskgarden/react-accordions";
import { forwardRef} from "react";
import { theme } from "../theme";
import styled from "styled-components";
import { LG, MD, SM } from "../typography/typescale";

interface AccordionLabelArgs extends React.HTMLAttributes<HTMLDivElement> {
isLarge?: boolean;
label?: string;
subtitle?: string;
supertitle?: string;
meta?: React.ReactNode;
}
const StyledAccordionLabel = styled(ZendeskAccordion.Label)<AccordionLabelArgs>`
padding: 0;
width: auto;
flex-grow: 1;
`;

export const AccordionLabel = forwardRef<HTMLButtonElement, AccordionLabelArgs>(({
label,
supertitle,
subtitle,
isLarge,
...rest
}, ref) => (
<StyledAccordionLabel ref={ref} {...rest}>
{supertitle && <SM color={theme.palette.grey[700]} style={{marginBottom: theme.space.xxs}}>{supertitle}</SM>}
{label &&
isLarge
? <LG isBold style={{marginBottom: theme.space.xxs}}>{label}</LG>
: <SM isBold style={{marginBottom: theme.space.xxs}}>{label}</SM>
}
{subtitle &&
isLarge
? <MD color={theme.palette.grey[600]} style={{marginBottom: theme.space.xs}}>{subtitle}</MD>
: <SM color={theme.palette.grey[600]} style={{marginBottom: theme.space.xs}}>{subtitle}</SM>
}
</StyledAccordionLabel>
));
16 changes: 16 additions & 0 deletions src/stories/accordion-new/AccordionMeta.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { forwardRef} from "react";
import styled from "styled-components";

interface AccordionMetaArgs extends React.HTMLAttributes<HTMLDivElement> {
}
const StyledAccordionMeta = styled.div<AccordionMetaArgs>`
`;

export const AccordionMeta = forwardRef<HTMLDivElement, AccordionMetaArgs>(({
children,
...rest
}, ref) => (
<StyledAccordionMeta ref={ref} {...rest}>
{children}
</StyledAccordionMeta>
));
19 changes: 19 additions & 0 deletions src/stories/accordion-new/AccordionSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Accordion as ZendeskAccordion } from "@zendeskgarden/react-accordions";
import { Checkbox, Field, Label } from "@zendeskgarden/react-forms";
import { forwardRef } from "react";
import styled from "styled-components";

export interface AccordionSectionArgs extends React.HTMLAttributes<HTMLDivElement> {
isSelected?: boolean;
}

export const AccordionSection = forwardRef<HTMLDivElement, AccordionSectionArgs>(({
children,
isSelected,
className,
...rest
}, ref) => (
<ZendeskAccordion.Section ref={ref} className={`${className} ${isSelected ? 'isSelected' : ''}`} {...rest}>
{children}
</ZendeskAccordion.Section>
));
66 changes: 66 additions & 0 deletions src/stories/accordion-new/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { Meta, StoryObj } from "@storybook/react";
import { AccordionArgs, AccordionNew } from ".";
import { Placeholder } from "../placeholder";

const accordionContent = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";

const items = [
{
accordionContent,
headerTitle: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, Equum cibum est optimum prandium est",
},
{
accordionContent,
headerTitle: "Lorem ipsum dolor sit amet, consectetur adipiscing elit",
},
{
accordionContent,
headerTitle: "Lorem ipsum dolor sit amet",
},
];

type StoryArgs = AccordionArgs & {};

const meta = {
title: "Molecules/New Accordion",
component: AccordionNew,

render: ({ ...args }) => {
return (

<AccordionNew {...args}>
{items.map((item) => {
return (
<AccordionNew.Section>
<AccordionNew.Header>
<AccordionNew.Label label={item.headerTitle} />
</AccordionNew.Header>
<AccordionNew.Panel><Placeholder /></AccordionNew.Panel>
</AccordionNew.Section>
)
})}
</AccordionNew>
);
},
} satisfies Meta<StoryArgs>;

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

const defaultArgs: StoryArgs = {
level: 3,
isBare: false
};

export const Default: Story = {
args: {
...defaultArgs,
},
};

export const Bare: Story = {
args: {
...defaultArgs,
isBare: true,
},
};
37 changes: 37 additions & 0 deletions src/stories/accordion-new/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Accordion as ZendeskAccordion } from "@zendeskgarden/react-accordions";
import { forwardRef } from "react";
import { IAccordionProps } from "@zendeskgarden/react-accordions";
import { AccordionHeader } from "./AccordionHeader";
import { AccordionSection } from "./AccordionSection";
import { AccordionLabel } from "./AccordionLabel";
import { AccordionMeta } from "./AccordionMeta";

export interface AccordionArgs extends IAccordionProps {
}

/**
* Accordions are headers that can be expanded to reveal content or collapsed to hide it.
* <hr>
* Used for this:
- To organize related information into sections
- To surface information through progressive disclosure
*/
const AccordionComponent = forwardRef<HTMLDivElement, AccordionArgs>((props, ref) => (
<ZendeskAccordion ref={ref} {...props} />
));



export const AccordionNew = AccordionComponent as typeof AccordionComponent & {
Section: typeof AccordionSection;
Header: typeof AccordionHeader;
Label: typeof AccordionLabel;
Meta: typeof AccordionMeta;
Panel: typeof ZendeskAccordion.Panel;
};

AccordionNew.Section = AccordionSection;
AccordionNew.Header = AccordionHeader;
AccordionNew.Label = AccordionLabel;
AccordionNew.Meta = AccordionMeta;
AccordionNew.Panel = ZendeskAccordion.Panel;
112 changes: 112 additions & 0 deletions src/stories/accordion-new/section.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { Meta, StoryObj } from "@storybook/react";
import { AccordionNew } from ".";
import { Checkbox } from "../forms/checkbox";
import React from "react";
import { ReactComponent as FolderIcon } from "@zendeskgarden/svg-icons/src/16/folder-open-stroke.svg";
import { Placeholder } from "../placeholder";
import { AccordionSectionArgs } from "./AccordionSection";


type StoryArgs = AccordionSectionArgs & {
hasCheckbox?: boolean;
selected?: boolean;
checkboxProps?: React.ComponentProps<typeof Checkbox>;
icon?: React.ReactNode;
isLarge?: boolean;
hasSubtitles?: boolean;
hasSupertitles?: boolean;
hasMeta?: boolean;
isOpen?: boolean;
};

const meta = {
title: "Molecules/New Accordion/Section",
component: AccordionNew.Section,
decorators: [
(Story: React.ComponentType, context) => {
return(
<AccordionNew level={3} expandedSections={context.args.isOpen ? [0] : []}>
<Story />
</AccordionNew>
)},
],
render: ({ ...args }) => {
return (
<AccordionNew.Section isSelected={args.selected}>
<AccordionNew.Header
hasCheckbox={args.hasCheckbox}
icon={args.icon}
>
<AccordionNew.Label isLarge={args.isLarge}
label="Lorem ipsum dolor sit amet, consectetur adipiscing elit, Equum cibum est optimum prandium est"
subtitle={args.hasSubtitles ? "Some more info on the item" : ""}
supertitle={args.hasSupertitles ? "00:00:23 - 00:00:27" : ""}
meta
/>
{args.hasMeta && <AccordionNew.Meta>
<Placeholder />
</AccordionNew.Meta>}
</AccordionNew.Header>
<AccordionNew.Panel><Placeholder /></AccordionNew.Panel>
</AccordionNew.Section>

);
},
} satisfies Meta<StoryArgs>;

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

const defaultArgs: StoryArgs = {
hasCheckbox: false,
isLarge: false,
hasSubtitles: false,
hasSupertitles: false,
hasMeta: false,
isOpen: false,
};

export const Default: Story = {
args: {
...defaultArgs,
},
};

export const Large: Story = {
args: {
...defaultArgs,
isLarge: true,
},
};

export const Selectable: Story = {
args: {
...defaultArgs,
hasCheckbox: true,
},
};

export const Icon: Story = {
args: {
...defaultArgs,
icon: <FolderIcon />,
},
};

export const WithMeta: Story = {
args: {
...defaultArgs,
hasMeta: true,
},
};

export const Full: Story = {
args: {
...defaultArgs,
icon: <FolderIcon />,
hasCheckbox: true,
hasSubtitles: true,
hasSupertitles: true,
hasMeta: true,
},
};
Loading