Skip to content

Commit

Permalink
Wolfgangbeer/ch3876/ersetzen der chakra menu component durch (#22)
Browse files Browse the repository at this point in the history
* chore: update package-lock.json

* feat(3876): create menu components and basic story

* feat(3876): make menu accessible and fix isDisabled on Link

* feat(3876): write menu story in mdx

* feat(3876): update description

* feat(3876): add example with disabled MenuButton

* feat(3876): update story height

* chore: adds tailwind config change

* feat(3876): change naming to be more explicit

Co-authored-by: David Wippel <[email protected]>
  • Loading branch information
WolfgangBeer and David Wippel authored Sep 7, 2020
1 parent 7c6f812 commit 8809c95
Show file tree
Hide file tree
Showing 18 changed files with 2,038 additions and 1,479 deletions.
2,722 changes: 1,332 additions & 1,390 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/components/button.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import ProviderDecorator from '../provider-decorator';

# Buttons

Note: We are handling disabled buttons with the `aria-disabled` html attribute rather then the `disabled` html attribute. This is because if you use `disabled` on a html element, it will completely dissapear for a user who uses a screen reader. With the attribute `aria-disabled="true"` it will still be focusable, but it will be announced as disabled. We use this pattern also for all sorts of Link an MenuItem Components.

## Example

Expand Down
4 changes: 3 additions & 1 deletion src/components/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const BaseButton: FC<VariantButtonProps> = forwardRef(
rightIcon,
onClick,
children,
...others
}: VariantButtonProps,
ref: Ref<HTMLButtonElement>
) => (
Expand All @@ -38,7 +39,8 @@ const BaseButton: FC<VariantButtonProps> = forwardRef(
onClick={isDisabled || isLoading ? undefined : onClick}
aria-label={
isLoading && typeof children === 'string' ? children : undefined
}>
}
{...others}>
{isLoading ? (
<LoadingIndicator size={size} />
) : (
Expand Down
84 changes: 0 additions & 84 deletions src/components/icon.jsx

This file was deleted.

89 changes: 89 additions & 0 deletions src/components/icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React, {FC} from 'react';

// icons taken from here: https://heroicons.com/
// use medium size

const icons = {
home: (
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
/>
),
search: (
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
/>
),
add: (
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M9 13h6m-3-3v6m5 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
/>
),
download: (
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"
/>
),
database: (
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4"
/>
),
'dots-horizontal': (
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M5 12h.01M12 12h.01M19 12h.01M6 12a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0z"
/>
),
};

const defaultIcon = (
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
);

export type IconName = keyof typeof icons;

type Props = {
icon: IconName;
className?: string;
};

const Icon: FC<Props> = ({icon, className}: Props) => {
return (
<svg
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
className={className}>
{icons[icon] || defaultIcon}
</svg>
);
};

Icon.defaultProps = {
className: 'w-6 h-6',
};

export default Icon;
16 changes: 16 additions & 0 deletions src/components/link.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@ export const DefaultStory = () => (

DefaultStory.storyName = 'default';

export const Disabled = () => (
<Stack isInline shouldWrapChildren>
<PrimaryLink isExternal to="https://www.trigo.dev" isDisabled>
Primary
</PrimaryLink>
<SecondaryLink isExternal to="https://www.trigo.dev" isDisabled>
Secondary
</SecondaryLink>
<TertiaryLink isExternal to="https://www.trigo.dev" isDisabled>
Tertiary
</TertiaryLink>
</Stack>
);

Disabled.storyName = 'disabled';

export default {
title: 'Components/Link',
component: PrimaryLink,
Expand Down
9 changes: 5 additions & 4 deletions src/components/link.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
/* eslint-disable jsx-a11y/anchor-is-valid */
import React, {forwardRef, Ref, FC} from 'react';
import {Icon} from '@chakra-ui/core';
import {Link as RouterLink} from '@reach/router';
import getButtonStyle from './get-button-style';
import {VariantLinkProps} from './types';

// this Component is currently not exported, it is only used within this repo
// to serve as a base-component for primary-button / secondary-button and tertiary-button

const BaseLink: FC<VariantLinkProps> = forwardRef(
(
{
Expand All @@ -28,7 +26,8 @@ const BaseLink: FC<VariantLinkProps> = forwardRef(
rel="noopener noreferrer"
ref={ref}
aria-disabled={isDisabled}
href={to}
tabIndex={isDisabled ? 0 : undefined}
href={isDisabled ? undefined : to}
className={getButtonStyle({
className,
size,
Expand All @@ -49,6 +48,8 @@ const BaseLink: FC<VariantLinkProps> = forwardRef(
<RouterLink
to={to}
ref={ref}
aria-disabled={isDisabled}
tabIndex={isDisabled ? 0 : undefined}
className={getButtonStyle({
className,
size,
Expand Down
8 changes: 8 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ export {default as PrimaryLink} from './components/primary-link';
export {default as SecondaryLink} from './components/secondary-link';
export {default as TertiaryLink} from './components/tertiary-link';

// Menu
export {default as Menu} from './menu/menu';
export {default as MenuButton} from './menu/menu-button';
export {default as MenuDivider} from './menu/menu-divider';
export {default as MenuItem} from './menu/menu-item';
export {default as MenuItemLink} from './menu/menu-item-link';
export {default as MenuList} from './menu/menu-list';

export {default as Badge} from './components/badge';

// Form fields
Expand Down
31 changes: 31 additions & 0 deletions src/menu/menu-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React, {FC, useContext, useCallback, useRef} from 'react';
import useClickOutside from '../use-click-outside';
import Button from '../components/button';
import {ButtonProps} from '../components/types';
import MenuContext from './menu-context';

const MenuButton: FC<ButtonProps> = ({onClick, ...others}: ButtonProps) => {
const ref = useRef<HTMLButtonElement>(null);
const {isOpen, closeMenu, toggleMenu} = useContext(MenuContext);
useClickOutside(ref, closeMenu);

const handleOnClick = useCallback(
(event: React.MouseEvent<HTMLButtonElement>) => {
if (onClick) onClick(event);
toggleMenu();
},
[onClick, closeMenu]
);

return (
<Button
ref={ref}
variant="tertiary"
{...others}
onClick={handleOnClick}
aria-expanded={isOpen ? 'true' : 'false'}
/>
);
};

export default MenuButton;
18 changes: 18 additions & 0 deletions src/menu/menu-context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* eslint-disable no-console */
import {createContext} from 'react';

const MenuContext = createContext({
isOpen: false,
toggleMenu: () => {
console.error(
'MenuContext "toggleMenu" method not initialized correctly'
);
},
closeMenu: () => {
console.error(
'MenuContext "closeMenu" method not initialized correctly'
);
},
});

export default MenuContext;
5 changes: 5 additions & 0 deletions src/menu/menu-divider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import React, {FC} from 'react';

const MenuDivider: FC = () => <div className="border-t border-gray-100" />;

export default MenuDivider;
Loading

0 comments on commit 8809c95

Please sign in to comment.