Skip to content

refactor(dashboard): measure scrollbar width directly from element#2069

Open
chintankavathia wants to merge 18 commits into
mainfrom
refactor/dashboard/scroll-width
Open

refactor(dashboard): measure scrollbar width directly from element#2069
chintankavathia wants to merge 18 commits into
mainfrom
refactor/dashboard/scroll-width

Conversation

@chintankavathia
Copy link
Copy Markdown
Member

@chintankavathia chintankavathia commented May 15, 2026

Replace ScrollbarHelper service with direct offsetWidth - clientWidth measurement on the scrollable element, which is more accurate and SSR-safe.

DEPRECATED: ScrollbarHelper service is deprecated and will be removed in v51. Use element.offsetWidth - element.clientWidth on the scrollable element instead.


Documentation.
Examples.
Dashboards Demo.
Playwright report.

Coverage Reports:

Code Coverage

chintankavathia and others added 17 commits May 12, 2026 13:36
…kerConfig

BREAKING CHANGE: `CriterionDefinition.datepickerConfig` type narrowed

The type of `datepickerConfig` in `CriterionDefinition` (filtered-search) changed from `DatepickerInputConfig` to `Omit<DatepickerInputConfig, 'enableDateRange' | 'enableTwoMonthDateRange'>`.

The properties `enableDateRange` and `enableTwoMonthDateRange ` are no longer accepted in `datepickerConfig` when used with filtered-search criteria, as they had no effect in that context.

Migration: Remove any `enableDateRange` and `enableTwoMonthDateRange` properties from your `datepickerConfig` objects passed to `CriterionDefinition`.
Adding a set of utilities that allows customers
to create selects with custom backed value selection,
for instance using `si-tree-view`.

A very simple version of it can look like this:

```ts
@component({
  selector: 'app-tree-select',
  imports: [SiSelectComboboxComponent, SiSelectDropdownDirective, SiTreeViewComponent],
  template: `
    <si-select-combobox>
      @if (select.value(); as val) {
        {{ val }}
      } @else {
        <span class="text-secondary">Select a location...</span>
      }
    </si-select-combobox>

    <ng-template si-select-dropdown>
      <si-tree-view
        class="d-block"
        ariaLabel="Locations"
        [items]="items()"
        [enableSelection]="true"
        [singleSelectMode]="true"
        [isVirtualized]="false"
        (treeItemClicked)="selectItem($event)"
      />
    </ng-template>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
  hostDirectives: [
    {
      directive: SiCustomSelectDirective,
      inputs: ['disabled', 'readonly', 'value'],
      outputs: ['valueChange']
    }
  ]
})
export class TreeSelectComponent {
  protected readonly select = inject(SiCustomSelectDirective);

  /** The tree items to display. */
  readonly items = input<TreeItem[]>([]);

  selectItem(item: TreeItem): void {
    if (item.label) {
      this.select.updateValue(item.label as string);
      this.select.close();
    }
  }
}
```

The goal is to empower applications
to build selects with whatever content they need
while we take care of accesibility and proper appereance.

Closes #1840
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request deprecates the ScrollbarHelper service and updates SiDashboardComponent to calculate scrollbar width directly using DOM properties. Feedback suggests refining the calculation to account for borders, ensuring SSR safety by guarding DOM access with isPlatformBrowser, and optimizing performance in the dashboard component by utilizing existing dimension data to avoid redundant DOM reads.

Comment thread projects/element-ng/common/services/scrollbar-helper.service.ts
Comment thread projects/element-ng/dashboard/si-dashboard.component.ts
Replace ScrollbarHelper service with direct offsetWidth - clientWidth
measurement on the scrollable element, which is more accurate and
SSR-safe.

DEPRECATED: `ScrollbarHelper` service is deprecated and will be removed
in v51. Use `element.offsetWidth - element.clientWidth` on the
scrollable element instead.
@chintankavathia chintankavathia force-pushed the refactor/dashboard/scroll-width branch from 4e0397e to 70ec30a Compare May 15, 2026 07:07
@chintankavathia chintankavathia marked this pull request as ready for review May 15, 2026 07:33
@chintankavathia chintankavathia requested review from a team as code owners May 15, 2026 07:33
Comment on lines 251 to +258
let padding = this.document.body.offsetWidth >= BOOTSTRAP_BREAKPOINTS.mdMinimum ? 32 : 16;
if (
dashboardDimensions &&
dashboardFrameDimensions &&
dashboardDimensions.height > dashboardFrameDimensions.height
) {
padding = padding - this.scrollbarHelper.width;
const { offsetWidth, clientWidth } = this.dashboardFrame().nativeElement;
padding = padding - (offsetWidth - clientWidth);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this whole padding calculation stuff can be dropped completely. Instead use the normal padding helper classes and when the scrollbar is visible, trigger a class that has scrollbar-gutter: stable;. What scheduler uses these days

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be I don't get it but isn't here it is opposite so we need to decrease padding when scrollbar is present but scrollbar-gutter: stable; ensures to have extra space always even when there is no scrollbar. padding value needs to be decreased upto width of scrollbar so that it vertically aligns with button above which differs browsers to browsers.

image

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah...didn't really read the code. I have a similar use case with a header and a scrollable area. What I do is to add the scrollbar-gutter to the header so it is aligned with the scroll area

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would work in terms of alignement but will add extra space when we have scrollbar:

with proposed change

  • with scrollbar
image

-without scrollbar
image

existing

  • with scrollbar
image
  • without scrollbar
image

@panch1739 WDYT

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants