Skip to content

Commit e812c7b

Browse files
committed
Created component, styling and template for v1.0.0
0 parents  commit e812c7b

11 files changed

+393
-0
lines changed

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 Omnedia
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+151
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
# ngx-scrollbar
2+
3+
`@omnedia/ngx-scrollbar` is an Angular library that provides a customizable and lightweight scrollbar component. This component offers a custom scrollbar with smooth scrolling functionality and allows for full control over its appearance through styling.
4+
5+
## Features
6+
7+
- Custom scrollbar for the y-Direction with adjustable styles and behavior.
8+
- Smooth scrolling with click-and-drag functionality.
9+
- Easily integratable into Angular projects as a standalone component.
10+
- Allows for styling customization via CSS classes and inline styles.
11+
12+
## Installation
13+
14+
Install the library using npm:
15+
16+
```bash
17+
npm install @omnedia/ngx-scrollbar
18+
```
19+
20+
## Usage
21+
22+
Import the `NgxScrollbarComponent` in your Angular module or component:
23+
24+
```typescript
25+
import { NgxScrollbarComponent } from '@omnedia/ngx-scrollbar';
26+
27+
@Component({
28+
...
29+
imports: [
30+
...
31+
NgxScrollbarComponent,
32+
],
33+
...
34+
})
35+
```
36+
37+
Use the component in your template:
38+
39+
```html
40+
<om-scrollbar [styleClass]="'custom-scrollbar'">
41+
<div>
42+
<!-- Your scrollable content here -->
43+
<p>Scrollable content 1</p>
44+
<p>Scrollable content 2</p>
45+
<p>Scrollable content 3</p>
46+
</div>
47+
</om-scrollbar>
48+
```
49+
50+
## How It Works
51+
52+
- Custom Scrollbar: The ngx-scrollbar component wraps your content inside a custom scrollbar container. The appearance of the scrollbar can be controlled via the styleClass input, allowing for full customization.
53+
- Smooth Scrolling: The scrollbar supports smooth scrolling, and users can drag the scrollbar for precise control.
54+
- Dynamic Calculation: The size of the scrollbar is calculated based on the content height relative to the container.
55+
56+
## API
57+
58+
```html
59+
<om-scrollbar [styleClass]="'your-custom-class'">
60+
<ng-content></ng-content>
61+
</om-scrollbar>
62+
```
63+
64+
- styleClass (optional): A custom CSS class to apply to the scrollbar component for additional styling.
65+
66+
## Example
67+
68+
```html
69+
<om-scrollbar [styleClass]="'custom-scrollbar-style'">
70+
<div>
71+
<p>Item 1</p>
72+
<p>Item 2</p>
73+
<p>Item 3</p>
74+
<!-- Add more content here -->
75+
</div>
76+
</om-scrollbar>
77+
```
78+
79+
This will create a custom scrollbar for the content with the specified custom styles.
80+
81+
## Styling
82+
83+
You can style the component globally or use the styleClass input to apply your custom styles. <br>
84+
Make sure to give the `om-scrollbar` component a height of 100% in your component. <br>
85+
The `max-height` is defined by the components parent component.
86+
87+
## Custom Scrollbar Styling Example
88+
89+
In this example, the scrollbar bar is styled to be larger and colored differently:
90+
91+
```html
92+
<div class="nav-bar">
93+
<om-scrollbar styleClass="custom-scrollbar">
94+
<div class="nav-items">
95+
<p>Content</p>
96+
<p>Content</p>
97+
<p>Content</p>
98+
<p>Content</p>
99+
<p>Content</p>
100+
<p>Content</p>
101+
<p>Content</p>
102+
<p>Content</p>
103+
<p>Content</p>
104+
</div>
105+
</om-scrollbar>
106+
</div>
107+
```
108+
109+
```css
110+
/* Component styling */
111+
om-scrollbar {
112+
height: 100%;
113+
}
114+
115+
.nav-bar {
116+
height: 500px
117+
}
118+
119+
.nav-items {
120+
display: flex;
121+
flex-direction: column;
122+
gap: 1rem;
123+
font-size: 2rem;
124+
}
125+
126+
127+
/* Global styling */
128+
.custom-scrollbar.om-scrollbar-bar {
129+
background-color: #ff6347; /* Tomato color for the scrollbar */
130+
width: 0.75rem;
131+
border-radius: 12px;
132+
opacity: 0.7;
133+
transition: opacity 0.2s;
134+
}
135+
136+
.custom-scrollbar .om-scrollbar-bar:hover {
137+
opacity: 1; /* While hovering */
138+
}
139+
140+
.custom-scrollbar .om-scrollbar.om-scrollbar-bar-active {
141+
opacity 1; /* While dragging */
142+
}
143+
```
144+
145+
## Contributing
146+
147+
Contributions are welcome. Please submit a pull request or open an issue to discuss your ideas.
148+
149+
## License
150+
151+
This project is licensed under the MIT License.

