Skip to content

Commit

Permalink
feat(Accordion): add alwaysOpen prop
Browse files Browse the repository at this point in the history
  • Loading branch information
Brendan-csel committed Jan 1, 2022
1 parent e232945 commit b687ff5
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 14 deletions.
18 changes: 13 additions & 5 deletions packages/bootstrap/src/Accordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@

import classNames from "./classnames";
import { JSX, mergeProps, splitProps } from "solid-js";
import { createControlledProp, SelectCallback } from "solid-bootstrap-core";
import { createControlledProp } from "solid-bootstrap-core";
import { useBootstrapPrefix } from "./ThemeProvider";
import AccordionBody from "./AccordionBody";
import AccordionButton from "./AccordionButton";
import AccordionCollapse from "./AccordionCollapse";
import AccordionContext from "./AccordionContext";
import AccordionContext, {
AccordionSelectCallback,
AccordionEventKey,
} from './AccordionContext';
import AccordionHeader from "./AccordionHeader";
import AccordionItem from "./AccordionItem";
import { BsPrefixProps, BsPrefixRefForwardingComponent } from "./helpers";
Expand All @@ -16,10 +19,11 @@ import { Dynamic } from "solid-js/web";
export interface AccordionProps
extends Omit<JSX.HTMLAttributes<HTMLElement>, "onSelect">,
BsPrefixProps {
activeKey?: string;
defaultActiveKey?: string;
onSelect?: SelectCallback;
activeKey?: AccordionEventKey;
defaultActiveKey?: AccordionEventKey;
onSelect?: AccordionSelectCallback;
flush?: boolean;
alwaysOpen?: boolean;
}

const defaultProps = {
Expand All @@ -32,6 +36,7 @@ const Accordion: BsPrefixRefForwardingComponent<"div", AccordionProps> = (
const [local, props] = splitProps(mergeProps(defaultProps, p), [
"as",
"activeKey",
"alwaysOpen",
"bsPrefix",
"className",
"defaultActiveKey",
Expand All @@ -50,6 +55,9 @@ const Accordion: BsPrefixRefForwardingComponent<"div", AccordionProps> = (
get activeEventKey() {
return activeKey();
},
get alwaysOpen() {
return local.alwaysOpen;
},
get onSelect() {
return onSelect;
},
Expand Down
23 changes: 19 additions & 4 deletions packages/bootstrap/src/AccordionButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import classNames from "./classnames";
import { JSX, mergeProps, splitProps, useContext } from "solid-js";
import { Dynamic } from "solid-js/web";
import { callEventHandler } from "solid-bootstrap-core";
import AccordionContext from "./AccordionContext";
import AccordionContext, {
isAccordionItemSelected,
AccordionEventKey,
} from './AccordionContext';
import AccordionItemContext from "./AccordionItemContext";
import { BsPrefixProps, BsPrefixRefForwardingComponent } from "./helpers";
import { useBootstrapPrefix } from "./ThemeProvider";
Expand All @@ -26,10 +29,22 @@ export function useAccordionButton(
Compare the event key in context with the given event key.
If they are the same, then collapse the component.
*/
const eventKeyPassed =
let eventKeyPassed: AccordionEventKey =
eventKey === context.activeEventKey ? null : eventKey;
if (context.alwaysOpen) {
if (Array.isArray(context.activeEventKey)) {
if (context.activeEventKey.includes(eventKey)) {
eventKeyPassed = context.activeEventKey.filter((k) => k !== eventKey);
} else {
eventKeyPassed = [...context.activeEventKey, eventKey];
}
} else {
// activeEventKey is undefined.
eventKeyPassed = [eventKey];
}
}

if (context.onSelect) context.onSelect(eventKeyPassed, e);
context.onSelect?.(eventKeyPassed, e);
callEventHandler(onClick, e);
};
}
Expand Down Expand Up @@ -66,7 +81,7 @@ const AccordionButton: BsPrefixRefForwardingComponent<
className={classNames(
local.className,
bsPrefix,
itemContext.eventKey !== accordionContext.activeEventKey && "collapsed"
!isAccordionItemSelected(accordionContext.activeEventKey, itemContext.eventKey) && 'collapsed',
)}
>
{props.children}
Expand Down
4 changes: 2 additions & 2 deletions packages/bootstrap/src/AccordionCollapse.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { mergeProps, splitProps, useContext } from "solid-js";
import { Dynamic } from "solid-js/web";
import { useBootstrapPrefix } from "./ThemeProvider";
import Collapse, { CollapseProps } from "./Collapse";
import AccordionContext from "./AccordionContext";
import AccordionContext, { isAccordionItemSelected } from './AccordionContext';
import { BsPrefixRefForwardingComponent, BsPrefixProps } from "./helpers";

export interface AccordionCollapseProps extends BsPrefixProps, CollapseProps {
Expand All @@ -31,7 +31,7 @@ const AccordionCollapse: BsPrefixRefForwardingComponent<
const bsPrefix = useBootstrapPrefix(local.bsPrefix, "accordion-collapse");

return (
<Collapse in={context.activeEventKey === local.eventKey} {...props}>
<Collapse in={isAccordionItemSelected(context.activeEventKey, local.eventKey)} {...props}>
<Dynamic
component={local.as}
className={classNames(local.className, bsPrefix)}
Expand Down
22 changes: 19 additions & 3 deletions packages/bootstrap/src/AccordionContext.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
// ported from https://github.com/react-bootstrap/react-bootstrap/blob/f11723114d532cfce840417834a73733a8436414/src/AccordionContext.ts

import { createContext } from "solid-js";
import { SelectCallback } from "solid-bootstrap-core";

export type AccordionEventKey = string | string[] | null | undefined;

export declare type AccordionSelectCallback = (
eventKey: AccordionEventKey,
e: Event,
) => void;

export interface AccordionContextValue {
activeEventKey?: string;
onSelect?: SelectCallback;
activeEventKey?: AccordionEventKey;
onSelect?: AccordionSelectCallback;
alwaysOpen?: boolean;
}

export function isAccordionItemSelected(
activeEventKey: AccordionEventKey,
eventKey: string,
): boolean {
return Array.isArray(activeEventKey)
? activeEventKey.includes(eventKey)
: activeEventKey === eventKey;
}

const context = createContext<AccordionContextValue>({});
Expand Down

0 comments on commit b687ff5

Please sign in to comment.