Skip to content
Draft
158 changes: 40 additions & 118 deletions packages/components-dev/scrollbar/module.ts
Original file line number Diff line number Diff line change
@@ -1,140 +1,62 @@
import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';
import { KbqButtonModule } from '@koobiq/components/button';
import {
KBQ_SCROLLBAR_CONFIG,
KbqScrollbarEvents,
KbqScrollbarModule,
KbqScrollbarOptions
} from '@koobiq/components/scrollbar';
PrivateScrollbarDisableInteractionExample,
PrivateScrollbarNativeExample,
PrivateScrollbarRtlExample,
PrivateScrollbarScrollToExample,
PrivateScrollbarVirtualScrollExample,
PrivateScrollbarVisibilityExample,
ScrollbarOverviewExample,
ScrollbarScrollToTopExample,
ScrollbarWithCustomConfigExample
} from 'packages/docs-examples/components/scrollbar';
import { DevThemeToggle } from '../theme-toggle';

@Component({
selector: 'dev-scrollbar-with-options',
imports: [KbqScrollbarModule],
template: `
<h4>ScrollbarWithOptions:</h4>
<kbq-scrollbar style="width: 200px; height: 200px;" [options]="options">
@for (item of items; track item) {
<div>{{ item }}</div>
<hr />
}
</kbq-scrollbar>
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DevScrollbarWithOptions {
readonly options: KbqScrollbarOptions = {
scrollbars: {
autoHide: 'never'
}
};
readonly items = Array.from({ length: 1000 }).map((_, i) => `Item #${i}`);
}

@Component({
selector: 'dev-scrollbar-with-custom-config',
imports: [KbqScrollbarModule],
template: `
<h4>ScrollbarWithCustomConfig:</h4>
<div kbq-scrollbar style="width: 200px; height: 200px;">
@for (item of items; track item) {
<div>{{ item }}</div>
<hr />
}
</div>
`,
providers: [
{
provide: KBQ_SCROLLBAR_CONFIG,
useValue: {
scrollbars: {
autoHide: 'never'
}
} satisfies KbqScrollbarOptions
}
],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DevScrollbarWithCustomConfig {
readonly items = Array.from({ length: 1000 }).map((_, i) => `Item #${i}`);
}

@Component({
selector: 'dev-scrollbar-scroll-to-top',
selector: 'dev-examples',
imports: [
KbqScrollbarModule,
KbqButtonModule
PrivateScrollbarVisibilityExample,
PrivateScrollbarVirtualScrollExample,
PrivateScrollbarScrollToExample,
PrivateScrollbarRtlExample,
PrivateScrollbarNativeExample,
PrivateScrollbarDisableInteractionExample,
ScrollbarOverviewExample,
ScrollbarScrollToTopExample,
ScrollbarWithCustomConfigExample
],
template: `
<h4>ScrollbarScrollToTop:</h4>
<kbq-scrollbar #scrollbarRef="kbqScrollbar" style="width: 200px; height: 200px;" (onScroll)="onScroll($event)">
@for (item of items; track item) {
<div>{{ item }}</div>
<hr />
}
</kbq-scrollbar>
<button
kbq-button
[disabled]="!(scrollbarRef?.contentElement()?.nativeElement?.scrollTop || 0 > 0)"
(click)="scrollbarRef.scrollTo({ top: 0, behavior: 'smooth' })"
>
Scroll To Top
</button>
<private-scrollbar-visibility-example />
<hr />
<private-scrollbar-virtual-scroll-example />
<hr />
<private-scrollbar-scroll-to-example />
<hr />
<private-scrollbar-rtl-example />
<hr />
<private-scrollbar-native-example />
<hr />
<private-scrollbar-disable-interaction-example />
<hr />
<scrollbar-overview-example />
<hr />
<scrollbar-scroll-to-top-example />
<hr />
<scrollbar-with-custom-config-example />
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DevScrollbarScrollToTop {
readonly items = Array.from({ length: 1000 }).map((_, i) => `Item #${i}`);

onScroll(event): void {
console.log('onScroll', event);
}
}
export class DevDocsExamples {}

@Component({
selector: 'dev-app',
imports: [
KbqScrollbarModule,
KbqButtonModule,
// components
DevScrollbarWithOptions,
DevScrollbarWithCustomConfig,
DevScrollbarScrollToTop,
DevDocsExamples,
DevThemeToggle
],
templateUrl: './template.html',
styleUrl: './styles.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None
})
export class DevApp {
options: KbqScrollbarOptions;
events: KbqScrollbarEvents = {
initialized: (...args) => this.onInitialize(args)
};

onScroll([instance, args]) {
console.log('onScroll', instance, args);
}

onInitialize($event) {
console.log($event);
}

longText: string = `Vivamus suscipit tortor eget felis porttitor volutpat. Vivamus magna justo, lacinia eget consectetur sed, convallis at tellus. Quisque velit nisi, pretium ut lacinia in, elementum id enim. Pellentesque in ipsum id orci porta dapibus. Curabitur arcu erat, accumsan id imperdiet et, porttitor at sem. Donec sollicitudin molestie malesuada. Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ac diam sit amet quam vehicula elementum sed sit amet dui.
Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec velit neque, auctor sit amet aliquam vel, ullamcorper sit amet ligula. Nulla porttitor accumsan tincidunt. Nulla quis lorem ut libero malesuada feugiat. Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Pellentesque in ipsum id orci porta dapibus. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Donec rutrum congue leo eget malesuada.
Proin eget tortor risus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ac diam sit amet quam vehicula elementum sed sit amet dui. Donec sollicitudin molestie malesuada. Pellentesque in ipsum id orci porta dapibus. Curabitur aliquet quam id dui posuere blandit. Vestibulum ac diam sit amet quam vehicula elementum sed sit amet dui. Curabitur arcu erat, accumsan id imperdiet et, porttitor at sem. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed porttitor lectus nibh.
Donec sollicitudin molestie malesuada. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Curabitur arcu erat, accumsan id imperdiet et, porttitor at sem. Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Vivamus suscipit tortor eget felis porttitor volutpat. Nulla quis lorem ut libero malesuada feugiat. Curabitur aliquet quam id dui posuere blandit. Donec sollicitudin molestie malesuada. Quisque velit nisi, pretium ut lacinia in, elementum id enim. Donec sollicitudin molestie malesuada.
Proin eget tortor risus. Vivamus magna justo, lacinia eget consectetur sed, convallis at tellus. Cras ultricies ligula sed magna dictum porta. Cras ultricies ligula sed magna dictum porta. Cras ultricies ligula sed magna dictum porta. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin eget tortor risus. Proin eget tortor risus. Curabitur arcu erat, accumsan id imperdiet et, porttitor at sem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec velit neque, auctor sit amet aliquam vel, ullamcorper sit amet ligula.
Vivamus suscipit tortor eget felis porttitor volutpat. Vivamus magna justo, lacinia eget consectetur sed, convallis at tellus. Quisque velit nisi, pretium ut lacinia in, elementum id enim. Pellentesque in ipsum id orci porta dapibus. Curabitur arcu erat, accumsan id imperdiet et, porttitor at sem. Donec sollicitudin molestie malesuada. Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ac diam sit amet quam vehicula elementum sed sit amet dui.
Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec velit neque, auctor sit amet aliquam vel, ullamcorper sit amet ligula. Nulla porttitor accumsan tincidunt. Nulla quis lorem ut libero malesuada feugiat. Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Pellentesque in ipsum id orci porta dapibus. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Donec rutrum congue leo eget malesuada.
Proin eget tortor risus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ac diam sit amet quam vehicula elementum sed sit amet dui. Donec sollicitudin molestie malesuada. Pellentesque in ipsum id orci porta dapibus. Curabitur aliquet quam id dui posuere blandit. Vestibulum ac diam sit amet quam vehicula elementum sed sit amet dui. Curabitur arcu erat, accumsan id imperdiet et, porttitor at sem. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed porttitor lectus nibh.
Donec sollicitudin molestie malesuada. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Curabitur arcu erat, accumsan id imperdiet et, porttitor at sem. Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Vivamus suscipit tortor eget felis porttitor volutpat. Nulla quis lorem ut libero malesuada feugiat. Curabitur aliquet quam id dui posuere blandit. Donec sollicitudin molestie malesuada. Quisque velit nisi, pretium ut lacinia in, elementum id enim. Donec sollicitudin molestie malesuada.
Proin eget tortor risus. Vivamus magna justo, lacinia eget consectetur sed, convallis at tellus. Cras ultricies ligula sed magna dictum porta. Cras ultricies ligula sed magna dictum porta. Cras ultricies ligula sed magna dictum porta. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin eget tortor risus. Proin eget tortor risus. Curabitur arcu erat, accumsan id imperdiet et, porttitor at sem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec velit neque, auctor sit amet aliquam vel, ullamcorper sit amet ligula.
Vivamus suscipit tortor eget felis porttitor volutpat. Vivamus magna justo, lacinia eget consectetur sed, convallis at tellus. Quisque velit nisi, pretium ut lacinia in, elementum id enim. Pellentesque in ipsum id orci porta dapibus. Curabitur arcu erat, accumsan id imperdiet et, porttitor at sem. Donec sollicitudin molestie malesuada. Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ac diam sit amet quam vehicula elementum sed sit amet dui.
Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec velit neque, auctor sit amet aliquam vel, ullamcorper sit amet ligula. Nulla porttitor accumsan tincidunt. Nulla quis lorem ut libero malesuada feugiat. Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Pellentesque in ipsum id orci porta dapibus. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Donec rutrum congue leo eget malesuada.
Proin eget tortor risus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ac diam sit amet quam vehicula elementum sed sit amet dui. Donec sollicitudin molestie malesuada. Pellentesque in ipsum id orci porta dapibus. Curabitur aliquet quam id dui posuere blandit. Vestibulum ac diam sit amet quam vehicula elementum sed sit amet dui. Curabitur arcu erat, accumsan id imperdiet et, porttitor at sem. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed porttitor lectus nibh.
Donec sollicitudin molestie malesuada. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Curabitur arcu erat, accumsan id imperdiet et, porttitor at sem. Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Vivamus suscipit tortor eget felis porttitor volutpat. Nulla quis lorem ut libero malesuada feugiat. Curabitur aliquet quam id dui posuere blandit. Donec sollicitudin molestie malesuada. Quisque velit nisi, pretium ut lacinia in, elementum id enim. Donec sollicitudin molestie malesuada.
Proin eget tortor risus. Vivamus magna justo, lacinia eget consectetur sed, convallis at tellus. Cras ultricies ligula sed magna dictum porta. Cras ultricies ligula sed magna dictum porta. Cras ultricies ligula sed magna dictum porta. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin eget tortor risus. Proin eget tortor risus. Curabitur arcu erat, accumsan id imperdiet et, porttitor at sem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec velit neque, auctor sit amet aliquam vel, ullamcorper sit amet ligula.
`;
}
export class DevApp {}
29 changes: 2 additions & 27 deletions packages/components-dev/scrollbar/styles.scss
Original file line number Diff line number Diff line change
@@ -1,29 +1,4 @@
.dev-container {
padding: 24px;
}

textarea {
margin: 10px;
dev-app {
max-width: 608px;
display: block;
}

.dev-with-horizontal {
white-space: nowrap;
overflow-x: visible;
}

.dev-with-buttons {
white-space: nowrap;
overflow: visible;
}

.dev-nested-scroll {
width: 200px;
height: 200px;
overflow: auto;
margin: 10px;
}

.dev-nested-scroll__content {
width: 800px;
}
60 changes: 1 addition & 59 deletions packages/components-dev/scrollbar/template.html
Original file line number Diff line number Diff line change
@@ -1,63 +1,5 @@
<dev-theme-toggle />

<dev-scrollbar-with-options />
<hr />

<dev-scrollbar-with-custom-config />
<hr />

<dev-scrollbar-scroll-to-top />
<hr />

<div class="dev-container kbq-text-big">
<div class="layout-row layout-align-space-between">
<div>
<h2>Simple Scrollbar Component</h2>

<h4>Simple example</h4>
<div
kbq-scrollbar
style="height: 300px; max-width: 200px"
[events]="events"
[options]="options"
(onScroll)="onScroll($event)"
>
<div style="width: 400px">{{ longText }}</div>
</div>

<div dir="rtl">
<h4>Bidi support</h4>
<div kbq-scrollbar style="height: 300px; max-width: 400px" (onScroll)="onScroll($event)">
<div style="width: 400px">{{ longText }}</div>
</div>
</div>
</div>

<div>
<h2>Scrollbar Via CSS</h2>

<h3>Horizontal</h3>
<textarea
style="height: 300px; width: 400px; overflow-y: auto; resize: none"
class="kbq-scrollbar dev-with-horizontal"
>{{ longText }}</textarea>

<h3>Buttons & Resize corner</h3>
<textarea style="height: 300px; width: 400px; overflow-y: auto" class="kbq-scrollbar dev-with-buttons">{{
longText
}}</textarea>

<h3>Nested scroll — class on wrapper</h3>
<div class="kbq-scrollbar">
<div class="dev-nested-scroll">
<div class="dev-nested-scroll__content">{{ longText }}</div>
</div>
</div>

<h3>Nested scroll — class on scroller (reference)</h3>
<div class="dev-nested-scroll kbq-scrollbar">
<div class="dev-nested-scroll__content">{{ longText }}</div>
</div>
</div>
</div>
</div>
<dev-examples />
13 changes: 0 additions & 13 deletions packages/components/content-panel/content-panel.en.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,5 @@
`KbqContentPanel` - a slide-out side panel that shifts adjacent content. Often used to implement a quick preview mode for entities from a table.

<div class="kbq-callout kbq-callout_theme">
<div class="kbq-callout__header">Note</div>
<div class="kbq-callout__content kbq-docs-element-last-child-margin-bottom-0">

The component uses [Scrollbar](/en/components/scrollbar), so its dependencies must be installed:

```bash
npm install overlayscrollbars@2.7.3
```

</div>
</div>

<!-- example(content-panel-overview) -->

### Grid and content-panel
Expand Down
13 changes: 0 additions & 13 deletions packages/components/content-panel/content-panel.ru.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,5 @@
`KbqContentPanel` - выезжающая сбоку панель, которая сдвигает соседний контент. Часто используется, чтобы реализовать режим быстрого просмотра сущности из таблицы.

<div class="kbq-callout kbq-callout_theme">
<div class="kbq-callout__header">Обрати внимание</div>
<div class="kbq-callout__content kbq-docs-element-last-child-margin-bottom-0">

Компонент использует [Scrollbar](/ru/components/scrollbar), поэтому необходимо установить его зависимости:

```bash
npm install overlayscrollbars@2.7.3
```

</div>
</div>

<!-- example(content-panel-overview) -->

### Грид и контент-панель
Expand Down
20 changes: 12 additions & 8 deletions packages/components/content-panel/content-panel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
} from '@koobiq/components/core';
import { KbqIconModule } from '@koobiq/components/icon';
import { KbqResizable, KbqResizer, KbqResizerSizeChangeEvent } from '@koobiq/components/resizer';
import { KbqScrollbar, KbqScrollbarModule } from '@koobiq/components/scrollbar';
import { KbqScrollbar } from '@koobiq/components/scrollbar/private';
import { SizeL } from '@koobiq/design-tokens';

const KBQ_CONTENT_PANEL_CONTAINER_CONTENT_ANIMATION = trigger('contentAnimation', [
Expand Down Expand Up @@ -139,15 +139,16 @@ export class KbqContentPanelHeader {

@Component({
selector: 'kbq-content-panel-body',
imports: [KbqScrollbarModule, KbqOverflowShadowContainer],
imports: [KbqScrollbar, KbqOverflowShadowContainer],
template: `
<kbq-scrollbar
<div
#overflowContainer="kbqOverflowShadowContainer"
kbqOverflowShadowContainer
kbqScrollbar
class="kbq-content-panel-body__content"
>
<ng-content />
</kbq-scrollbar>
</div>
`,
styleUrl: './content-panel-body.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
Expand Down Expand Up @@ -206,19 +207,22 @@ export class KbqContentPanelFooter {
export class KbqContentPanel {
private readonly contentPanelBody = contentChild(KbqContentPanelBody);

/** Current body overflow state. Read by the header and footer to render their `box-shadow`. */
/**
* Current body overflow state. Read by the header and footer to render their `box-shadow`.
* @docs-private
*/
readonly bodyOverflow = computed(
() => this.contentPanelBody()?.overflowContainer().overflow() ?? { top: false, bottom: false }
);
}

@Component({
selector: 'kbq-content-panel-container',
imports: [KbqResizable, KbqResizer, KbqScrollbarModule],
imports: [KbqResizable, KbqResizer, KbqScrollbar],
template: `
<kbq-scrollbar class="kbq-content-panel-container__content" [@contentAnimation]="contentAnimationState()">
<div kbqScrollbar class="kbq-content-panel-container__content" [@contentAnimation]="contentAnimationState()">
<ng-content />
</kbq-scrollbar>
</div>
@if (openedState()) {
<div
@panelAnimation
Expand Down
Loading