-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
Component-based toolbar customisation API #3067
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
1 Ignored Deployment
|
Happy to talk through what you're unsure about with the CSS - afaict, there's not a way of avoiding doing something DOM-based like this if we want to drive the API through react components rather than e.g. an For me, the main thing I want to avoid is making consumers have to manage the overflow logic themselves if they want to do custom tools. I don't understand how the two separate groups thing avoids that - the overflow group needs to know how many items are visible in the main group, right? I'm probably missing something from yr description tho |
I think no, it would just use the opposite logic as relates to the breakpoint! i.e. the toolbar might have "show only the first five at breakpoint 4" and the overflow menu would have "show all but the first five at breakpoint 4". |
I have a branch that works for what I expected it to work for, but the "last selected shape" is beyond me. We can review together to see if you have any ideas, otherwise I think your approach is the best option. |
|
||
export function OverflowingToolbar({ children }: { children: React.ReactNode }) { | ||
const editor = useEditor() | ||
const id = useId().replace(/:/g, '_') |
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 replacement here? i see we do it in ArrowShapeUtil - should there be a util function safeId
or something like that? hard to know why this is necessary on first read
</div> | ||
{totalItems > overflowIndex && ( | ||
<IsInOverflowContext.Provider value={true}> | ||
<TldrawUiDropdownMenuRoot id="toolbar overflow" modal={false}> |
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 know we have this in a couple places in the codebase but it feels odd to have a space in the id
- i know you're not doing this but if there was ever a css selector rule targeting this you wouldn't be able to do it. maybe a bit of pedanticism on my part ¯_(ツ)_/¯
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.
yeahhh, this is just copied from what was here before. confusingly, this isn't actually a DOM ID at all - it's used to identify this menu in our weird isMenuOpen
system
if (lastActiveOverflowItem) { | ||
showInMainSelectors.push(`[data-value="${lastActiveOverflowItem}"]`) | ||
} else { | ||
showInMainSelectors.push(`:nth-child(${overflowIndex + 1})`) |
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'm curious: is there a way to do this without the dynamic css?
like, can there be a demarcated element with a className that looks at a boundary or some other kind grouping?
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 don't think so? steve's branch was trying that - we can sort of make it work for truncating the list, but not really for the active item which is pretty dynamic. open to suggestions tho!
if (!mainToolsRef.current) return | ||
|
||
const mutationObserver = new MutationObserver(onDomUpdate) | ||
mutationObserver.observe(mainToolsRef.current, { |
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.
oo fancy!
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.
a9adbb9
to
2dacf12
Compare
When we went from overrides-based to component based UI customisation APIs, we didn't do the toolbar because it had some significant extra complexity around overflowing the contents of the menu into the dropdown. This is really hard to do at render-time with react - you can't introspect what a component will return to move some of it into an overflow.
Instead, this diff runs that logic in a
useLayoutEffect
- we render all the items into both the main toolbar and the overflow menu, then in the effect (or if the rendered components change) we use CSS to remove the items we don't need, check which was last active, etc. Originally, I wasn't really into this approach - but i've actually found it to work super well and be very reliable.Change Type
major
— Breaking changedependencies
— Changes to package dependencies1documentation
— Changes to the documentation only2tests
— Changes to any test code only2internal
— Any other changes that don't affect the published package2Test Plan
Footnotes
publishes a
patch
release, for devDependencies useinternal
↩will not publish a new version ↩ ↩2 ↩3