diff --git a/.changeset/layout-header-back-button.md b/.changeset/layout-header-back-button.md new file mode 100644 index 000000000..c9615a8f5 --- /dev/null +++ b/.changeset/layout-header-back-button.md @@ -0,0 +1,5 @@ +--- +"@cube-dev/ui-kit": minor +--- + +Added `onBack` prop to `Layout.Header` component. When provided, a back button with arrow icon is rendered to the left of the title, allowing users to navigate back from the current page. diff --git a/src/components/content/Layout/Layout.docs.mdx b/src/components/content/Layout/Layout.docs.mdx index 96f0a7483..049555175 100644 --- a/src/components/content/Layout/Layout.docs.mdx +++ b/src/components/content/Layout/Layout.docs.mdx @@ -118,8 +118,10 @@ A semantic page header with title, breadcrumbs, subtitle, and action areas. | subtitle | `ReactNode` | - | Text below the title | | suffix | `ReactNode` | - | Content next to the title | | extra | `ReactNode` | - | Content on the right side | +| onBack | `() => void` | - | Callback for the back button. When provided, a back arrow button appears to the left of the title. | **Sub-elements:** +- `Back` - Back button container (visible when `onBack` is provided) - `Breadcrumbs` - Navigation path container - `Title` - Main heading element - `Suffix` - Content adjacent to title @@ -431,6 +433,28 @@ A variant of Layout that enables CSS Grid for the content area. ``` +### With Back Button + + + +```jsx + + navigate(-1)} + extra={ + + + + + } + /> + + Page content with a back button in the header + + +``` + ### Resizable Side Panel diff --git a/src/components/content/Layout/Layout.stories.tsx b/src/components/content/Layout/Layout.stories.tsx index 999093ca2..3731e25cd 100644 --- a/src/components/content/Layout/Layout.stories.tsx +++ b/src/components/content/Layout/Layout.stories.tsx @@ -180,6 +180,26 @@ export const WithBreadcrumbs: Story = { ), }; +export const WithBackButton: Story = { + render: () => ( + + + + + + } + onBack={() => console.log('Back pressed')} + /> + + Page content with a back button in the header + + + ), +}; + export const WithSidePanel: Story = { render: function WithSidePanelStory() { const [isPanelOpen, setIsPanelOpen] = useState(true); diff --git a/src/components/content/Layout/LayoutHeader.tsx b/src/components/content/Layout/LayoutHeader.tsx index ffc139f03..b11947caa 100644 --- a/src/components/content/Layout/LayoutHeader.tsx +++ b/src/components/content/Layout/LayoutHeader.tsx @@ -1,3 +1,4 @@ +import { IconArrowLeft } from '@tabler/icons-react'; import { ForwardedRef, forwardRef, @@ -10,6 +11,7 @@ import { import { SlashIcon } from '../../../icons/SlashIcon'; import { tasty } from '../../../tasty'; +import { Button } from '../../actions/Button/Button'; import { Link } from '../../actions/Link/Link'; import { useAutoTooltip } from '../use-auto-tooltip'; @@ -29,16 +31,24 @@ const HeaderElement = tasty(LayoutContent, { $: '>', display: 'grid', gridTemplate: ` - "breadcrumbs breadcrumbs breadcrumbs" auto - "title suffix extra" 1fr - "subtitle subtitle extra" auto - / max-content 1fr minmax(0, auto) + "breadcrumbs breadcrumbs breadcrumbs breadcrumbs" auto + "back title suffix extra" 1fr + ".. subtitle subtitle extra" auto + / auto max-content 1fr minmax(0, auto) `, gap: 0, placeContent: 'stretch', placeItems: 'center stretch', }, + Back: { + $: '> Inner >', + gridArea: 'back', + display: 'flex', + placeItems: 'center', + margin: '.5x right', + }, + Breadcrumbs: { $: '> Inner >', gridArea: 'breadcrumbs', @@ -111,6 +121,8 @@ export interface CubeLayoutHeaderProps extends CubeLayoutContentProps { * Uses Link component which integrates with the navigation provider. */ breadcrumbs?: Array<[label: string, href: string]>; + /** Callback for the back button. When provided, a back arrow button is rendered to the left of the title. */ + onBack?: () => void; } function LayoutHeader( @@ -124,6 +136,7 @@ function LayoutHeader( extra, subtitle, breadcrumbs, + onBack, scrollbar = 'tiny', children, mods, @@ -181,6 +194,16 @@ function LayoutHeader( scrollbar={scrollbar} > {renderBreadcrumbs()} + {onBack && ( +
+
+ )} {renderWithTooltip(renderTitle, 'bottom')} {suffix &&
{suffix}
} {extra &&
{extra}
}