-
Notifications
You must be signed in to change notification settings - Fork 11.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Grafana/UI: Add new Splitter component #82357
Conversation
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 looks great and is really gonna help with our consistency 🚀
Add dragPosition prop so we can have drag handles on the edge in panel edit (saves some space and we then use same UX pattern as with the drag handle in the drawer that is also on the edge)
my potentially controversial UX opinion... i think we should always indent our drag handles and not have them on the edge. something like:
default | onHover | |
---|---|---|
explore | ||
drawer |
@ashharrison90 not sure, looks very strange with a drag handle floating inside the box. Feels much more intuitive with it the edge (and that way it does not conflict/overlap the content). We can tweak the drag handle styling maybe (in the future) to add some kind of grip bars to make it more noticeable or tweak the background. Did check with UX (patrick) and agree that having on the edge is best, like we do for drawer and explore drawer. For panel edit the options pane there is no room to have it inside the box |
@ashharrison90 here is having it inside the panel edit options pane, not great :) |
@torkelo yeah in the panel edit case i'd still have it in the gap tbh. that feels like a slightly different use case to drawers anyway (resizing 2 panes vs. resizing one edge) the main reason for me thinking that is that other drag handle examples are indented, e.g. slack on mobile: but that might be more of a mobile pattern 🤔 |
@ashharrison90 slack on desktop it's on the edge (without any drag handle) |
@ashharrison90 pushed storybook docs, and added some prop docs and simplified it a bit more. Think this is ready |
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.
Looks good!
verticalOffset = '0'; | ||
horizontalOffset = '0'; |
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.
verticalOffset = '0'; | |
horizontalOffset = '0'; | |
verticalOffset = '0%'; | |
horizontalOffset = '0%'; |
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.
fixed
kids, | ||
containerRef, | ||
firstPaneRef, | ||
minDimProp, | ||
splitterRef, | ||
measurementProp, | ||
handleSize, | ||
onPointerUp, | ||
onPointerDown, | ||
onPointerMove, | ||
onKeyDown, | ||
onKeyUp, | ||
onDoubleClick, | ||
onBlur, | ||
secondPaneRef, |
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 lot of returned "things". could we instead group some of them into one thing like splitterProps
that can then be spread onto the splitter element? i'm mostly thinking about the interaction stuff (onPointer
, onKey
, onBlur
, etc.), since they all have to go on the same element anyway
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.
you could also return the tabIndex
, associated aria-value*
attributes and role
stuff as part of the splitterProps
as well if you pass through the initialSize
? that way you wouldn't have to manipulate the dom directly in the hook to change ariaValueNow
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.
@ashharrison90 I moved most to a splitterProps and got rid of a few others, I did not like adding role, aria props tabIndex etc, because then I basically have move everything to the hook and there i no nothing in the markup generation left so the separation between callback / static logic and markup rendering becomes lost.
I agree if useSplitter was designed to be used outside this component is should probably return all props, but here it just a way to separate all the callbacks from the rendering
: never; | ||
type HTMLElementOrNull = HTMLElement | null; | ||
|
||
function measureElement<T extends HTMLElementOrNull>(ref: T): MeasureR<T> { |
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 think we can simplify our types a lot here if we restrict this to only allow an element to be passed (and not null
). then our return type is always just
{ minWidth, maxWidth, minHeight, maxHeight }
and we just gate every use of measureElement
behind an if statement, like
if (firstPaneRef.current) {
const dim = measureElement(firstPaneRef.current);
...
}
this will also allow us to remove all(?) of the !
operators. maybe slightly more lines, but imo more readable and type-safe 😎
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.
good suggestion! updated, had to add a lot if statements though :)
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.
can remove the type assertion - otherwise lgtm 👍
ref.style.height = savedHeight; | ||
ref.style.flexGrow = savedFlex; | ||
|
||
return { minWidth, maxWidth, minHeight, maxHeight } as MeasureResult; |
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.
can remove this type assertion 🥳
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.
ah, of course :)
* Initial thing working * Update * Progress * Update * Update * Simplify a bit more * minor refacto * more review fixes * Update * review fix * minor fix * update
This brings a component @kaydelaney developed over from the scenes lib. As we need it in core directly (and not only through scenes SplitLayout).
General-Layout-Splitter---Basic-.-Storybook.mp4