✨ [bento][amp-sidebar] Preact version of amp-sidebar#31479
✨ [bento][amp-sidebar] Preact version of amp-sidebar#31479krdwan merged 9 commits intoampproject:masterfrom
Conversation
dvoytenko
left a comment
There was a problem hiding this comment.
This looks pretty much there. No significant comments on structure.
dvoytenko
left a comment
There was a problem hiding this comment.
Looks good, but one thing is not quite clear.
caroqliu
left a comment
There was a problem hiding this comment.
Left a couple comments/questions but LGTM for the foundation. I'm curious what the plan is for:
- checking/warning if the component is a direct descendent of
<body> - responsive toolbar feature
- future functionality for nested menus that interop with sidebar
- bonus: if we were to add support for display locking, what would that look like? we could no longer conditionally render the markup
Would also be nice for the storybook to have a scrollable sample too.
| * @return {{current: T}} | ||
| * @template T | ||
| */ | ||
| function useValueRef(current) { |
There was a problem hiding this comment.
I think lightbox also defines useValueRef, do you want to move it to preact/index or preact/utils instead?
There was a problem hiding this comment.
At this very initial stage, I'd like to keep it separate as I think a lot may change during the rest of the sidebar implementation. But I've added an item to the tracker to #31366 to look at shared items between this and lightbox. We have also talked about creating a common component that does the animations.
| // To open, we mount and render the contents (invisible), then animate the display (visible). | ||
| // To close, it's the reverse. | ||
| // `mounted` mounts the component. `opened` plays the animation. | ||
| const initialOpen = false; |
There was a problem hiding this comment.
If this is always false, do we need a named constant for the two times it's used?
| }, [onBeforeOpenRef]); | ||
| const close = useCallback(() => setOpened(false), []); | ||
| const toggle = useCallback(() => (opened ? close() : open()), [ | ||
| opened, |
There was a problem hiding this comment.
Would it be helpful to have an openedRef so this callback value does not have to be redefined every time the state changes?
There was a problem hiding this comment.
Thanks, will address this as a follow up once we get further into the sidebar implementation.
| // `mounted` mounts the component. `opened` plays the animation. | ||
| const initialOpen = false; | ||
| const [mounted, setMounted] = useState(initialOpen); | ||
| const [opened, setOpened] = useState(initialOpen); |
There was a problem hiding this comment.
nit: Should this follow [visible, setVisible] like lightbox? the meaning of "open" could get a bit overloaded here
There was a problem hiding this comment.
I personally prefer opened since the sidebar docs all refer to the sidebar as being opened / closed. 🙂
| : ANIMATION_KEYFRAMES_SLIDE_IN_RIGHT, | ||
| { | ||
| duration: ANIMATION_DURATION, | ||
| fill: 'both', |
There was a problem hiding this comment.
FMI: Why are some of these style objects given constant doc level names and others inlined here?
There was a problem hiding this comment.
It is a tiny bit wonky, but my thought process was -
fill and direction are not configurable as they are fundamentally needed for the way the animation works.
duration and ease-in can be configured to make the animation slower / faster, curvier, and it still works, so thought it made sense to make as a constant.
I'm not married to it either way so let me know if you feel strongly about it.
| side === 'left' ? classes.left : classes.right | ||
| }`} | ||
| role="menu" | ||
| tabindex="-1" |
There was a problem hiding this comment.
Isn't a <div> not focusable by default?
There was a problem hiding this comment.
Also, shouldn't it be focusable so it can listen for Esc to close?
There was a problem hiding this comment.
The only ways to close that have been implemented so far are the imperative API and click on the mask. I have an action item in the tracker: #31366 for handling focus, so I'll follow up at that point :). This may be updated.
| import {createUseStyles} from 'react-jss'; | ||
|
|
||
| const sidebarClass = { | ||
| position: 'fixed !important', |
There was a problem hiding this comment.
FMI: Why do we need these !importants?
There was a problem hiding this comment.
Mostly just so the user cannot over overwrite by accident (or on purpose). The way the sidebar animates in and is positioned on the viewport is all critically dependent on position: fixed.
| return ( | ||
| <> | ||
| <Sidebar ref={ref} {...props}> | ||
| <div style={{margin: 8}}> |
There was a problem hiding this comment.
Is this margin necessary?
There was a problem hiding this comment.
It's not needed per se, but I think it looks infinitely better with the margin. 😂
Are you opposed to it?
There was a problem hiding this comment.
This is storybook only, right?
There was a problem hiding this comment.
Right, this is just in the storybook.
First draft of Preact amp-sidebar component for initial review
12/11 - Update