From d86c7266bd5654685049a4053fd782b7091d0e51 Mon Sep 17 00:00:00 2001 From: Orr Gottlieb <60314759+orrgottlieb@users.noreply.github.com> Date: Mon, 26 Apr 2021 14:53:58 +0300 Subject: [PATCH] Orr/focus style (#112) * feat: focus * focus visible changes * update jest tests * fix: small adjustments * fix: update stuff --- package.json | 2 +- .../__snapshots__/attentionBox.jest.js.snap | 2 + .../BreadcrumbContent/BreadcrumbContent.scss | 2 +- .../BreadcrumbItem/BreadcrumbItem.scss | 1 - src/components/Button/Button.jsx | 16 +++ src/components/Button/Button.scss | 3 + src/components/ButtonGroup/ButtonGroup.scss | 7 - src/components/Checkbox/Checkbox.scss | 10 ++ .../__snapshots__/checkbox.jest.js.snap | 4 + .../__snapshots__/dropdown.jest.js.snap | 8 ++ .../EditableHeading/EditableHeading.scss | 7 +- .../EditableInput/EditableInput.jsx | 2 +- .../EditableInput/EditableInput.scss | 1 + .../__snapshots__/editableInput.jest.js.snap | 2 +- .../ExpandCollapse/ExpandCollapse.jsx | 21 ++- .../ExpandCollapse/ExpandCollapse.scss | 107 +++++++------- .../__stories__/expandCollapse.stories.js | 23 +-- .../__snapshots__/expandCollapse.jest.js.snap | 10 +- src/components/Icon/Icon.jsx | 1 + src/components/Link/Link.scss | 5 +- .../__tests__/__snapshots__/menu.jest.js.snap | 2 + .../__snapshots__/menuItem.jest.js.snap | 5 + src/components/MenuButton/MenuButton.jsx | 124 +++++++++++----- src/components/MenuButton/MenuButton.scss | 21 ++- .../__stories__/menuButton.stories.js | 23 ++- .../__snapshots__/menuButton.jest.js.snap | 8 ++ .../multiStepIndicator.jest.js.snap | 1 + src/components/RadioButton/RadioButton.scss | 7 + .../__snapshots__/splitButton.jest.js.snap | 12 -- src/components/TextField/TextField.jsx | 5 +- src/components/TextField/TextField.scss | 5 +- .../__stories__/textField.stories.js | 1 - src/general-stories/focus/focus.scss | 15 ++ src/general-stories/focus/focus.stories.js | 135 ++++++++++++++++++ src/styles/states.scss | 40 ++++++ 35 files changed, 491 insertions(+), 147 deletions(-) create mode 100644 src/general-stories/focus/focus.scss create mode 100644 src/general-stories/focus/focus.stories.js diff --git a/package.json b/package.json index cec89b3230..014f33605d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "monday-ui-react-core", - "version": "0.3.7", + "version": "0.3.8", "description": "Official monday.com UI resources for application development in React.js", "main": "dist/main.js", "scripts": { diff --git a/src/components/AttentionBox/__tests__/__snapshots__/attentionBox.jest.js.snap b/src/components/AttentionBox/__tests__/__snapshots__/attentionBox.jest.js.snap index 4eee62b47c..fbcae6aaf0 100644 --- a/src/components/AttentionBox/__tests__/__snapshots__/attentionBox.jest.js.snap +++ b/src/components/AttentionBox/__tests__/__snapshots__/attentionBox.jest.js.snap @@ -10,6 +10,7 @@ exports[`AttentionBox Tests Snapshot Tests renders correctly 1`] = ` > { + if (typeof leftIcon !== "function") return; + if (size === SIZES.SMALL) return "20"; + if (size === SIZES.MEDIUM) return "24"; + return "24"; + }, [leftIcon, size]); + + const rightIconSize = useMemo(() => { + if (typeof rightIcon !== "function") return; + if (size === SIZES.SMALL) return "20"; + if (size === SIZES.MEDIUM) return "24"; + return "24"; + }, [rightIcon, size]); + if (loading) { return (
+
-
{headerComponentRenderer && headerComponentRenderer()} -
+ {isOpen && (
{children}
@@ -49,6 +55,10 @@ const ExpandCollapse = forwardRef( ); ExpandCollapse.propTypes = { + /** + * Id for the component + */ + id: PropTypes.string, /** * Component as parameter to be rendered as header */ @@ -71,6 +81,7 @@ ExpandCollapse.propTypes = { defaultOpenState: PropTypes.bool }; ExpandCollapse.defaultProps = { + id: "", className: "", defaultOpenState: false, iconSize: 24 diff --git a/src/components/ExpandCollapse/ExpandCollapse.scss b/src/components/ExpandCollapse/ExpandCollapse.scss index 7f7acf9ca5..c39d7a3a5b 100644 --- a/src/components/ExpandCollapse/ExpandCollapse.scss +++ b/src/components/ExpandCollapse/ExpandCollapse.scss @@ -1,64 +1,67 @@ @import "../../styles/themes.scss"; @import "../../styles/typography.scss"; +@import "../../styles/states.scss"; .expand-collapse--wrapper { - .expand-collapse { - display: flex; - flex-direction: column; - justify-content: space-between; - align-items: center; - @include theme-prop(color, primary-text-color); - background-color: transparent; - border: 1px solid; - @include theme-prop(border-color, ui-border-color); - box-sizing: border-box; - border-radius: $border-radius-small; - } + .expand-collapse { + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; + @include theme-prop(color, primary-text-color); + background-color: transparent; + border: 1px solid; + @include theme-prop(border-color, ui-border-color); + box-sizing: border-box; + border-radius: $border-radius-small; + } - .expand-collapse__header { - padding: $spacing-medium; - display: flex; - justify-content: space-between; - align-items: center; - cursor: pointer; - } + .expand-collapse__header { + @include reset-button(); - .expand-collapse__header--open{ - border-bottom: 1px solid; - @include theme-prop(border-color, ui-border-color); - } + padding: $spacing-medium; + display: flex; + justify-content: space-between; + align-items: center; + cursor: pointer; + } - .expand-collapse__content { - padding: $spacing-medium; - } + .expand-collapse__header--open { + border-bottom: 1px solid; + @include theme-prop(border-color, ui-border-color); + } - .expand-collapse__section { - width: 100%; - } + .expand-collapse__content { + padding: $spacing-medium; + } - .animate-icon-open { - transform: rotate( -180deg ); - transition: transform 200ms ease; + .expand-collapse__section { + width: 100%; + } + + .animate-icon-open { + transform: rotate(-180deg); + transition: transform 200ms ease; + } + + .animate-icon-close { + transform: rotate(-360deg); + transition: transform 200ms ease; + } + + .animate-expand-collapse__content { + animation: expandContentAnimation 0.1s $expand-animation-timing; + } + + @keyframes expandContentAnimation { + 0% { + opacity: 0; + transform: translateY(-75px); + transform: translateY(var(--dropdown-menu-fadinY, -75px)); } - - .animate-icon-close { - transform: rotate( -360deg ); - transition: transform 200ms ease; + 100% { + opacity: 1; + transform: translateY(0px); } - - .animate-expand-collapse__content { - animation: expandContentAnimation 0.1s $expand-animation-timing; - } - - @keyframes expandContentAnimation { - 0% { - opacity: 0; - transform: translateY(-75px); - transform: translateY(var(--dropdown-menu-fadinY, -75px)); - } - 100% { - opacity: 1; - transform: translateY(0px); - } - } + } } diff --git a/src/components/ExpandCollapse/__stories__/expandCollapse.stories.js b/src/components/ExpandCollapse/__stories__/expandCollapse.stories.js index 7390a54bff..598c0a4464 100644 --- a/src/components/ExpandCollapse/__stories__/expandCollapse.stories.js +++ b/src/components/ExpandCollapse/__stories__/expandCollapse.stories.js @@ -8,22 +8,23 @@ import Robot from "../../Icon/Icons/components/Robot"; import "./expandCollapse.stories.scss" export const Sandbox = () => { - const width = number("width", 300); - const height = number("height", 200); + const width = number("width", 300); + const height = number("height", 200); - return (
- I can be anything}> -

insert any component you want

-

here is a robot for you

- -
-
); + return ( +
+ I can be anything}> +

insert any component you want

+

here is a robot for you

+ +
+
+ ); }; export const OpenByDefault = () => (
-

Any component you want

}> diff --git a/src/components/ExpandCollapse/__tests__/__snapshots__/expandCollapse.jest.js.snap b/src/components/ExpandCollapse/__tests__/__snapshots__/expandCollapse.jest.js.snap index fa0fbd1ccb..77f91029c3 100644 --- a/src/components/ExpandCollapse/__tests__/__snapshots__/expandCollapse.jest.js.snap +++ b/src/components/ExpandCollapse/__tests__/__snapshots__/expandCollapse.jest.js.snap @@ -3,16 +3,20 @@ exports[`ExpandCollapse renders correctly with empty props 1`] = `
-
-
+
`; diff --git a/src/components/Icon/Icon.jsx b/src/components/Icon/Icon.jsx index 9241172b60..32e29ae7d3 100644 --- a/src/components/Icon/Icon.jsx +++ b/src/components/Icon/Icon.jsx @@ -43,6 +43,7 @@ const Icon = forwardRef( return ( item 1
+
item 2
+
my item
+
my item
+
+
+
my item
+
{ const [isOpen, setIsOpen] = useState(open); @@ -88,41 +95,58 @@ const MenuButton = ({ [dialogOffset] ); + const onMouseUp = event => { + if (disabled) { + event.currentTarget.blur(); + } + }; + const Icon = component; const iconSize = size - 4; return ( - - - + + + ); }; @@ -135,6 +159,15 @@ const MenuButtonSizes = { }; const DialogPositions = { + LEFT: "left", + LEFT_START: "left-start", + LEFT_END: "left-end", + RIGHT: "right", + RIGHT_START: "right-start", + RIGHT_END: "right-end", + TOP: "top", + TOP_START: "top-start", + TOP_END: "top-end", BOTTOM: "bottom", BOTTOM_START: "bottom-start", BOTTOM_END: "bottom-end" @@ -185,8 +218,22 @@ MenuButton.propTypes = { dialogPosition: PropTypes.oneOf([ MenuButton.dialogPositions.BOTTOM_START, MenuButton.dialogPositions.BOTTOM, - MenuButton.dialogPositions.BOTTOM_END + MenuButton.dialogPositions.BOTTOM_END, + MenuButton.dialogPositions.LEFT, + MenuButton.dialogPositions.LEFT_START, + MenuButton.dialogPositions.LEFT_END, + MenuButton.dialogPositions.RIGHT, + MenuButton.dialogPositions.RIGHT_START, + MenuButton.dialogPositions.RIGHT_END, + MenuButton.dialogPositions.TOP, + MenuButton.dialogPositions.TOP_END, + MenuButton.dialogPositions.TOP_START ]), + + /** + * Dialog Alignment + */ + startingEdge: PropTypes.string, /* Callback function to be called when the menu is shown */ @@ -195,7 +242,15 @@ MenuButton.propTypes = { Callback function to be called when the menu is shown */ onMenuHide: PropTypes.func, - disabled: PropTypes.bool + /** + * Text to be displayed after the icon + */ + text: PropTypes.string, + disabled: PropTypes.bool, + /** + * Disabled tooltip text + */ + disabledReason: PropTypes.string }; MenuButton.defaultProps = { componentClassName: "", @@ -204,6 +259,7 @@ MenuButton.defaultProps = { open: false, zIndex: null, ariaLabel: "Menu", + startingEdge: "bottom", closeDialogOnContentClick: false, dialogClassName: "", openDialogComponentClassName: "", @@ -212,7 +268,9 @@ MenuButton.defaultProps = { dialogPosition: MenuButton.dialogPositions.BOTTOM_START, onMenuShow: NOOP, onMenuHide: NOOP, - disabled: false + disabled: false, + text: undefined, + disabledReason: undefined }; export default MenuButton; diff --git a/src/components/MenuButton/MenuButton.scss b/src/components/MenuButton/MenuButton.scss index c182aa124e..a345bb33d5 100644 --- a/src/components/MenuButton/MenuButton.scss +++ b/src/components/MenuButton/MenuButton.scss @@ -1,19 +1,19 @@ @import "../../styles/themes.scss"; @import "../../styles/typography.scss"; @import "../../styles/global-css-settings.scss"; +@import "../../styles/states.scss"; .menu-button--wrapper { + @include reset-button(); border-radius: $border-radius-small; - border: none; - outline: none; background-color: transparent; display: flex; align-items: center; justify-content: center; cursor: pointer; - padding: 0; transition: transform 50ms $expand-animation-timing; @include theme-prop(color, primary-text-color); + @include focus-style(); &:focus, &:hover { @@ -26,37 +26,40 @@ @include theme-prop(color, primary-color); &:focus { @include theme-prop(background-color, primary-selected-color); - } &:hover { @include theme-prop(background-color, primary-selected-color); } - } &--size-16 { width: 16px; height: 16px; + @include font-input(); } &--size-24 { width: 24px; height: 24px; + @include font-paragraph(); } &--size-32 { width: 32px; height: 32px; + @include font-paragraph(); } &--size-40 { width: 40px; height: 40px; + @include font-subtitle(); } &--size-48 { width: 48px; height: 48px; + @include font-title(); } &--reference-icon { @@ -71,6 +74,12 @@ @include theme-prop(border-color, disabled-background-color); @include theme-prop(color, disabled-text-color); cursor: not-allowed; - pointer-events: none; + } + &--text { + width: 100%; + } + + &--inner-text { + margin: 0 $spacing-small; } } diff --git a/src/components/MenuButton/__stories__/menuButton.stories.js b/src/components/MenuButton/__stories__/menuButton.stories.js index 9d6d24bd0e..359092c0c3 100644 --- a/src/components/MenuButton/__stories__/menuButton.stories.js +++ b/src/components/MenuButton/__stories__/menuButton.stories.js @@ -6,7 +6,7 @@ import { ComponentStateDescription, FlexLayout, StoryStateColumn, StoryStateRow import DropdownChevronDown from "../../Icon/Icons/components/DropdownChevronDown"; import "./menuButton.style.scss"; import { Menu, MenuItem, MenuTitle, MenuItemButton } from "../../index"; -import { Favorite, Sun, Moon } from "../../Icon/Icons"; +import { Favorite, Sun, Moon, AddSmall } from "../../Icon/Icons"; import Bolt from "../../Icon/Icons/components/Bolt"; import MoveArrowUp from "../../Icon/Icons/components/MoveArrowUp"; import MoveArrowDown from "../../Icon/Icons/components/MoveArrowDown"; @@ -50,6 +50,14 @@ export const Sandbox = () => ( ); +export const Disabled = () => ( +
+ + + +
+); + export const DifferentIcon = () => (
@@ -155,6 +163,19 @@ export const Positions = () => ( ); +export const WithText = () => ( +
+ + + +
+); + export default { title: "Components|MenuButton", component: MenuButton, diff --git a/src/components/MenuButton/__tests__/__snapshots__/menuButton.jest.js.snap b/src/components/MenuButton/__tests__/__snapshots__/menuButton.jest.js.snap index e80a3bace4..4af2f2ca55 100644 --- a/src/components/MenuButton/__tests__/__snapshots__/menuButton.jest.js.snap +++ b/src/components/MenuButton/__tests__/__snapshots__/menuButton.jest.js.snap @@ -2,6 +2,7 @@ exports[`renders correctly with Bolt Icon 1`] = ` + + +
+ Button Group + console.log("Selected: ", value)} + size={ButtonGroup.sizes.MEDIUM} + options={[ + { value: 1, text: "Option 1", icon: Robot }, + { value: 2, text: "Option 2" }, + { value: 3, text: "Option 3", leftIcon: Bolt } + ]} + /> + Split Buttons +
+ Content
}>Split + Content
}> + Split + +
+ Checkbox +
+ + + +
+ + Radio buttons +
+ + + +
+ Fields +
+ + +
+ Breadcrumbs +
+ + + + + + +
+ Menu Button component + + + + + + + + + + + + + + + + Expandable component +
+ I can be anything}> +

insert any component you want

+

here is a robot for you

+ +
+
+
+
+ ); +}; + +export default { + title: "Foundations|Focus" +}; diff --git a/src/styles/states.scss b/src/styles/states.scss index 720dd3908f..0c3f485557 100644 --- a/src/styles/states.scss +++ b/src/styles/states.scss @@ -9,3 +9,43 @@ background-color: transparent; } } + +@mixin reset-button { + border: none; + margin: 0; + padding: 0; + width: auto; + overflow: visible; + + background: transparent; + + /* inherit font & color from ancestor */ + color: inherit; + font: inherit; + + /* Normalize `line-height`. Cannot be changed from `normal` in Firefox 4+. */ + line-height: normal; + + /* Corrects font smoothing for webkit */ + -webkit-font-smoothing: inherit; + -moz-osx-font-smoothing: inherit; + /* Corrects inability to style clickable `input` types in iOS */ + -webkit-appearance: none; + + @include focus-style(); +} + +@mixin focus-style { + &:focus:not(.focus-visible) { + outline: none; + } + &:focus-visible, + &.focus-visible { + outline: none; + //border: 1px solid; + @include theme-prop(border-color, primary-color); + box-shadow: 0 0 0 2px hsla(209, 100%, 50%, 0.5); + z-index: 11; + border-radius: 2px; + } +}