diff --git a/.storybook/components/Roadmap/data.ts b/.storybook/components/Roadmap/data.ts
index 58f6a3ea..7ab28a62 100644
--- a/.storybook/components/Roadmap/data.ts
+++ b/.storybook/components/Roadmap/data.ts
@@ -380,4 +380,10 @@ export const rows: Rows = [
stage: 'π΅ experimental',
planned: 'Q3 2026',
},
+ {
+ component: 'TopBar',
+ status: 'β Done',
+ stage: 'π΅ experimental',
+ planned: 'Q3 2026',
+ },
];
diff --git a/packages/components/src/components/TopBar/TopBar.mdx b/packages/components/src/components/TopBar/TopBar.mdx
new file mode 100644
index 00000000..4ce21242
--- /dev/null
+++ b/packages/components/src/components/TopBar/TopBar.mdx
@@ -0,0 +1,121 @@
+import {
+ Meta,
+ Story,
+ Props,
+ Status,
+} from '../../../../../.storybook/components';
+
+import * as Stories from './TopBar.stories';
+
+
+
+# TopBar
+
+
+
+TopBar is the bar at the top of a page. It shows the page title or the breadcrumbs on the start side
+and the page actions on the end side.
+
+## Import
+
+```tsx
+import { TopBar } from '@koobiq/react-components';
+```
+
+## Usage
+
+
+
+The bar holds one container per side. Render only the ones you need.
+
+```tsx
+
+
+ Dashboards
+
+
+
+
+
+
+```
+
+- `TopBar.Container` β one side of the bar. `placement="start"` grows and shrinks first,
+ `placement="end"` sticks to the opposite edge.
+- `TopBar.Title` β the page heading. It renders an `h1` and cuts long text with an ellipsis.
+
+By default, TopBar keeps at least `80px` between the two sides. Use `--kbq-top-bar-gap` to override
+it.
+
+## Props
+
+
+
+## Logo and counter
+
+A logo and an object counter are plain content of the start container β TopBar has no slots for them.
+
+
+
+## Position
+
+Use `position` to choose how the bar sits on the page:
+
+- `sticky` (default) β the bar pins to the top of the nearest scrolling ancestor.
+- `static` β the bar stays in the flow.
+
+The bar always stays in the flow, so the page content never needs a top offset.
+
+
+
+## Shadow
+
+The `hasShadow` prop only paints the bottom shadow. TopBar never listens to scrolling β watch the scroll
+position yourself and pass the result in.
+
+
+
+## Breadcrumbs
+
+Put [Breadcrumbs](?path=/docs/components-breadcrumbs--docs) in the start container. They collapse on
+their own β you do not need to add any logic around them.
+
+
+
+## Collapsing actions
+
+Use [useHideOverflowItems](?path=/docs/hooks-usehideoverflowitems--docs) and a `Menu` to collapse
+overflowing actions under a "β¦" button.
+
+
+
+The example reserves `160px` for the logo and collapsed Breadcrumbs. The `busy` value also includes
+the container gap and TopBar inline padding, so Breadcrumbs collapse before the actions.
+
+## CSS variables
+
+These optional variables override the component's internal values.
+
+| Variable | Purpose |
+| ----------------------------------------------- | --------------------------------------------------- |
+| `--kbq-top-bar-background` | Background of the bar. |
+| `--kbq-top-bar-padding-block` | Block padding. |
+| `--kbq-top-bar-padding-inline` | Inline padding. |
+| `--kbq-top-bar-border-radius` | Border radius. |
+| `--kbq-top-bar-min-block-size` | Minimum block size of the bar. |
+| `--kbq-top-bar-gap` | Minimum distance between the two sides. |
+| `--kbq-top-bar-z-index` | Stack order while `sticky`. |
+| `--kbq-top-bar-shadow` | Shadow shown by `hasShadow`. |
+| `--kbq-top-bar-container-start-gap` | Gap between items in the start container. |
+| `--kbq-top-bar-container-start-min-inline-size` | Width the start container keeps for itself. |
+| `--kbq-top-bar-container-end-gap` | Gap between items in the end container. |
+| `--kbq-top-bar-title-min-inline-size` | Smallest width of the title before the end shrinks. |
+
+## Accessibility
+
+- TopBar renders a `header`. Use `as` when the bar is not the banner of the page.
+- `TopBar.Title` renders an `h1`. Use `as` to fit the heading order of your page.
+- Set `isToolbar` on the container with the actions. It adds `role="toolbar"` and lets the user move
+ between the actions with the arrow keys, so the whole group takes one Tab stop.
+- Give a toolbar container an `aria-label`, for example `aria-label="Page actions"`.
+- Give icon-only actions an `aria-label`.
diff --git a/packages/components/src/components/TopBar/TopBar.module.css b/packages/components/src/components/TopBar/TopBar.module.css
new file mode 100644
index 00000000..b77fbf3c
--- /dev/null
+++ b/packages/components/src/components/TopBar/TopBar.module.css
@@ -0,0 +1,43 @@
+.base {
+ --top-bar-background: var(--kbq-background-bg);
+ --top-bar-padding-block: var(--kbq-size-m);
+ --top-bar-padding-inline: var(--kbq-size-xxl);
+ --top-bar-border-radius: 0;
+ --top-bar-min-block-size: var(--kbq-size-6xl);
+ --top-bar-gap: 80px;
+ --top-bar-z-index: var(--kbq-layer-topbar);
+ --top-bar-shadow: var(--kbq-shadow-overflow-normal-bottom);
+ --top-bar-container-start-gap: 0;
+ --top-bar-container-start-min-inline-size: 0;
+ --top-bar-container-end-gap: var(--kbq-size-s);
+ --top-bar-title-min-inline-size: 4ch;
+
+ display: flex;
+ box-sizing: border-box;
+ align-items: center;
+ min-block-size: var(
+ --kbq-top-bar-min-block-size,
+ var(--top-bar-min-block-size)
+ );
+ gap: var(--kbq-top-bar-gap, var(--top-bar-gap));
+ padding-block: var(--kbq-top-bar-padding-block, var(--top-bar-padding-block));
+ padding-inline: var(
+ --kbq-top-bar-padding-inline,
+ var(--top-bar-padding-inline)
+ );
+ border-radius: var(--kbq-top-bar-border-radius, var(--top-bar-border-radius));
+ background: var(--kbq-top-bar-background, var(--top-bar-background));
+ transition: box-shadow var(--kbq-transition-slow);
+}
+
+/* position */
+.base[data-position='sticky'] {
+ position: sticky;
+ z-index: var(--kbq-top-bar-z-index, var(--top-bar-z-index));
+ inset-block-start: 0;
+}
+
+/* shadow */
+.base[data-shadow='true'] {
+ box-shadow: var(--kbq-top-bar-shadow, var(--top-bar-shadow));
+}
diff --git a/packages/components/src/components/TopBar/TopBar.stories.tsx b/packages/components/src/components/TopBar/TopBar.stories.tsx
new file mode 100644
index 00000000..b6d9c426
--- /dev/null
+++ b/packages/components/src/components/TopBar/TopBar.stories.tsx
@@ -0,0 +1,417 @@
+import { type CSSProperties, type SVGProps, useEffect, useState } from 'react';
+
+import {
+ mergeProps,
+ mergeRefs,
+ useHideOverflowItems,
+} from '@koobiq/react-core';
+import {
+ IconArrowsRotate16,
+ IconBug16,
+ IconEllipsisHorizontal16,
+ IconFilter16,
+ IconGear16,
+ IconList16,
+ IconMagnifyingGlass16,
+ IconPlus16,
+ IconPrinter16,
+} from '@koobiq/react-icons';
+import type { Meta, StoryObj } from '@storybook/react';
+
+import { BreadcrumbItem, Breadcrumbs } from '../Breadcrumbs';
+import { Button } from '../Button';
+import { FlexBox } from '../FlexBox';
+import { IconButton } from '../IconButton';
+import { spacing } from '../layout';
+import { Menu } from '../Menu';
+import { Tooltip } from '../Tooltip';
+import { Typography } from '../Typography';
+
+import { TopBar, type TopBarProps, topBarPropPosition } from './index.js';
+
+const meta = {
+ title: 'Components/TopBar',
+ component: TopBar,
+ subcomponents: {
+ 'TopBar.Container': TopBar.Container,
+ 'TopBar.Title': TopBar.Title,
+ },
+ parameters: {
+ layout: 'padded',
+ },
+ tags: ['status:new', 'date:2026-07-31'],
+} satisfies Meta;
+
+export default meta;
+
+type Story = StoryObj;
+
+const AppIcon = (props: SVGProps) => (
+
+);
+
+const Content = () => (
+
+
+ Web security is a crucial aspect of modern digital infrastructure,
+ ensuring the protection of sensitive data, user privacy, and system
+ integrity. As cyber threats continue to evolve, developers and
+ organizations must adopt a proactive approach to securing web applications
+ against attacks.
+
+
+ One of the most common vulnerabilities is SQL injection, where attackers
+ manipulate database queries to gain unauthorized access to sensitive
+ information. Similarly, cross-site scripting (XSS) allows malicious
+ scripts to run on a victimβs browser, leading to data theft or session
+ hijacking. Another prevalent threat is cross-site request forgery (CSRF),
+ in which users are tricked into executing unwanted actions on
+ authenticated sites. Additionally, man-in-the-middle attacks intercept
+ communication between users and servers, compromising the confidentiality
+ of data. Distributed Denial-of-Service (DDoS) attacks can also cripple web
+ services by overwhelming them with excessive traffic.
+
+
+ To mitigate these risks, implementing strong security practices is
+ essential. Using HTTPS ensures encrypted communication, protecting data
+ from interception. Proper input validation and escaping mechanisms help
+ prevent code injection attacks. Authentication and authorization
+ mechanisms, including multi-factor authentication (MFA) and role-based
+ access control (RBAC), add layers of security to user access. Secure API
+ development, including authentication, rate limiting, and encryption,
+ reduces vulnerabilities in web services. Keeping software, frameworks, and
+ dependencies up to date minimizes the risk of exploiting known
+ vulnerabilities. Continuous monitoring, logging, and security audits help
+ detect and respond to threats before they cause significant damage.
+
+
+ Web security is not a one-time implementation but an ongoing process that
+ evolves alongside emerging threats. By following best practices and
+ staying vigilant, businesses and developers can build resilient, secure
+ applications that protect users and data in an increasingly connected
+ world.
+
+
+);
+
+export const Base: Story = {
+ render: (args) => (
+
+
+ Dashboards
+
+
+
+ }>Create dashboard
+
+
+ ),
+};
+
+export const WithLogoAndCounter: Story = {
+ render: (args) => (
+
+
+
+
+
+
+ Dashboards
+
+
+ 10
+
+
+
+ }>Create dashboard
+
+
+ ),
+};
+
+export const Position: Story = {
+ render: function Render() {
+ const containerStyle = {
+ overflow: 'auto',
+ position: 'relative',
+ blockSize: 240,
+ borderRadius: 'var(--kbq-size-s)',
+ border: '1px solid var(--kbq-line-contrast-less)',
+ } as CSSProperties;
+
+ return (
+
+ {topBarPropPosition.map((position) => (
+
+
+ position = {position}
+
+