Skip to content

Commit

Permalink
Use default theme
Browse files Browse the repository at this point in the history
  • Loading branch information
exoup committed Mar 23, 2024
1 parent 22c1e23 commit b4129f2
Show file tree
Hide file tree
Showing 20 changed files with 293 additions and 201 deletions.
39 changes: 38 additions & 1 deletion src/components/Accordion/Accordion.stories.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,41 @@ export const NonAccordionComponent = ({ ...args }) => (
</Accordion>
);

NonAccordionComponent.storyName = "OpenableAccordion";
NonAccordionComponent.storyName = "OpenableAccordion";

export const CustomnAccordionComponent = ({ ...args }) => (
<Accordion {...args} className={`w-96 divide-none space-y-4`}>
<Drawer title="Drawer 1"
buttonProps={
{
className: "rounded-t-md border bg-gray-1 border-gray-1 aria-expanded:border-gray-4 aria-expanded:border-b-0 aria-expanded:bg-transparent",
}
}
className={`rounded-b-md data-[open=true]:border data-[open=true]:border-t-0 border-gray-4 bg-transparent`}>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Nisi nostrum ab odio aliquid fuga? Ea cumque, iste nulla praesentium quo dolorum esse rem perspiciatis iure. Architecto placeat minima mollitia aspernatur?
</Drawer>
<Drawer title="Drawer 2"
buttonProps={
{
className: "rounded-md border bg-gray-1 border-gray-1 aria-expanded:rounded-b-none aria-expanded:border-gray-4 aria-expanded:border-b-0 aria-expanded:bg-transparent",
}
}
className={`rounded-b-md data-[open=true]:border data-[open=true]:border-t-0 border-gray-4 bg-transparent`}>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sed atque alias, culpa illum officia quia fuga dolore rerum accusantium animi delectus ipsam dignissimos quas, ut officiis asperiores maiores debitis! Harum!
</Drawer>
<Drawer title="Drawer 3"
buttonProps={
{
className: "rounded-md border bg-gray-1 border-gray-1 aria-expanded:rounded-b-none aria-expanded:border-gray-4 aria-expanded:border-b-0 aria-expanded:bg-transparent",
}
}
className={`rounded-b-md data-[open=true]:border data-[open=true]:border-t-0 border-gray-4 bg-transparent`}>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Et numquam enim commodi nisi incidunt doloremque totam dolore nobis voluptatem omnis quia odio ex, animi quibusdam facere, nostrum in dignissimos maiores.
</Drawer>
</Accordion>
);

