Skip to content
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

[Feature]: Overflow should allow for configuration of gap per item #33643

Open
1 task done
mathis-m opened this issue Jan 14, 2025 · 2 comments
Open
1 task done

[Feature]: Overflow should allow for configuration of gap per item #33643

mathis-m opened this issue Jan 14, 2025 · 2 comments

Comments

@mathis-m
Copy link
Contributor

mathis-m commented Jan 14, 2025

Area

React Components (@fluentui/react-components)

Describe the feature that you would like added

Currently it is not posible to define the exact gap between items so that at any given point in time the visible items are hidden at the exact time of overflow.

We can only provide a static padding, this results for early overflow when resizing smaller. This is getting more noticable for whenn many items are used with a larger gap.
Eg. 10 items (100px width), gap 20px => padding 200px
Item 2 will be hidden at 399px container width, Even tho it would fit until 220px container width

Example dynamic padding based on visible item count: [Item 1] [Item 2] [Item 3]

General State
Item width: 100px
Gap: 10px

Initial state for Overflow
Overflow Padding: 20px
Container size: 320px

Container Resize
Container size: 319px

Overflow Manager will hide Item 3 because 3 * 100 > 319 - 20
Example is now: [Item 1] [Item 2]

Option 1: In order for the overflow to happen after resizing at 209px the padding needs to be in total 10px.

Option 2: But the padding as well needs to be 20px so that the overflow can happen after resizing to 320px. Otherwise it would already show item 3 at 310px when we would use 10px for padding.

Even if we would use 10px (Option 1, set padding to actual total padding currently in use) this would introduce a flickering as the overflow manager (instances, plural because if the options change a new instance is created) would oscillate between 3 and 2 items:

container size: 319px
padding: 20px

  1. 3 * 100 > 319 - 20 => Item 3 hide
  2. Update Padding to 10px
  3. Next instance of overflow manager is created: all items are in visible queue
  4. Hide Until 3 * 100 < 319 - 10 => all are shown
  5. Update Padding to 20px
  6. Next instance of overflow manager is created: all items are in visible queue
  7. Hide Until 3 * 100 < 319 - 20=> Item 3 is hidden
  8. Continue at 2.

Related Code for proccesing of items:

const processOverflowItems = (): boolean => {
if (!container) {
return false;
}
sizeCache.clear();
const availableSize = getClientSize(container) - options.padding;
// Snapshot of the visible/invisible state to compare for updates
const visibleTop = visibleItemQueue.peek();
const invisibleTop = invisibleItemQueue.peek();
while (compareItems(invisibleItemQueue.peek(), visibleItemQueue.peek()) > 0) {
hideItem(); // hide elements whose priority become smaller than the highest priority of the hidden one
}
// Run the show/hide step twice - the first step might not be correct if
// it was triggered by a new item being added - new items are always visible by default.
for (let i = 0; i < 2; i++) {
// Add items until available width is filled - can result in overflow
while (
(occupiedSize() < availableSize && invisibleItemQueue.size() > 0) ||
invisibleItemQueue.size() === 1 // attempt to show the last invisible item hoping it's size does not exceed overflow menu size
) {
showItem();
}
// Remove items until there's no more overflow
while (occupiedSize() > availableSize && visibleItemQueue.size() > options.minimumVisible) {
hideItem();
}
}
// only update when the state of visible/invisible items has changed
return visibleItemQueue.peek() !== visibleTop || invisibleItemQueue.peek() !== invisibleTop;
};

Re-instantiate of manager

useIsomorphicLayoutEffect(() => {
if (!containerRef.current || !canUseDOM() || firstMount) {
return;
}
const newOverflowManager = createOverflowManager();
newOverflowManager.observe(containerRef.current, overflowOptions);
setOverflowManager(newOverflowManager);
// We don't want to re-create the overflow manager when the first mount flag changes from true to false
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [overflowOptions]);
/* Clean up overflow manager on unmount */
React.useEffect(
() => () => {
overflowManager?.disconnect();
},
[overflowManager],
);

Add all items to visible queue after instantiate

Object.values(overflowItems).forEach(item => visibleItemQueue.enqueue(item.id));

Missing Option from my perspective

Provide a way to either statically define a space between items and padding per item, that is used based on items visible.
Provide a function that is called per item to let the user decide based on id and index what the total padding is.

Is there a better solution to process overflow

Probably, yes, is there any reason why we use width sum instead of reverse iterating and checking x coordinate plus width?
If coordinate would be used, all the css gap would work ootb.

Additional context

No response

Have you discussed this feature with our team

No response

Validations

  • Check that there isn't already an issue that requests the same feature to avoid creating a duplicate.

Priority

Low

@ValentinaKozlova
Copy link
Contributor

Hello @mathis-m, currently there's a workaround for a gap in the Overflow component.
You might want to use OverflowDivider as a gap and to style it accordingly.
It's not the best solution, but might help for now.
Here's an example:
https://stackblitz.com/edit/um8bvi5k?file=src%2Fexample.tsx

@mathis-m
Copy link
Contributor Author

Hello @mathis-m, currently there's a workaround for a gap in the Overflow component.
You might want to use OverflowDivider as a gap and to style it accordingly.
It's not the best solution, but might help for now.
Here's an example:
https://stackblitz.com/edit/um8bvi5k?file=src%2Fexample.tsx

Thanks, my workaround is to add padding within the item itself, depending on its index and if overflow button is shown or not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants