Skip to content

feat(top-bar): updated docs examples (#DS-3487) #600

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

Merged
merged 15 commits into from
Apr 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
border-radius: inherit;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
background: var(--docs-live-example-example-background);
}

.docs-live-example-viewer {
Expand Down
4 changes: 2 additions & 2 deletions apps/docs/src/app/services/documentation-items.ts
Original file line number Diff line number Diff line change
Expand Up @@ -696,8 +696,8 @@ const DOCS: { [key: string]: DocCategory[] } = {
{
id: 'top-bar',
name: {
ru: 'Top Bar',
en: 'Top Bar'
ru: 'Topbar',
en: 'Topbar'
},
svgPreview: 'top-bar',
hasApi: true,
Expand Down
12 changes: 12 additions & 0 deletions apps/docs/src/assets/example-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions apps/docs/src/assets/stackblitz/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { provideHttpClient } from '@angular/common/http';
import { bootstrapApplication } from '@angular/platform-browser';
import { provideAnimations } from '@angular/platform-browser/animations';
import { provideRouter } from '@angular/router';
import { KBQ_LOCALE_SERVICE, KbqLocaleService } from '@koobiq/components/core';
import { KoobiqDocsExample } from './example/koobiq-docs-example';

bootstrapApplication(KoobiqDocsExample, {
providers: [
provideAnimations(),
provideHttpClient(),
provideRouter([]),
{ provide: KBQ_LOCALE_SERVICE, useClass: KbqLocaleService }]
}).catch((err) => console.error(err));
13 changes: 11 additions & 2 deletions apps/docs/src/styles/_examples.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
.docs-live-example__example_breadcrumbs-with-auto-wrap-adaptive {
background: var(--kbq-background-bg-secondary);
.docs-live-example__example {
&.docs-live-example__example_top-bar-overflow,
&.docs-live-example__example_top-bar-breadcrumbs-adaptive,
&.docs-live-example__example_top-bar-title-counter-adaptive,
&.docs-live-example__example_breadcrumbs-with-auto-wrap-adaptive {
--docs-live-example-example-background: var(--kbq-background-bg-secondary);
}

&.docs-live-example__example_top-bar-overflow {
padding: var(--kbq-size-3xl);
}
}
2 changes: 2 additions & 0 deletions packages/components-dev/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

@use '../components/core/styles/visual/layout';

@use '../components/core/styles/common/list';

@use '../../apps/docs/src/styles/koobiq/default-theme/css-tokens.css';
@use '../../apps/docs/src/styles/koobiq/default-theme/css-tokens-light.css';
@use '../../apps/docs/src/styles/koobiq/default-theme/css-tokens-dark.css';
Expand Down
6 changes: 5 additions & 1 deletion packages/components-dev/top-bar/module.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';
import { KbqLocaleServiceModule } from '@koobiq/components/core';
import { TopBarExamplesModule } from '../../docs-examples/components/top-bar';
import { DevLocaleSelector } from '../locale-selector';

@Component({
standalone: true,
Expand All @@ -8,7 +10,9 @@ import { TopBarExamplesModule } from '../../docs-examples/components/top-bar';
encapsulation: ViewEncapsulation.None,
templateUrl: './template.html',
imports: [
TopBarExamplesModule
TopBarExamplesModule,
DevLocaleSelector,
KbqLocaleServiceModule
],
changeDetection: ChangeDetectionStrategy.OnPush
})
Expand Down
3 changes: 2 additions & 1 deletion packages/components-dev/top-bar/template.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<div class="app-shell-dev">
<aside class="app-sidebar-dev">app-sidebar</aside>
<top-bar-active-breadcrumb-example class="app-container-dev layout-column flex" />
<dev-locale-selector />
<top-bar-breadcrumbs-example class="app-container-dev layout-column flex" />
</div>
7 changes: 4 additions & 3 deletions packages/components/top-bar/top-bar-tokens.scss
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
.kbq-top-bar {
:where(.kbq-top-bar) {
--kbq-top-bar-position: sticky;
--kbq-top-bar-background: var(--kbq-background-bg);
--kbq-top-bar-spacer-min-width: 80px;
--kbq-top-bar-padding-vertical: var(--kbq-size-xl);
--kbq-top-bar-padding-horizontal: var(--kbq-size-xxl);
--kbq-top-bar-border-radius: 0;
--kbq-top-bar-left-gap: 0;
--kbq-top-bar-right-gap: var(--kbq-size-s);
--kbq-top-bar-container-start-gap: 0;
--kbq-top-bar-container-start-basis: 0;
--kbq-top-bar-container-end-gap: var(--kbq-size-s);
--kbq-top-bar-shadow-bottom: var(--kbq-shadow-overflow-normal-bottom);
--kbq-top-bar-shadow-transition: ease-out 300ms;
}
60 changes: 37 additions & 23 deletions packages/components/top-bar/top-bar.en.md
Original file line number Diff line number Diff line change
@@ -1,46 +1,60 @@
The `Top Bar` is a toolbar that remains visible on the page at all times, providing quick access to navigation and
controls. Depending on the interface requirements, it can include breadcrumbs, a title, action buttons, and other
elements. Below are various ways to use the toolbar and recommendations for adapting it to different scenarios.
Topbar is a toolbar that always remains visible on the page and provides quick access to navigation and controls.

<!-- example(top-bar-overview) -->

Depending on the interface requirements, it may include a logo, a title, breadcrumbs, action buttons, and other elements.

### Page title

This content option is suitable for initial screens when there is no need to display the navigation path.

<!-- example(top-bar-overview) -->

If you need to display the number of objects on the current page, you can do so by showing a special counter next to the page title:

<!-- example(top-bar-title-counter) -->

### Breadcrumbs

Use breadcrumbs to display the navigation path. This panel is always visible and helps users navigate the application.
For internal pages of a specific module, using [Breadcrumbs](/en/components/breadcrumbs) is an excellent option. This helps users navigate the application more easily.

<!-- example(top-bar-breadcrumbs) -->

### Replacing Breadcrumbs with a Title
### Action buttons

For a more compact layout, replace breadcrumbs with a title that reflects the current section.
On the right side of the toolbar, there is a dedicated area for placing any actions that need to be displayed on the current page.

<!-- example(top-bar-overview) -->
We recommend using the following set of actions (from left to right):

- Indicators (e.g., data refresh indicator)
- A group of icon buttons (e.g., filters)
- Frequently used actions as buttons (e.g., "Add...", "Share")
- Additional actions in a dropdown menu, where all secondary actions related to the current page can be placed.

### Active Breadcrumb Display
<!-- example(top-bar-actions) -->

The last breadcrumb in the navigation is always active and can be used for various actions.
### Responsive mode

<!-- example(top-bar-active-breadcrumb) -->
Internal elements can adjust to the toolbar size.

### Additional Actions
The minimum allowed spacing between the left side and the right side with actions is **80px** and is defined using the CSS variable `--kbq-top-bar-spacer-min-width`.

Additional (secondary) actions are placed in a dropdown menu for better UI convenience.
#### Breadcrumbs variant

<!-- example(top-bar-secondary-actions) -->
When the panel is compressed, the breadcrumbs will adjust as follows:

### Responsive Behavior
<!-- example(top-bar-breadcrumbs-adaptive) -->

Additional actions can be moved into the dropdown menu as the screen width decreases, ensuring a seamless user experience across different devices.
A more detailed explanation of breadcrumb compression is provided on the [Breadcrumbs](/en/components/breadcrumbs) page.

<!-- example(top-bar-secondary-actions-responsive) -->
#### Page title variant

### Minimum Spacing Between Elements
The variant using only the page title will adjust as follows:

<!-- cspell:ignore Dashbo -->
<!-- example(top-bar-title-counter-adaptive) -->

To ensure usability:
#### Scroll behavior

- Hide button text when the screen width decreases.
- Show a tooltip with the button text on hover.
- Maintain a minimum spacing of **80px**, set via `--kbq-top-bar-spacer-min-width`. It applies to Top Bar elements, including the header.
- If a long title does not fit, truncate it with an ellipsis (**"Dashbo..."**).
The toolbar can remain fixed while scrolling the page.

<!-- example(top-bar-overflow) -->
64 changes: 38 additions & 26 deletions packages/components/top-bar/top-bar.ru.md
Original file line number Diff line number Diff line change
@@ -1,49 +1,61 @@
`Top Bar` — это панель инструментов, которая всегда остается видимой на странице и обеспечивает быстрый доступ к
навигации
и управлению. В зависимости от требований интерфейса, она может включать хлебные крошки, заголовок, кнопки действий и
другие элементы. Ниже представлены различные варианты использования toolbar и рекомендации по его адаптации под разные
сценарии.
Topbar — это панель инструментов, которая всегда остается видимой на странице и обеспечивает быстрый доступ к
навигации и управлению.

<!-- example(top-bar-overview) -->

В зависимости от требований интерфейса, она может включать логотип, заголовок, хлебные крошки, кнопки действий и другие элементы.

### Заголовок страницы

Данный вариант наполнения подходит для начальных экранов, когда отсутствует необходимость в отображении навигационного пути.

<!-- example(top-bar-overview) -->

Если необходимо вывести количество объектов на текущей странице, то это можно сделать с помощью отображения рядом с заголовком страницы специального счетчика:

<!-- example(top-bar-title-counter) -->

### Хлебные крошки

Используйте хлебные крошки для отображения пути навигации. Эта панель всегда видна и помогает пользователю
ориентироваться в приложении.
Для внутренних страниц отдельного модуля отлично подойдет вариант с [хлебными крошками](/ru/components/breadcrumbs). 
Это поможет пользователю легче ориентироваться в приложении.

<!-- example(top-bar-breadcrumbs) -->

### Замена хлебных крошек заголовком
### Кнопки действий

Если требуется более компактное представление, замените хлебные крошки заголовком, отображающим текущий раздел.
В правой части панели инструментов располагается область для размещения любых действий, которые необходимо отобразить на текущей странице.

<!-- example(top-bar-overview) -->
Мы рекомендуем использовать следующий набор действий (слева направо):

- Индикаторы (например, индикатор обновления данных)
- Группа кнопок-иконок (фильтры)
- Частые действия в виде кнопок (например, «Добавить…», «Поделиться»)
- Дополнительные действия в виде дропдаун меню, куда можно отнести все второстепенные действия относящиеся к текущей странице.

### Отображение активной крошки
<!-- example(top-bar-actions) -->

Последняя крошка в навигации всегда активна и может использоваться для различных действий.
### Адаптивный режим

<!-- example(top-bar-active-breadcrumb) -->
Внутренние элементы могут подстраиваться под размер панели.

### Дополнительные действия
Допустимое минимальное расстояние между левой частью и правой частью с действиями составляет **80px** и задается через CSS-переменную `--kbq-top-bar-spacer-min-width`.

Дополнительные (второстепенные) действия выносятся в выпадающее меню.
#### Вариант с хлебными крошками

<!-- example(top-bar-secondary-actions) -->
При сжатии панели хлебные крошки будут перестраиваться следующим образом:

#### Адаптивное поведение
<!-- example(top-bar-breadcrumbs-adaptive) -->

Дополнительные действия могут скрываться в выпадающее меню при уменьшении ширины экрана, обеспечивая удобную навигацию на разных устройствах.
#### Вариант с заголовком страницы

<!-- example(top-bar-secondary-actions-responsive) -->
Вариант с использованием только заголовка будет перестраиваться следующим образом:

### Минимальный отступ между элементами
<!-- example(top-bar-title-counter-adaptive) -->

<!-- cspell:ignore Дашбо -->
Более подробно сжатие хлебных крошек разобрано на странице [хлебных крошек](/ru/components/breadcrumbs).

Чтобы обеспечить удобство взаимодействия:
#### Поведение при прокрутке

- Скрывайте текст на кнопках при уменьшении ширины экрана.
- Добавляйте тултип с текстом при наведении.
- Соблюдайте минимальный отступ **80px**, задаваемый через `--kbq-top-bar-spacer-min-width`. Он применяется к элементам топ-меню, включая заголовок.
- Чтобы длинный заголовок не ломал верстку, скрывайте часть текста многоточием (**"Дашбо..."**).
Панель может фиксироваться при прокрутке страницы.

<!-- example(top-bar-overflow) -->
30 changes: 27 additions & 3 deletions packages/components/top-bar/top-bar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,41 @@

.kbq-top-bar-spacer {
height: 100%;
flex: 1 0 var(--kbq-top-bar-spacer-min-width);
flex: 0 0 var(--kbq-top-bar-spacer-min-width);
}

.kbq-top-bar-container__start {
display: flex;
gap: var(--kbq-top-bar-left-gap);
gap: var(--kbq-top-bar-container-start-gap);
flex: 1 0 var(--kbq-top-bar-container-start-basis);
justify-content: flex-start;
min-width: 0;
}

.kbq-top-bar-container__end {
display: flex;
gap: var(--kbq-top-bar-right-gap);
gap: var(--kbq-top-bar-container-end-gap);
justify-content: end;
}

.kbq-top-bar-container__with-overflow-items {
gap: unset;
padding: 1px;

> .kbq-overflow-item {
&:not(:last-of-type) {
margin-right: var(--kbq-top-bar-container-end-gap);
}

// apply margin if the last item needs to be alwaysVisible
&:last-of-type:is([aria-hidden='false']) + .kbq-overflow-items-result {
margin-left: var(--kbq-top-bar-container-end-gap);
}
}

.kbq-overflow-items-result:first-child {
margin-right: var(--kbq-top-bar-container-end-gap);
}
}

&.kbq-top-bar_with-shadow {
Expand Down
11 changes: 10 additions & 1 deletion packages/components/top-bar/top-bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import {
ChangeDetectionStrategy,
Component,
Directive,
inject,
input,
Input,
ViewEncapsulation
} from '@angular/core';
import { KbqOverflowItems } from '@koobiq/components/overflow-items';

@Directive({
standalone: true,
Expand All @@ -26,14 +28,21 @@ export class KbqTopBarSpacer {}
host: {
class: 'kbq-top-bar-container',
'[class.kbq-top-bar-container__start]': 'placement() === "start"',
'[class.kbq-top-bar-container__end]': 'placement() === "end"'
'[class.kbq-top-bar-container__end]': 'placement() === "end"',
'[class.kbq-top-bar-container__with-overflow-items]': 'overflowItems'
}
})
export class KbqTopBarContainer {
/**
* Conditionally applies a CSS class based on the value
*/
placement = input.required<'start' | 'end'>();
/**
* Track if container has `KbqOverflowItems` directive assigned.
* Used to replace `gap` with `margin` so `KbqOverflowItems` will calculate correct width on resize.
* @docs-private
*/
protected readonly overflowItems = inject(KbqOverflowItems, { optional: true, self: true });
}

@Component({
Expand Down
Loading