-
Notifications
You must be signed in to change notification settings - Fork 54
feat(Popup): refactor and add controlled mode #282
Conversation
Codecov Report
@@ Coverage Diff @@
## master #282 +/- ##
========================================
- Coverage 91.69% 89.9% -1.8%
========================================
Files 62 62
Lines 1168 1159 -9
Branches 150 150
========================================
- Hits 1071 1042 -29
- Misses 94 115 +21
+ Partials 3 2 -1
Continue to review full report at Codecov.
|
@@ -1,145 +1,67 @@ | |||
import React from 'react' | |||
import { Button, Grid, Popup } from '@stardust-ui/react' | |||
|
|||
class PopupArrowExample extends React.Component<any, any> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why the name is PopupArrow
? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 name should reflect name of file
src/components/Popup/Popup.tsx
Outdated
/** The popup content (deprecated). */ | ||
children: customPropTypes.disallow(['children']), | ||
children: PropTypes.any, // customPropTypes.disallow(['children']), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it intended?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to remove disallow
statement - yes, this is intended :) but at the same time (other than cleaning up commented code), PropTypes.node would be a better substitute here - let me address that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we remove it? we support children API now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes - as this is quite reasonable for the Popup case, see:
<SomeTree>
<Popup content={popupContent}>
<button>Click me to trigger popup</button>
</Popup>
</SomeTree>
Now to introduce popup functionality it is necessary just to wrap the component that previously was in the tree - to augment it with popup functionality (and make it a trigger)
src/components/Popup/Popup.tsx
Outdated
toggle: e => _.invoke(this.props, 'onOpenChange', e, !this.props.open), | ||
closeAndFocusTrigger: e => { | ||
_.invoke(this.props, 'onOpenChange', false) | ||
_.invoke(this.state.triggerRef, 'focus') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, in case of user won't provide onOpenChange
function which will handle open/close state, the Popup won't be closed, but the trigger would be focused. It seems like a not expected scenario.
And seems like same for toggle (in case it's not a button).
Let's discuss it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a good catch - lets discuss closeAndFocus
case. Speaking of the toggle
one - could you, please, suggest what the problem is exactly about?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Speaking of a toggle, if a trigger is not button
element, you won't be able to toggle popup with Enter
\ Space
button. So, do we expect here that a user should use ```onOpenChange`` function in case to handle toggling?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes - but this leads us to more general problem that is rather accessibility related. In this PR I would like to focus on the following things, with all the previously introduced functionality being untouched:
- refactor and simplify
Popup
base implementation - introduce controlled mode to it
So, these are the main reasons I've left PopupBehavior
's functionality as it was introduced before. so that If we would like to address/discuss some problems related to this aspect exclusively, we would be able to do it by means of a dedicated PR.
Please, let me know about your thoughts on that :)
docs/src/examples/components/Popup/Variations/PopupExamplePosition.shorthand.tsx
Show resolved
Hide resolved
src/components/Popup/Popup.tsx
Outdated
children?: ReactChildren | ||
className?: string | ||
content?: ItemShorthand | ItemShorthand[] | ||
defaultOpen?: boolean | ||
open?: boolean | ||
onOpenChange?: () => void |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should't we expose the open
flag here as well; what's the advantage of this on having 2 props as in SUIR:
onOpen
and onClose
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for adding handlers onOpen and onClose that would be invoked based on the value of the open. It is much cleaner API for the user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any thoughts here?
src/components/Popup/Popup.tsx
Outdated
...accessibility.keyHandlers.trigger, | ||
})} | ||
</Ref> | ||
{this.props.open && this.renderPopupContent(rtl, accessibility)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: add open
to destructured object above and use from there
docs/src/examples/components/Popup/Variations/PopupExamplePosition.shorthand.tsx
Show resolved
Hide resolved
docs/src/examples/components/Popup/Variations/PopupExamplePosition.shorthand.tsx
Show resolved
Hide resolved
docs/src/examples/components/Popup/Variations/PopupExamplePosition.shorthand.tsx
Outdated
Show resolved
Hide resolved
docs/src/examples/components/Popup/Variations/PopupExamplePosition.shorthand.tsx
Show resolved
Hide resolved
docs/src/examples/components/Popup/Variations/PopupExamplePosition.shorthand.tsx
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pls take a look at comments
src/components/Popup/Popup.tsx
Outdated
style={popupPlacementStyles} | ||
{...accessibility.attributes.popup} | ||
{...accessibility.keyHandlers.popup} | ||
data-placement={placement} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this needed? accessibility / w3c standards? it's not adding any functionality
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these lines reflect changes that were merged by another PR - please, take a look on the current state of master. So, those are necessary to project this already introduced functionality on top of changes made in this PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was talking about line 162:
data-placement={placement}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, got it - let me address..
{ position: 'after', align: 'top', icon: 'arrow circle right', padding: '5px 5px 18px 42px' }, | ||
{ position: 'after', align: 'center', icon: 'arrow circle right', padding: '5px 5px 5px 42px' }, | ||
{ position: 'after', align: 'bottom', icon: 'arrow circle right', padding: '18px 5px 5px 42px' }, | ||
] | ||
|
||
const PopupExamplePosition = () => ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This const and the class both have the same name which is casing some compiler errors:
[at-loader] Checking finished with 2 errors
[at-loader] ./docs/src/examples/components/Popup/Variations/PopupExamplePosition.shorthand.tsx:4:7
TS2300: Duplicate identifier 'PopupExamplePosition'.
[at-loader] ./docs/src/examples/components/Popup/Variations/PopupExamplePosition.shorthand.tsx:52:7
TS2300: Duplicate identifier 'PopupExamplePosition'.
Please rename one of them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
approved
TODO
The following issues are aimed to be addressed by the proposed PR:
Popup
componentas
propas
components/elements could cause breaks in ref capturing logicPopup
open
anddefaultOpen
props