mirror of
https://github.com/MAKS-IT-COM/maksit-webui.git
synced 2026-08-15 09:58:09 +02:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd575eb926 |
10
CHANGELOG.md
10
CHANGELOG.md
@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.4.5] - 2026-08-12
|
||||
|
||||
### Changed
|
||||
|
||||
- **Breaking:** `Breadcrumb` now renders links with react-router `Link` directly. Dropped injectable `linkComponent`, `href`, and `linkProps` — use `to` on trail items only. Default link/current/separator colors use slate tones.
|
||||
|
||||
### Removed
|
||||
|
||||
- `BreadcrumbLinkComponent` export (no longer needed).
|
||||
|
||||
## [0.4.4] - 2026-08-12
|
||||
|
||||
### Fixed
|
||||
|
||||
@ -1,30 +1,12 @@
|
||||
import {
|
||||
type ComponentType,
|
||||
type FC,
|
||||
type ReactNode,
|
||||
} from 'react'
|
||||
import { type FC, type ReactNode } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
export interface BreadcrumbItem {
|
||||
label: ReactNode
|
||||
/** Used by default `<a>` and as fallback for router links. */
|
||||
href?: string
|
||||
/** Preferred when injecting react-router `Link`. */
|
||||
/** Omit on the current page (last item). */
|
||||
to?: string
|
||||
/** Extra props passed to the injected link component. */
|
||||
linkProps?: Record<string, unknown>
|
||||
}
|
||||
|
||||
/**
|
||||
* Injectable link surface for SPA routers.
|
||||
* `to` is always provided when Breadcrumb renders a link, so react-router `Link` is assignable.
|
||||
*/
|
||||
export type BreadcrumbLinkComponent = ComponentType<{
|
||||
to: string
|
||||
href?: string
|
||||
className?: string
|
||||
children?: ReactNode
|
||||
}>
|
||||
|
||||
export interface BreadcrumbProps {
|
||||
items: BreadcrumbItem[]
|
||||
/** Defaults to `"/"`. */
|
||||
@ -33,35 +15,21 @@ export interface BreadcrumbProps {
|
||||
linkClassName?: string
|
||||
currentClassName?: string
|
||||
separatorClassName?: string
|
||||
/** Host injects `Link` from react-router (or any anchor-like component). Defaults to `<a>`. */
|
||||
linkComponent?: BreadcrumbLinkComponent
|
||||
/** Accessible name for the nav landmark. Defaults to `"Breadcrumb"`. */
|
||||
label?: string
|
||||
}
|
||||
|
||||
const DefaultLink: BreadcrumbLinkComponent = ({
|
||||
href,
|
||||
to,
|
||||
children,
|
||||
...rest
|
||||
}) => (
|
||||
<a href={href ?? to} {...rest}>
|
||||
{children}
|
||||
</a>
|
||||
)
|
||||
|
||||
/**
|
||||
* Presentational page trail. Use links/`span` only — never headings.
|
||||
* Keep a single page `h1` on `FormHeader` or the page title.
|
||||
* Page trail (`nav` + `ol`). Links use react-router `Link`.
|
||||
* Never uses headings — keep a single page `h1` on `FormHeader` or the page title.
|
||||
*/
|
||||
const Breadcrumb: FC<BreadcrumbProps> = ({
|
||||
items,
|
||||
separator = '/',
|
||||
className = '',
|
||||
linkClassName = 'text-sky-700 hover:text-sky-900 hover:underline',
|
||||
currentClassName = 'text-gray-700',
|
||||
separatorClassName = 'text-gray-400',
|
||||
linkComponent: LinkComponent = DefaultLink,
|
||||
linkClassName = 'text-slate-500 hover:text-slate-800 hover:underline',
|
||||
currentClassName = 'text-slate-700',
|
||||
separatorClassName = 'text-slate-400',
|
||||
label = 'Breadcrumb',
|
||||
}) => {
|
||||
if (items.length === 0)
|
||||
@ -75,8 +43,7 @@ const Breadcrumb: FC<BreadcrumbProps> = ({
|
||||
<ol className={'flex flex-wrap items-center gap-x-2 gap-y-1'}>
|
||||
{items.map((item, index) => {
|
||||
const isLast = index === items.length - 1
|
||||
const target = item.to ?? item.href
|
||||
const isLink = !isLast && Boolean(target)
|
||||
const isLink = !isLast && Boolean(item.to)
|
||||
|
||||
return (
|
||||
<li
|
||||
@ -92,15 +59,13 @@ const Breadcrumb: FC<BreadcrumbProps> = ({
|
||||
</span>
|
||||
) : null}
|
||||
|
||||
{isLink && target ? (
|
||||
<LinkComponent
|
||||
href={item.href ?? (typeof item.to === 'string' ? item.to : undefined)}
|
||||
to={target}
|
||||
{isLink && item.to ? (
|
||||
<Link
|
||||
to={item.to}
|
||||
className={linkClassName}
|
||||
{...(item.linkProps ?? {})}
|
||||
>
|
||||
{item.label}
|
||||
</LinkComponent>
|
||||
</Link>
|
||||
) : (
|
||||
<span
|
||||
className={currentClassName}
|
||||
|
||||
@ -1,6 +1,2 @@
|
||||
export { Breadcrumb } from './Breadcrumb'
|
||||
export type {
|
||||
BreadcrumbProps,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLinkComponent,
|
||||
} from './Breadcrumb'
|
||||
export type { BreadcrumbProps, BreadcrumbItem } from './Breadcrumb'
|
||||
|
||||
@ -4,11 +4,7 @@ export { SecretComponent } from './components/editors/SecretComponent'
|
||||
export type { SecretDataSource, SecretComponentProps } from './components/editors/SecretComponent'
|
||||
export { FormContainer, FormContent, FormFooter, FormHeader } from './components/FormLayout'
|
||||
export { Breadcrumb } from './components/Breadcrumb'
|
||||
export type {
|
||||
BreadcrumbProps,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLinkComponent,
|
||||
} from './components/Breadcrumb'
|
||||
export type { BreadcrumbProps, BreadcrumbItem } from './components/Breadcrumb'
|
||||
export { Offcanvas } from './components/Offcanvas'
|
||||
export { Modal, ConfirmDialog } from './components/Modal'
|
||||
export type { ModalProps, ModalSize, ConfirmDialogProps } from './components/Modal'
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@maks-it.com/webui",
|
||||
"version": "0.4.4",
|
||||
"version": "0.4.5",
|
||||
"description": "Shared contracts, utilities, and React components for MaksIT WebUI apps",
|
||||
"type": "module",
|
||||
"main": "./dist/index.cjs",
|
||||
|
||||
@ -11,7 +11,7 @@ const meta = {
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
'Presentational page trail (`nav` + `ol`). Never uses headings — keep a single page `h1` on `FormHeader` or the page title. Inject `linkComponent` (e.g. react-router `Link`) for SPA navigation.',
|
||||
'Page trail (`nav` + `ol`) using react-router `Link`. Never uses headings — keep a single page `h1` on `FormHeader` or the page title.',
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -47,15 +47,14 @@ export const SingleItem: Story = {
|
||||
export const WithFormHeader: Story = {
|
||||
render: () => (
|
||||
<div className="space-y-0 border border-gray-200 bg-white">
|
||||
<div className="bg-gray-50 px-4 py-2">
|
||||
<Breadcrumb
|
||||
className="bg-gray-50 px-4 py-2"
|
||||
items={[
|
||||
{ label: 'Admin', to: '/admin' },
|
||||
{ label: 'Shop', to: '/admin/shop' },
|
||||
{ label: 'Edit item' },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<FormHeader>Edit shop item</FormHeader>
|
||||
<div className="p-4 text-sm text-gray-600">Form content</div>
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user