Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
MurhafSousli committed Jul 11, 2024
1 parent 87f0b8d commit ea15b10
Show file tree
Hide file tree
Showing 15 changed files with 127 additions and 26 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## 15.1.0

- feat: Add a new option `hoverOffset` to activate hover effect on the offset area around the scrollbar, closes [#616](https://github.com/MurhafSousli/ngx-scrollbar/issues/616).
- fix: Scrollbar thumb color is not changing on hover, closes [#625](https://github.com/MurhafSousli/ngx-scrollbar/issues/625).

## 15.0.4

- fix: global Angular app styles gets broken in Firefox, closes [#615](https://github.com/MurhafSousli/ngx-scrollbar/issues/615).
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
ng-scrollbar {
--scrollbar-thickness: 7;
--scrollbar-hover-thickness: 7;
--scrollbar-offset: 16;
--scrollbar-track-color: rgb(0 0 0 / 10%);
--scrollbar-thumb-color: rgb(0 0 0 / 20%);
Expand Down
14 changes: 13 additions & 1 deletion projects/ngx-scrollbar-demo/src/app/lab/lab.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,15 @@
</mat-button-toggle-group>
</div>

<div class="lab-control">
<div class="lab-control-label">Hover offset</div>
<mat-button-toggle-group aria-label="Hover offset"
[(value)]="hoverOffset">
<mat-button-toggle [value]="true">True</mat-button-toggle>
<mat-button-toggle [value]="false">False</mat-button-toggle>
</mat-button-toggle-group>
</div>

<div class="lab-control">
<div class="lab-control-label">Buttons</div>
<mat-button-toggle-group aria-label="Buttons"
Expand Down Expand Up @@ -117,7 +126,9 @@
</div>
</mat-expansion-panel>

<mat-expansion-panel>
<mat-expansion-panel [style.overflow]="stylingPanelExpanded ? 'initial' : 'hidden'"
(afterExpand)="stylingPanelExpanded = true"
(expandedChange)="onExpandedChange($event)">
<mat-expansion-panel-header>
<mat-panel-title>
Styling
Expand Down Expand Up @@ -153,6 +164,7 @@
[position]="position"
[style]="cssVariables"
[buttons]="buttons"
[hoverOffset]="hoverOffset"
[disableInteraction]="interactionDisabled"
[disableSensor]="disableSensor"
[sensorThrottleTime]="sensorThrottleTime"
Expand Down
15 changes: 11 additions & 4 deletions projects/ngx-scrollbar-demo/src/app/lab/lab.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ChangeDetectionStrategy, Component, signal, ViewChild, WritableSignal } from '@angular/core';
import { Component, inject, signal, ViewChild, WritableSignal, ChangeDetectionStrategy } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { DomSanitizer, SafeStyle } from '@angular/platform-browser';
Expand Down Expand Up @@ -51,10 +51,15 @@ import { SmoothScrollFormComponent, SmoothScrollOptionsForm } from './smooth-scr
})
export class LabComponent {

private sanitizer: DomSanitizer = inject(DomSanitizer);

@ViewChild(NgScrollbar, { static: true }) component: NgScrollbar;

stylingPanelExpanded: boolean;

direction: 'ltr' | 'rtl' = 'ltr';
buttons: boolean = true;
hoverOffset: boolean = false;
interactionDisabled: boolean = false;
disableSensor: boolean = false;
disableReached: boolean = false;
Expand Down Expand Up @@ -97,9 +102,6 @@ export class LabComponent {
return '<b>Lorem ipsum dolor sit amet</b>' + content.repeat(this.slider.contentSize);
}

constructor(private sanitizer: DomSanitizer) {
}

width: number = 448;
height: number = 300;
id: number = -1;
Expand Down Expand Up @@ -154,6 +156,11 @@ export class LabComponent {
}
}

onExpandedChange(expanded: boolean): void {
if (!expanded) {
this.stylingPanelExpanded = false;
}
}
}

