Skip to content

Commit

Permalink
feat: add selectedHeaderCSS and contentCSS
Browse files Browse the repository at this point in the history
  • Loading branch information
jamiehenson committed Nov 12, 2024
1 parent 69afe01 commit cbf00c0
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 64 deletions.
82 changes: 33 additions & 49 deletions src/core/Accordion.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { ReactNode, useMemo } from "react";
import React, { ReactNode, useMemo, useState } from "react";
import {
AccordionContent,
AccordionItem,
Expand All @@ -9,7 +9,6 @@ import clsx from "clsx";

import Icon from "./Icon";
import type { IconName } from "./Icon/types";
import type { ColorClass } from "./styles/colors/types";
import type {
AccordionData,
AccordionIcons,
Expand All @@ -23,45 +22,15 @@ import {
} from "./Accordion/utils";

type AccordionRowProps = {
/**
* The content to be displayed within the accordion row.
*/
children: ReactNode;

/**
* The name or title of the accordion row.
*/
name: string;

/**
* Optional icon to be displayed alongside the row name.
*/
rowIcon?: IconName;

/**
* The theme to be applied to the accordion row.
*/
theme: AccordionTheme;

/**
* Icons to be used for toggling the accordion row.
*/
toggleIcons: AccordionIcons;

/**
* Optional additional options for the accordion row.
*/
options?: AccordionOptions;

/**
* The index of the accordion row within the accordion.
*/
index: number;

/**
* Callback function to be called when the accordion row is clicked.
*/
onClick: () => void;
openRowValues: string | string[];
};

export type AccordionProps = {
Expand Down Expand Up @@ -95,8 +64,11 @@ const AccordionRow = ({
theme,
index,
onClick,
openRowValues,
}: AccordionRowProps) => {
const { selectable, sticky } = options || {};
const rowKey = `accordion-item-${index}`;
const isOpen = openRowValues.includes(rowKey);

const {
text,
Expand All @@ -108,11 +80,11 @@ const AccordionRow = ({
toggleIconColor,
} = themeClasses[theme];

const textClass = ((selectable && selectableText) || text) as ColorClass;
const textClass = (selectable && isOpen && selectableText) || text;

return (
<AccordionItem
value={`accordion-item-${index}`}
value={rowKey}
className={clsx({
[`${border}`]: border && !options?.hideBorders,
})}
Expand All @@ -127,9 +99,11 @@ const AccordionRow = ({
"pointer-events-none focus:outline-none": isStaticTheme(theme),
"focus:outline-gui-blue-focus": !isStaticTheme(theme),
"sticky top-0": sticky,
[`${bg} ${hoverBg} ${text}`]: true,
[`${selectableBg} ${selectableText}`]: selectable,
[options?.headerCSS ?? ""]: true,
[`${bg} ${hoverBg} ${text}`]: !(selectable && isOpen),
[`${selectableBg} ${selectableText}`]: selectable && isOpen,
[options?.headerCSS ?? ""]: options?.headerCSS,
[options?.selectedHeaderCSS ?? ""]:
options?.selectedHeaderCSS && isOpen,
})}
>
{rowIcon ? (
Expand All @@ -143,21 +117,20 @@ const AccordionRow = ({
{!selectable && !isStaticTheme(theme) ? (
<span className="flex-1 justify-end flex items-center">
<Icon
additionalCSS="group-data-[state=closed]/accordion-trigger:hidden"
name={toggleIcons.open.name}
color={toggleIconColor}
size={options?.iconSize ?? "16px"}
/>
<Icon
additionalCSS="group-data-[state=open]/accordion-trigger:hidden"
name={toggleIcons.closed.name}
name={isOpen ? toggleIcons.open.name : toggleIcons.closed.name}
color={toggleIconColor}
size={options?.iconSize ?? "16px"}
/>
</span>
) : null}
</AccordionTrigger>
<AccordionContent className="ui-text-p2 overflow-hidden transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down">
<AccordionContent
className={clsx({
"ui-text-p2 overflow-hidden transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down":
true,
[options?.contentCSS ?? ""]: options?.contentCSS,
})}
>
<div className="pb-16">{children}</div>
</AccordionContent>
</AccordionItem>
Expand All @@ -174,6 +147,7 @@ const Accordion = ({
options,
...props
}: AccordionProps) => {
const [openRowValues, setOpenRowValues] = useState<string | string[]>([]);
const innerAccordion = data.map((item, index) => (
<AccordionRow
key={item.name}
Expand All @@ -186,6 +160,7 @@ const Accordion = ({
onClick={() => {
item.onClick?.(index);
}}
openRowValues={openRowValues}
>
{item.content}
</AccordionRow>
Expand All @@ -203,11 +178,20 @@ const Accordion = ({
return (
<div {...props}>
{options?.autoClose ? (
<RadixAccordion type="single" collapsible defaultValue={openIndexes[0]}>
<RadixAccordion
type="single"
collapsible
defaultValue={openIndexes[0]}
onValueChange={(values) => setOpenRowValues(values)}
>
{innerAccordion}
</RadixAccordion>
) : (
<RadixAccordion type="multiple" defaultValue={openIndexes}>
<RadixAccordion
type="multiple"
defaultValue={openIndexes}
onValueChange={(values) => setOpenRowValues(values)}
>
{innerAccordion}
</RadixAccordion>
)}
Expand Down
6 changes: 4 additions & 2 deletions src/core/Accordion/Accordion.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,9 @@ export const WithCustomElementCSS = {
AccordionPresentation({
data: dataWithIcons,
options: {
headerCSS: "bg-pink-400 hover:!bg-pink-600 h-40",
selectedHeaderCSS: "bg-green-400 hover:bg-blue-600",
contentCSS: "bg-yellow-200",
headerCSS: "bg-pink-400 hover:bg-pink-600 h-40",
iconSize: "40px",
rowIconSize: "12px",
},
Expand All @@ -243,7 +245,7 @@ export const WithCustomElementCSS = {
docs: {
description: {
story:
"By modifying `headerCSS`, `iconSize`, and `rowIconSize` in `options`, you can customize the styling of the header, row expansion icons (i.e. the plus and minus), and the icons on the left of the row. What's below is hideous, but you get the gist.",
"By modifying `headerCSS`, `selectedHeaderCSS`, `contentCSS`, `iconSize`, and `rowIconSize` in `options`, you can customize the styling of the header, row expansion icons (i.e. the plus and minus), and the icons on the left of the row. What's below is hideous, but you get the gist.",
},
},
},
Expand Down
20 changes: 17 additions & 3 deletions src/core/Accordion/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ReactNode } from "react";
import { IconName, IconSize } from "../Icon/types";
import { ColorClass, DataStateOpenColorClass } from "../styles/colors/types";
import { ColorClass } from "../styles/colors/types";

/**
* Represents the data structure for an Accordion component.
Expand Down Expand Up @@ -77,12 +77,12 @@ export type AccordionThemeColors = {
/**
* Optional background color class for selectable accordion items.
*/
selectableBg?: DataStateOpenColorClass;
selectableBg?: ColorClass;

/**
* Optional text color class for selectable accordion items.
*/
selectableText?: DataStateOpenColorClass;
selectableText?: ColorClass;

/**
* Optional border color for the accordion.
Expand Down Expand Up @@ -138,11 +138,25 @@ export type AccordionOptions = {

/**
* Size of the row icon.
* @default "32px"
*/
rowIconSize?: IconSize;

/**
* Size of the accordion icon.
* @default "16px"
*/
iconSize?: IconSize;

/**
* Custom CSS classes to apply to the selected accordion header.
* @default ""
*/
selectedHeaderCSS?: string;

/**
* Custom CSS classes to apply to the accordion content.
* @default ""
*/
contentCSS?: string;
};
16 changes: 8 additions & 8 deletions src/core/Accordion/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ export const themeClasses: Record<AccordionTheme, AccordionThemeColors> = {
hoverBg: "hover:bg-neutral-1100",
text: "text-white",
toggleIconColor: "text-orange-600",
selectableBg: "data-[state=open]:bg-neutral-300",
selectableText: "data-[state=open]:text-neutral-1300",
selectableBg: "bg-neutral-300",
selectableText: "text-neutral-1300",
},
light: {
bg: "bg-neutral-200",
hoverBg: "hover:bg-neutral-300",
text: "text-neutral-1300",
toggleIconColor: "text-neutral-1000",
selectableBg: "data-[state=open]:bg-neutral-1200",
selectableText: "data-[state=open]:text-white",
selectableBg: "bg-neutral-1200",
selectableText: "text-white",
},
transparent: {
bg: "bg-transparent",
Expand All @@ -36,16 +36,16 @@ export const themeClasses: Record<AccordionTheme, AccordionThemeColors> = {
hoverBg: "hover:bg-neutral-200",
text: "text-neutral-1300",
toggleIconColor: "text-neutral-200",
selectableBg: "data-[state=open]:bg-neutral-1200",
selectableText: "data-[state=open]:text-white",
selectableBg: "bg-neutral-1200",
selectableText: "text-white",
},
darkStatic: {
bg: "bg-neutral-1200",
hoverBg: "hover:bg-neutral-1200",
text: "text-white",
toggleIconColor: "text-neutral-1200",
selectableBg: "data-[state=open]:bg-neutral-1200",
selectableText: "data-[state=open]:text-neutral-1300",
selectableBg: "bg-neutral-1200",
selectableText: "text-neutral-1300",
},
};

Expand Down
2 changes: 0 additions & 2 deletions src/core/styles/colors/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ export type Theme = "light" | "dark";
export type ColorClass =
`${ColorClassVariants}${ColorClassPrefixes}-${ColorName}`;

export type DataStateOpenColorClass = `data-[state=open]:${ColorClass}`;

export const neutralColors = [
"neutral-000",
"neutral-100",
Expand Down

0 comments on commit cbf00c0

Please sign in to comment.