Skip to content

Commit

Permalink
feat(button): ✨ add react aria buttons & interactions (#9)
Browse files Browse the repository at this point in the history
* feat(button): ✨  add react aria buttons

* feat(components): ✨  add focus, button & link

* docs(button): 📝  better storybook docs for button

* feat(calendar): ✨  start calendar experiment

* refactor: ♻️  remove datepicker experiments

* refactor(hooks): 👌  update code after code review

* refactor(type): ♻️  change type for button state aria
  • Loading branch information
navin-moorthy authored Sep 1, 2020
1 parent 9feb564 commit b61e990
Show file tree
Hide file tree
Showing 26 changed files with 1,466 additions and 363 deletions.
37 changes: 22 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,31 +24,38 @@
"storybook": "start-storybook -p 6006"
},
"dependencies": {
"@chakra-ui/hooks": "1.0.0-rc.2",
"@chakra-ui/utils": "1.0.0-rc.2",
"@chakra-ui/hooks": "1.0.0-rc.3",
"@chakra-ui/utils": "1.0.0-rc.3",
"@react-aria/button": "^3.2.1",
"@react-aria/interactions": "^3.2.0",
"@react-aria/link": "^3.1.0",
"@react-aria/utils": "^3.2.0",
"@react-stately/toggle": "^3.2.0",
"@types/lodash.debounce": "^4.0.6",
"dayzed": "^3.2.1",
"emotion": "^10.0.27",
"lodash.debounce": "^4.0.8",
"reakit": "^1.2.3",
"reakit-system": "^0.14.3",
"reakit-utils": "^0.14.3"
},
"devDependencies": {
"@babel/core": "7.11.4",
"@babel/core": "7.11.5",
"@commitlint/cli": "9.1.2",
"@commitlint/config-conventional": "9.1.2",
"@storybook/addon-a11y": "6.0.17",
"@storybook/addon-actions": "6.0.17",
"@storybook/addon-essentials": "6.0.17",
"@storybook/addon-links": "6.0.17",
"@storybook/addon-storysource": "6.0.17",
"@storybook/react": "6.0.17",
"@types/react": "16.9.47",
"@storybook/addon-a11y": "6.0.21",
"@storybook/addon-actions": "6.0.21",
"@storybook/addon-essentials": "6.0.21",
"@storybook/addon-links": "6.0.21",
"@storybook/addon-storysource": "6.0.21",
"@storybook/react": "6.0.21",
"@types/react": "16.9.49",
"@types/react-dom": "16.9.8",
"@typescript-eslint/eslint-plugin": "3.10.0",
"@typescript-eslint/parser": "3.10.0",
"@typescript-eslint/eslint-plugin": "4.0.1",
"@typescript-eslint/parser": "4.0.1",
"babel-eslint": "10.1.0",
"babel-loader": "8.1.0",
"eslint": "7.7.0",
"eslint": "7.8.0",
"eslint-config-prettier": "6.11.0",
"eslint-config-react-app": "5.2.1",
"eslint-plugin-flowtype": "5.2.0",
Expand All @@ -59,8 +66,8 @@
"eslint-plugin-react-hooks": "4.1.0",
"gacp": "2.10.0",
"husky": "4.2.5",
"lint-staged": "10.2.11",
"prettier": "2.1.0",
"lint-staged": "10.2.13",
"prettier": "2.1.1",
"react": "16.13.1",
"react-dom": "16.13.1",
"react-is": "16.13.1",
Expand Down
31 changes: 31 additions & 0 deletions src/Link/AriaLink.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as React from "react";
import { useForkRef } from "reakit-utils";
import { useLink, AriaLinkOptions } from "@react-aria/link";
import { BoxHTMLProps, useBox } from "reakit";
import { mergeProps } from "@react-aria/utils";
import { INTERACTION_KEYS } from "../interactions/__keys";
import { createComponent, createHook } from "reakit-system";

export const useAriaLink = createHook<AriaLinkOptions, BoxHTMLProps>({
name: "AriaLink",
keys: INTERACTION_KEYS,
compose: [useBox],

useProps(options, { ref: htmlRef, ...htmlProps }) {
const props = { ...options, ...htmlProps };
const ref = React.useRef<HTMLElement>(null);

const { linkProps } = useLink(props, ref);

return mergeProps(htmlProps, {
...linkProps,
ref: useForkRef(ref, htmlRef),
});
},
});

export const AriaLink = createComponent({
as: "a",
memo: true,
useHook: useAriaLink,
});
1 change: 1 addition & 0 deletions src/Link/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./AriaLink";
58 changes: 58 additions & 0 deletions src/Link/stories/Link.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React from "react";
import { Meta } from "@storybook/react";
import { AriaLink } from "../index";

export default {
title: "Component/Link",
} as Meta;

export const ReactAriaLink = () => {
return (
<AriaLink
href="https://adobe.com"
target="_blank"
style={{
color: "blue",
textDecoration: "underline",
cursor: "pointer",
}}
>
Adobe
</AriaLink>
);
};

export const ReactAriaCustomLink = () => {
return (
<AriaLink
as="span"
elementType="span"
style={{
color: "blue",
textDecoration: "underline",
cursor: "pointer",
}}
onPress={() => alert("Pressed link")}
>
Custom
</AriaLink>
);
};

export const ReactAriaDisabledLink = () => {
return (
<AriaLink
href="https://adobe.com"
target="_blank"
style={{
color: "blue",
textDecoration: "underline",
cursor: "pointer",
}}
onPress={() => alert("Pressed link")}
isDisabled
>
Adobe
</AriaLink>
);
};
32 changes: 32 additions & 0 deletions src/button/AriaButton.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import * as React from "react";
import { useForkRef } from "reakit-utils";
import { BoxHTMLProps, useBox } from "reakit";
import { useButton } from "@react-aria/button";
import { mergeProps } from "@react-aria/utils";
import { AriaButtonProps } from "@react-types/button";
import { INTERACTION_KEYS } from "../interactions/__keys";
import { createComponent, createHook } from "reakit-system";

export const useAriaButton = createHook<AriaButtonProps, BoxHTMLProps>({
name: "AriaButton",
keys: INTERACTION_KEYS,
compose: [useBox],

useProps(options, { ref: htmlRef, ...htmlProps }) {
const props = { ...options, ...htmlProps } as AriaButtonProps;
const ref = React.useRef<HTMLElement>(null);

const { buttonProps } = useButton(props, ref);

return mergeProps(htmlProps, {
...buttonProps,
ref: useForkRef(ref, htmlRef),
});
},
});

export const AriaButton = createComponent({
as: "button",
memo: true,
useHook: useAriaButton,
});
40 changes: 40 additions & 0 deletions src/button/AriaToggleButton.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import * as React from "react";
import { useForkRef } from "reakit-utils";
import { BoxHTMLProps, useBox } from "reakit";
import { mergeProps } from "@react-aria/utils";
import { ToggleState } from "@react-stately/toggle";
import { useToggleButton } from "@react-aria/button";
import { INTERACTION_KEYS } from "../interactions/__keys";
import { createComponent, createHook } from "reakit-system";
import { AriaToggleButtonProps } from "@react-types/button";

type useAriaToggleButtonOptions = AriaToggleButtonProps & ToggleState;

export const useAriaToggleButton = createHook<
useAriaToggleButtonOptions,
BoxHTMLProps
>({
name: "AriaToggleButton",
keys: [...INTERACTION_KEYS, "isSelected", "setSelected", "toggle"],
compose: [useBox],

useProps(options, { ref: htmlRef, ...htmlProps }) {
const { isSelected, setSelected, toggle, ...restOptions } = options;
const props = { ...restOptions, ...htmlProps } as AriaToggleButtonProps;
const state = { isSelected, setSelected, toggle };
const ref = React.useRef<HTMLElement>(null);

const { buttonProps } = useToggleButton(props, state, ref);

return mergeProps(htmlProps, {
...buttonProps,
ref: useForkRef(ref, htmlRef),
});
},
});

export const AriaToggleButton = createComponent({
as: "button",
memo: true,
useHook: useAriaToggleButton,
});
3 changes: 3 additions & 0 deletions src/button/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { Button, useButton } from "reakit/Button";
export * from "./AriaButton";
export * from "./AriaToggleButton";
40 changes: 40 additions & 0 deletions src/button/stories/AriaButton.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from "react";
import { Meta, Story } from "@storybook/react";
import { ReactAriaButton, ReactAriaButtonProps } from "./Buttons";

export default {
title: "Component/Buttons/ReactAriaButton",
component: ReactAriaButton,
} as Meta;

const Template: Story<ReactAriaButtonProps> = args => (
<ReactAriaButton {...args} />
);

export const Default = Template.bind({});
Default.args = {};

export const LinkButton = Template.bind({});
LinkButton.args = {
as: "a",
elementType: "a",
href: "https://reakit.io/docs/button/",
target: "_blank",
rel: "noreferrer noopener",
};

export const SpanButton = Template.bind({});
SpanButton.args = {
as: "span",
elementType: "span",
};

export const AutoFocus = Template.bind({});
AutoFocus.args = {
autoFocus: true,
};

export const Disabled = Template.bind({});
Disabled.args = {
isDisabled: true,
};
40 changes: 40 additions & 0 deletions src/button/stories/AriaToggleButton.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from "react";
import { Meta, Story } from "@storybook/react";
import { ReactAriaToggleButton, ReactAriaButtonProps } from "./Buttons";

export default {
title: "Component/Buttons/ReactAriaToggleButton",
component: ReactAriaToggleButton,
} as Meta;

const Template: Story<ReactAriaButtonProps> = args => (
<ReactAriaToggleButton {...args} />
);

export const Default = Template.bind({});
Default.args = {};

export const LinkButton = Template.bind({});
LinkButton.args = {
as: "a",
elementType: "a",
href: "https://reakit.io/docs/button/",
target: "_blank",
rel: "noreferrer noopener",
};

export const SpanButton = Template.bind({});
SpanButton.args = {
as: "span",
elementType: "span",
};

export const AutoFocus = Template.bind({});
AutoFocus.args = {
autoFocus: true,
};

export const Disabled = Template.bind({});
Disabled.args = {
isDisabled: true,
};
Loading

0 comments on commit b61e990

Please sign in to comment.