const content: string = `
Expand Down
8 changes: 4 additions & 4 deletions projects/ngx-scrollbar/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ngx-scrollbar",
"version": "15.0.4",
"version": "15.1.0",
"license": "MIT",
"homepage": "https://ngx-scrollbar.netlify.com/",
"author": {
Expand All @@ -20,9 +20,9 @@
"scroll-reached"
],
"peerDependencies": {
"@angular/common": ">=17.0.0",
"@angular/core": ">=17.0.0",
"@angular/cdk": ">=17.0.0",
"@angular/common": ">=17.1.0",
"@angular/core": ">=17.1.0",
"@angular/cdk": ">=17.1.0",
"rxjs": ">=7.0.0"
},
"dependencies": {
Expand Down
8 changes: 7 additions & 1 deletion projects/ngx-scrollbar/src/lib/ng-scrollbar-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ const defaultOptions: NgScrollbarOptions = {
sensorThrottleTime: 0,
disableSensor: false,
disableInteraction: false,
buttons: false
buttons: false,
hoverOffset: false
};

interface ViewportState {
Expand Down Expand Up @@ -154,6 +155,11 @@ export abstract class NgScrollbarCore implements _NgScrollbar, OnInit, AfterView
transform: numberAttribute
});

/** A flag used to activate hover effect on the offset area around the scrollbar */
hoverOffset: InputSignalWithTransform<boolean, string | boolean> = input<boolean, string | boolean>(this.options.hoverOffset, {
transform: booleanAttribute
});

viewportDimension: WritableSignal<ViewportBoundaries> = signal({
contentHeight: 0,
contentWidth: 0,
Expand Down
2 changes: 2 additions & 0 deletions projects/ngx-scrollbar/src/lib/ng-scrollbar.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,6 @@ export interface NgScrollbarOptions {
disableSensor?: boolean;
/** Show scrollbar buttons */
buttons?: boolean;
/** A flag used to activate hover effect on the offset area around the scrollbar */
hoverOffset?: boolean;
}
8 changes: 4 additions & 4 deletions projects/ngx-scrollbar/src/lib/scrollbar/horizontal.scss
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@
.ng-scrollbar-track-wrapper {
height: var(--_track-x-thickness);
flex-direction: row;
}

&:hover {
--_track-x-thickness: var(--_scrollbar-hover-thickness-px);
--_thumb-x-color: var(var(--INTERNAL-scrollbar-thumb-min-size));
}
.ng-scrollbar-hover:hover {
--_track-x-thickness: var(--_scrollbar-hover-thickness-px);
--_thumb-x-color: var(--INTERNAL-scrollbar-thumb-hover-color);
}

.ng-scrollbar-thumb {
Expand Down
12 changes: 8 additions & 4 deletions projects/ngx-scrollbar/src/lib/scrollbar/scrollbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ import { ScrollbarManager } from '../utils/scrollbar-manager';
standalone: true,
selector: 'scrollbar-y',
template: `
<div #sticky class="ng-scrollbar-sticky">
<div class="ng-scrollbar-track-wrapper">
<div class="ng-scrollbar-sticky"
[class.ng-scrollbar-hover]="cmp.hoverOffset()">
<div class="ng-scrollbar-track-wrapper"
[class.ng-scrollbar-hover]="!cmp.hoverOffset()">
<div scrollbarTrackY class="ng-scrollbar-track {{ cmp.trackClass }}">
<div scrollbarThumbY class="ng-scrollbar-thumb {{ cmp.thumbClass }}"></div>
</div>
Expand Down Expand Up @@ -68,8 +70,10 @@ export class ScrollbarY extends ScrollbarAdapter {
selector: 'scrollbar-x',
host: { '[attr.dir]': 'cmp.direction()' },
template: `
<div #sticky class="ng-scrollbar-sticky">
<div class="ng-scrollbar-track-wrapper">
<div class="ng-scrollbar-sticky"
[class.ng-scrollbar-hover]="cmp.hoverOffset()">
<div class="ng-scrollbar-track-wrapper"
[class.ng-scrollbar-hover]="!cmp.hoverOffset()">
<div scrollbarTrackX class="ng-scrollbar-track {{ cmp.trackClass }}">
<div scrollbarThumbX class="ng-scrollbar-thumb {{ cmp.thumbClass }}"></div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion projects/ngx-scrollbar/src/lib/scrollbar/shared.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
z-index: 100;
opacity: var(--_scrollbar-hover-opacity);
transition: var(--_scrollbar-opacity-transition);
pointer-events: var(--_scrollbar-pointer-events);
}

.ng-scrollbar-track-wrapper {
Expand All @@ -32,7 +33,6 @@
bottom: var(--_scrollbar-track-bottom);
right: var(--_scrollbar-track-right);
left: var(--_scrollbar-track-left);
pointer-events: var(--_scrollbar-pointer-events);
transition: var(--INTERNAL-scrollbar-track-wrapper-transition);
position: absolute;
overflow: hidden;
Expand Down
8 changes: 4 additions & 4 deletions projects/ngx-scrollbar/src/lib/scrollbar/vertical.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@
.ng-scrollbar-track-wrapper {
width: var(--_track-y-thickness);
flex-direction: column;
}

&:hover {
--_track-y-thickness: var(--_scrollbar-hover-thickness-px);
--_thumb-y-color: var(var(--INTERNAL-scrollbar-thumb-min-size));
}
.ng-scrollbar-hover:hover {
--_track-y-thickness: var(--_scrollbar-hover-thickness-px);
--_thumb-y-color: var(--INTERNAL-scrollbar-thumb-hover-color);
}

.ng-scrollbar-thumb {
Expand Down
3 changes: 1 addition & 2 deletions projects/ngx-scrollbar/src/lib/tests/appearance.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,8 @@ describe('Appearance [native / compact] styles', () => {

fixture = TestBed.createComponent(NgScrollbar);
component = fixture.componentInstance;
// Set scrollbar thickness to 13px

component.nativeElement.style.setProperty('--scrollbar-thickness', '5');
component.nativeElement.style.setProperty('--scrollbar-margin', '4');
component.nativeElement.style.setProperty('--scrollbar-offset', '4');
});

Expand Down
64 changes: 64 additions & 0 deletions projects/ngx-scrollbar/src/lib/tests/hover-effect.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { ComponentFixture, ComponentFixtureAutoDetect, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { firstValueFrom } from 'rxjs';
import { NgScrollbar } from 'ngx-scrollbar';
import { setDimensions } from './common-test.';

describe('Hover effect', () => {
let component: NgScrollbar;
let fixture: ComponentFixture<NgScrollbar>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [NgScrollbar],
providers: [
{ provide: ComponentFixtureAutoDetect, useValue: true }
]
}).compileComponents();

fixture = TestBed.createComponent(NgScrollbar);
component = fixture.componentInstance;
component.nativeElement.style.setProperty('--scrollbar-thickness', '5');
component.nativeElement.style.setProperty('--scrollbar-hover-thickness', '10');
component.nativeElement.style.setProperty('--scrollbar-offset', '4');
});

it('Should activate hover effect only when mouse is over the scrollbar in case [hoverOffset]="false"', async () => {
setDimensions(component, { cmpHeight: 200, cmpWidth: 200, contentHeight: 400, contentWidth: 400 });
fixture.componentRef.setInput('hoverOffset', false);
component.ngOnInit();
component.ngAfterViewInit();
await firstValueFrom(component.afterInit);

const stickyYElement: Element = fixture.debugElement.query(By.css('scrollbar-y .ng-scrollbar-sticky')).nativeElement;
const stickyXElement: Element = fixture.debugElement.query(By.css('scrollbar-x .ng-scrollbar-sticky')).nativeElement;

const trackYElement: Element = fixture.debugElement.query(By.css('scrollbar-y .ng-scrollbar-track-wrapper')).nativeElement;
const trackXElement: Element = fixture.debugElement.query(By.css('scrollbar-x .ng-scrollbar-track-wrapper')).nativeElement;

expect(stickyYElement.classList).not.toContain('ng-scrollbar-hover');
expect(stickyXElement.classList).not.toContain('ng-scrollbar-hover');
expect(trackYElement.classList).toContain('ng-scrollbar-hover');
expect(trackXElement.classList).toContain('ng-scrollbar-hover');
});

it('Should activate hover effect when mouse is over the offset area in case [hoverOffset]="true"', async () => {
setDimensions(component, { cmpHeight: 200, cmpWidth: 200, contentHeight: 400, contentWidth: 400 });
fixture.componentRef.setInput('hoverOffset', true);
component.ngOnInit();
component.ngAfterViewInit();
await firstValueFrom(component.afterInit);

const stickyYElement: Element = fixture.debugElement.query(By.css('scrollbar-y .ng-scrollbar-sticky')).nativeElement;
const stickyXElement: Element = fixture.debugElement.query(By.css('scrollbar-x .ng-scrollbar-sticky')).nativeElement;

const trackYElement: Element = fixture.debugElement.query(By.css('scrollbar-y .ng-scrollbar-track-wrapper')).nativeElement;
const trackXElement: Element = fixture.debugElement.query(By.css('scrollbar-x .ng-scrollbar-track-wrapper')).nativeElement;

expect(stickyYElement.classList).toContain('ng-scrollbar-hover');
expect(stickyXElement.classList).toContain('ng-scrollbar-hover');
expect(trackYElement.classList).not.toContain('ng-scrollbar-hover');
expect(trackXElement.classList).not.toContain('ng-scrollbar-hover');
});
});

2 changes: 1 addition & 1 deletion projects/ngx-scrollbar/src/lib/tests/visibility.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('Visibility styles', () => {
imports: [NgScrollbar],
providers: [
{ provide: ComponentFixtureAutoDetect, useValue: true }
],
]
}).compileComponents();

fixture = TestBed.createComponent(NgScrollbar);
Expand Down
1 change: 1 addition & 0 deletions projects/ngx-scrollbar/src/lib/utils/scrollbar-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface _NgScrollbar {
dragging: WritableSignal<ScrollbarDragging>;
direction: Signal<Direction>;
trackScrollDuration: number;
hoverOffset: Signal<boolean>;
buttons: Signal<boolean>;
disableSensor: Signal<boolean>;
sensorThrottleTime: Signal<number>;
Expand Down

1 comment on commit ea15b10

@github-actions
Copy link

Choose a reason for hiding this comment

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

Please sign in to comment.