ng-package.json

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3+
"dest": "../../dist/ngx-scrollbar",
4+
"lib": {
5+
"entryFile": "src/public-api.ts"
6+
}
7+
}

package.json

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"name": "@omnedia/ngx-scrollbar",
3+
"description": "A simple component library to create a custom scrollbar for the Y-Direction. ",
4+
"version": "1.0.0",
5+
"peerDependencies": {
6+
"@angular/common": "^18.2.0",
7+
"@angular/core": "^18.2.0"
8+
},
9+
"dependencies": {
10+
"tslib": "^2.3.0"
11+
},
12+
"sideEffects": false,
13+
"keywords": [
14+
"npm",
15+
"scrollbar",
16+
"y",
17+
"direction",
18+
"custom"
19+
],
20+
"repository": {
21+
"url": "https://github.com/omnedia/ngx-scrollbar"
22+
},
23+
"author": "Markus Block (markus.block@omnedia.com)",
24+
"license": "MIT"
25+
}

src/lib/ngx-scrollbar.component.html

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<div class="om-scrollbar" [ngStyle]="style" #OmScrollbarContainer>
2+
<div class="om-scrollbar-wrapper" (scroll)="onScroll($event)" #OmScrollbarWrapper>
3+
<div class="om-scrollbar-content" #OmScrollbarContent>
4+
<ng-content></ng-content>
5+
</div>
6+
</div>
7+
8+
<div class="om-scrollbar-bar" [class.om-scrollbar-bar-active]="mouseDown" [ngClass]="styleClass" #OmScrollbar>
9+
</div>
10+
</div>

src/lib/ngx-scrollbar.component.scss

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
.om-scrollbar {
2+
--om-scrollbar-height: 0;
3+
--om-scrollbar-top: 0;
4+
--om-scrollbar-hover-display: block;
5+
position: relative;
6+
7+
height: 100%;
8+
9+
.om-scrollbar-bar {
10+
position: absolute;
11+
display: var(--om-scrollbar-hover-display);
12+
width: 0.625rem;
13+
height: var(--om-scrollbar-height);
14+
top: var(--om-scrollbar-top);
15+
background-color: grey;
16+
right: -1.5rem;
17+
border-radius: 10px;
18+
transition: opacity 0.2;
19+
20+
&:hover,
21+
&.om-scrollbar-bar-active {
22+
opacity: 0.9;
23+
}
24+
}
25+
26+
&:hover > .sidebar-scrollbar {
27+
display: block;
28+
}
29+
30+
.om-scrollbar-wrapper {
31+
overflow-y: auto;
32+
height: 100%;
33+
34+
scrollbar-width: none;
35+
36+
&::-webkit-scrollbar {
37+
display: none;
38+
}
39+
}
40+
41+
.om-scrollbar-content {
42+
height: fit-content;
43+
}
44+
}