CustomnAccordionComponent.storyName = "CustomAccordion";
CustomnAccordionComponent.args = {
flush: true
}
10 changes: 5 additions & 5 deletions src/components/Card/Card.stories.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export const CardWithHero = ({ ...args }) => {

return (
<Card {...args} className="w-80">
<Hero className="h-64 bg-slate-600 heroPatternClouds" />
<Hero className="h-64 bg-boulder-10 heroPatternClouds" />
<Content variant={args.color}>
<Title>This is a card component.</Title>
<p>It uses a Hero with a background-image.</p>
Expand Down Expand Up @@ -87,7 +87,7 @@ export const CardWithSection = ({ ...args }) => (

export const CardWithAccordion = ({ ...args }) => (
<Card {...args}>
<Hero className="h-64 bg-primary dark:bg-tertiary heroPatternCogs" />
<Hero className="h-64 bg-primary dark:bg-roman-3 heroPatternCogs" />
<Content variant={args.color}>
<Title className="text-xl">This is an accordion card.</Title>
<Accordion
Expand All @@ -108,15 +108,15 @@ export const CardWithAccordion = ({ ...args }) => (
);

export const CardWithLogin = ({ ...args }) => (
<Card {...args} className="pb-2 border-l-tertiary-500 border-l-8 rounded-l-md">
<Card {...args} className="pb-2 border-l-roman-5 border-l-8 rounded-l-md">
<Content variant={args.color} className="flex flex-col place-content-center">
<form className="flex flex-col gap-6" onSubmit={(e) => e.preventDefault()} action="#">
<Title className="text-2xl">Login</Title>
<Input color={args.color} label={"Username"} required />
<Input color={args.color} label={"Password"} type={"password"} required />
<div className="flex justify-between items-center gap-2">
<label className="flex items-center gap-2"><input type="checkbox" className="checked:text-tertiary-500" />Remember me</label>
<a href="#" className="hover:underline text-tertiary-500">Forgot Password?</a>
<label className="flex items-center gap-2"><input type="checkbox" className="checked:text-roman-6" />Remember me</label>
<a href="#" className="hover:underline text-roman-6">Forgot Password?</a>
</div>
<Button {...args} type="submit" className="w-3/4 self-center">Login</Button>
</form>
Expand Down
27 changes: 18 additions & 9 deletions src/components/Layout/Layout.stories.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@ import "../../resources/styles.css";
export const LoginPage = ({ ...args }) => (
<div className="size-full">
<Card {...args} className={"flex flex-row size-full"}>
<Hero className="bg-tertiary-300/50 heroPatternTopography w-3/5" />
{/* <Hero className="fill-roman-3 base64 w-3/5" /> */}
<Hero className="heroPatternTopography bg-roman-3 w-3/5" />
<Content variant={args.color} className="flex flex-col w-2/5 p-20 place-content-center">
<form className="flex flex-col gap-6" onSubmit={(e) => e.preventDefault()} action="#">
<Title className="text-2xl">Login</Title>
<Input color={args.color} label={"Username"} required />
<Input color={args.color} label={"Password"} type={"password"} required />
<Input color={args.color} radius={args.radius} label={"Username"} required />
<Input color={args.color} radius={args.radius} label={"Password"} type={"password"} required />
<div className="flex justify-between items-center gap-2">
<label className="flex items-center gap-2"><input type="checkbox" className="checked:text-tertiary-500" />Remember me</label>
<a href="#" className="hover:underline text-tertiary-500">Forgot Password?</a>
<label className="flex items-center gap-2"><input type="checkbox" className="checked:text-roman-3" />Remember me</label>
<a href="#" className="hover:underline text-roman-5">Forgot Password?</a>
</div>
<Button {...args} type="submit">Login</Button>
<a href="#" className="hover:underline text-tertiary-500 self-center">Sign up Here</a>
Expand All @@ -24,7 +25,15 @@ export const LoginPage = ({ ...args }) => (
</div>
)

LoginPage.args = {
color: "tertiary",
radius: "round",
};
LoginPage.argTypes = {
color: {
defaultValue: 'default',
options: ['default'],
control: { type: 'inline-radio' }
},
radius: {
defaultValue: 'round',
options: ['round', 'sharp'],
control: { type: 'inline-radio' }
},
}
138 changes: 98 additions & 40 deletions src/components/Menu/Menu.jsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,53 @@
import { useRef, useCallback, useEffect } from "react";
import { useRef, useCallback, useEffect, Children, cloneElement, isValidElement } from "react";
import { useMenu, MenuProvider, useOnClickOutside } from "./MenuContext.jsx";
import { twMerge, twJoin } from "tailwind-merge";
import { useTheme } from "../../context/ThemeContext.jsx";
import mapObjectToString from "../../util/mapObjectToString";
import lookupOptions from "../../util/lookupOptions";

const generateId = () => Math.random().toString(36).substring(2, 9);

export default function Menu({ children, className }) {
return (
<MenuProvider>
<span className={twMerge(className)}>{children}</span>
<div className={twMerge(className)}>{children}</div>
</MenuProvider>
);
}

export const MenuControl = ({ children }) => {
const { toggleMenu, setButtonRef, buttonRef } = useMenu();
const { toggleMenu, isOpen, setButtonRef, buttonRef, buttonControllerId, setButtonControllerId, menuId, setMenuId } = useMenu();
const buttonGroupRef = useRef(null);

const handleClick = useCallback(() => {
setButtonRef(buttonGroupRef);
toggleMenu();
}, [setButtonRef, toggleMenu]);

useEffect(() => {
setMenuId(`menu-${generateId()}`);
setButtonControllerId(`menu-button-${generateId()}`);
}, [setButtonControllerId, setMenuId]);

return (
<div ref={buttonRef} className='size-max' onClick={handleClick}>
{children}
<div ref={buttonRef}
className='size-max'>
{
Children.map(children, (child) => {
if (isValidElement(child)) {
return cloneElement(child, {
...child.props,
id: buttonControllerId,
role: "button",
"aria-controls": menuId,
"aria-expanded": String(isOpen),
"aria-haspopup": "true",
onClick: handleClick
});
}
return child;
})
}
</div>
);
};
Expand All @@ -40,35 +63,37 @@ export const MenuContent = ({
...args
}) => {
const menuRef = useRef(null);
const { isOpen, toggleMenu, buttonRef } = useMenu();

const handleMenuPosition = useCallback(
(alignment) => {
if (!isOpen || !buttonRef.current || !menuRef.current) return;
const { left, top, width, height } =
buttonRef.current.getBoundingClientRect();
const menuWidth = menuRef.current.offsetWidth;
const menuHeight = menuRef.current.offsetHeight;
const windowWidth = window.innerWidth;
const windowHeight = window.innerHeight;
let leftPos;

switch (alignment) {
case "left":
leftPos = left;
break;
case "right":
leftPos = left + width - menuWidth;
break;
default:
leftPos = left + width / 2 - menuWidth / 2;
}
const topPos = top + height;

menuRef.current.style.left = Math.max(10, Math.min(leftPos, windowWidth - menuWidth)) + "px";
menuRef.current.style.top = Math.max(0, Math.min(topPos, windowHeight - menuHeight)) + "px";
},
[isOpen, buttonRef]
const { isOpen, toggleMenu, buttonRef, buttonControllerId, menuId } = useMenu();

const handleMenuPosition = useCallback(() => {
if (!isOpen || !buttonRef.current || !menuRef.current) return;
const { left, top, width, height } =
buttonRef.current.getBoundingClientRect();
const menuWidth = menuRef.current.offsetWidth;
const menuHeight = menuRef.current.offsetHeight;
const windowWidth = window.innerWidth;
const windowHeight = window.innerHeight;
let leftPos;

switch (alignment) {
case "left":
leftPos = left;
break;
case "right":
leftPos = left + width - menuWidth;
break;
default:
leftPos = left + width / 2 - menuWidth / 2;
}
const topPos = top + height;

menuRef.current.style.left = Math.max(10, Math.min(leftPos, windowWidth - menuWidth)) + "px";
menuRef.current.style.top = Math.max(0, Math.min(topPos, windowHeight - menuHeight)) + "px";
menuRef.current.firstChild.focus({
focusVisible: true
});
},
[isOpen, buttonRef, alignment]
);

const handleOutsideClick = () => {
Expand All @@ -77,8 +102,24 @@ export const MenuContent = ({
}
};

const handleEscape = useCallback((e) => {
if (isOpen) {
if (e.key === "Escape") {
buttonRef.current?.firstChild?.focus();
toggleMenu();
}
}
}, [isOpen, toggleMenu, buttonRef]);

useEffect(() => {
const handleDocumentKeyDown = (e) => handleEscape(e);
document.addEventListener('keydown', handleDocumentKeyDown);

return () => document.removeEventListener('keydown', handleDocumentKeyDown);
}, [handleEscape]);

useEffect(() => {
handleMenuPosition(alignment);
handleMenuPosition();
}, [isOpen, alignment, handleMenuPosition]);

useOnClickOutside(menuRef, handleOutsideClick, buttonRef);
Expand Down Expand Up @@ -108,11 +149,19 @@ export const MenuContent = ({
className
);

return isOpen ? (
<div {...args} ref={menuRef} hidden={!isOpen} className={classes}>
return (
<div {...args}
ref={menuRef}
id={menuId}
tabIndex={-1}
role="menu"
aria-labelledby={buttonControllerId}
aria-orientation="vertical"
hidden={!isOpen}
className={classes}>
{children}
</div>
) : null;
);
};

export const MenuItem = ({ disabled = false, className, children, ...args }) => {
Expand All @@ -125,7 +174,12 @@ export const MenuItem = ({ disabled = false, className, children, ...args }) =>
const classes = twMerge(...initialClasses, className);

return (
<button {...args} disabled={disabled} className={classes}>
<button {...args}
type={args.type || 'button'}
tabIndex={0}
disabled={disabled}
role="menuitem"
className={classes}>
{children}
</button>
);
Expand All @@ -140,7 +194,11 @@ export const MenuDivider = ({ className, ...args }) => {

const classes = twMerge(...initialClasses, className);

return <div {...args} className={classes}></div>;
return <div {...args}
role="separator"
aria-orientation="horizontal"
className={classes}>
</div>;
};

// /* Always center carot to middle of button. */
Expand Down
4 changes: 3 additions & 1 deletion src/components/Menu/MenuContext.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ export const MenuProvider = ({ children }) => {

const [isOpen, setIsOpen] = useState(false);
const [buttonRef, setButtonRef] = useState(null);
const [menuId, setMenuId] = useState(null);
const [buttonControllerId, setButtonControllerId] = useState(null);

const toggleMenu = useCallback(() => {
setIsOpen((prevIsOpen) => !prevIsOpen);
}, []);

return (
<MenuContext.Provider value={{ isOpen, toggleMenu, buttonRef, setButtonRef }}>
<MenuContext.Provider value={{ isOpen, toggleMenu, buttonRef, setButtonRef, menuId, setMenuId, buttonControllerId, setButtonControllerId }}>
{children}
</MenuContext.Provider>
);
Expand Down
Loading

0 comments on commit b4129f2

Please sign in to comment.