src/lib/ngx-scrollbar.component.ts

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { CommonModule } from '@angular/common';
2+
import { AfterViewInit, Component, ElementRef, HostListener, Input, ViewChild } from '@angular/core';
3+
4+
@Component({
5+
selector: 'om-scrollbar',
6+
standalone: true,
7+
imports: [CommonModule],
8+
templateUrl: "./ngx-scrollbar.component.html",
9+
styleUrl: "./ngx-scrollbar.component.scss",
10+
})
11+
export class NgxScrollbarComponent implements AfterViewInit {
12+
@ViewChild('OmScrollbarContainer') sidebarRef!: ElementRef<HTMLElement>;
13+
@ViewChild('OmScrollbarWrapper') wrapperRef!: ElementRef<HTMLElement>;
14+
@ViewChild('OmScrollbarContent') contentRef!: ElementRef<HTMLElement>;
15+
@ViewChild('OmScrollbar') scrollbarRef!: ElementRef<HTMLElement>;
16+
17+
@Input('styleClass')
18+
styleClass?: string;
19+
20+
style: any = {};
21+
22+
private scrollPercent = 0;
23+
mouseDown = false;
24+
private lastY?: number;
25+
26+
@HostListener('mousedown', ['$event'])
27+
onMouseDown(event: MouseEvent) {
28+
const target = event.target as HTMLElement;
29+
30+
if (target.classList.contains('om-scrollbar-bar')) {
31+
event.preventDefault();
32+
this.mouseDown = true;
33+
}
34+
}
35+
36+
@HostListener('mouseup')
37+
onMouseUp() {
38+
this.lastY = undefined;
39+
this.mouseDown = false;
40+
}
41+
42+
ngAfterViewInit(): void {
43+
window.addEventListener('mouseup', () => {
44+
this.lastY = undefined;
45+
this.mouseDown = false;
46+
});
47+
window.addEventListener('mousemove', (event) => this.onDrag(event));
48+
49+
this.calcScrollbar();
50+
}
51+
52+
calcScrollbar(): void {
53+
const sideBarHeight = this.sidebarRef.nativeElement.clientHeight;
54+
const contentHeight = this.contentRef.nativeElement.clientHeight;
55+
const scrollBarHeight = Math.floor(sideBarHeight / contentHeight * 100);
56+
57+
this.style['--om-scrollbar-height'] = `${scrollBarHeight}%`;
58+
}
59+
60+
onScroll(event: Event): void {
61+
const target = event.target as HTMLElement;
62+
const contentHeight = this.contentRef.nativeElement.clientHeight;
63+
const scrollTop = target.scrollTop;
64+
65+
this.scrollPercent = Math.floor(scrollTop / contentHeight * 100);
66+
67+
this.style['--om-scrollbar-top'] = `${this.scrollPercent}%`;
68+
}
69+
70+
onDrag(event: MouseEvent): void {
71+
if (!this.mouseDown) {
72+
return;
73+
}
74+
75+
event.preventDefault();
76+
77+
const offsetY = event.clientY;
78+
79+
const scrollPx = offsetY - (this.lastY ?? offsetY);
80+
this.lastY = offsetY;
81+
82+
const contentHeight = this.sidebarRef.nativeElement.clientHeight;
83+
const scrollPercent = (scrollPx) / (contentHeight);
84+
85+
const scrollContentPx = this.contentRef.nativeElement.clientHeight * scrollPercent;
86+
87+
this.wrapperRef.nativeElement.scrollBy(0, scrollContentPx);
88+
}
89+
}

src/public-api.ts

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/*
2+
* Public API Surface of ngx-scrollbar
3+
*/
4+
5+
export * from './lib/ngx-scrollbar.component';

tsconfig.lib.json

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
2+
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
3+
{
4+
"extends": "../../tsconfig.json",
5+
"compilerOptions": {
6+
"outDir": "../../out-tsc/lib",
7+
"declaration": true,
8+
"declarationMap": true,
9+
"inlineSources": true,
10+
"types": []
11+
},
12+
"exclude": [
13+
"**/*.spec.ts"
14+
]
15+
}

tsconfig.lib.prod.json

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
2+
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
3+
{
4+
"extends": "./tsconfig.lib.json",
5+
"compilerOptions": {
6+
"declarationMap": false
7+
},
8+
"angularCompilerOptions": {
9+
"compilationMode": "partial"
10+
}
11+
}

0 commit comments

Comments
 (0)