tamga-ui 0.5.4 → 0.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/dist/components/layout.js +1 -1
- package/dist/fonts.css +1 -1
- package/dist/kit.css +4 -4
- package/dist/patterns/app-shell.d.ts +24 -2
- package/dist/patterns/app-shell.d.ts.map +1 -1
- package/dist/patterns/app-shell.js +6 -4
- package/dist/styles.css +1 -1
- package/dist/theme.css +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,31 @@ Versions follow [semver](https://semver.org/). Through `0.x`, breaking changes m
|
|
|
5
5
|
|
|
6
6
|
> 🇹🇷 Türkçe için [tamga.org.tr/tr](https://tamga.org.tr/tr).
|
|
7
7
|
|
|
8
|
+
## 0.5.5
|
|
9
|
+
|
|
10
|
+
> A page title finds its size, a shell can be driven by state instead of addresses, and the
|
|
11
|
+
> current rail row stands on the brand.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **`AppShell` entries can carry an action instead of an address.** `NavEntry.href` was required and
|
|
16
|
+
the active row was found by comparing paths, which is right for a web panel and wrong for a
|
|
17
|
+
desktop app, where a screen is state and there is no URL. An entry may now give `onSelect`, and
|
|
18
|
+
`activePath` is then matched against its `key`. One of the two is required; nothing changes for an
|
|
19
|
+
entry that has a path.
|
|
20
|
+
|
|
21
|
+
- **`AppShell.mainClassName`** — a state class on the content surface, for something the shell
|
|
22
|
+
cannot know: a window-wide drop target marking its edge, say. Layout stays the kit's; without it
|
|
23
|
+
a product had to draw the whole shell by hand to reach that one edge.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- **A page title is 24px, not 40px.** `PageBand` drew its heading at `--text-display-lg`, which is
|
|
28
|
+
the reference design's own size for a marketing-width page. In a dense panel — a table under the
|
|
29
|
+
title, a filter bar above it — it took the room the data needed and read as a banner rather than a
|
|
30
|
+
heading. The scale now reads 16 section · 18 dialog · 24 page · 30 KPI, and the two token comments
|
|
31
|
+
that still called 18px "page titles" and 30px "KPI numbers only" were corrected with it.
|
|
32
|
+
|
|
8
33
|
## 0.5.4
|
|
9
34
|
|
|
10
35
|
> An empty filter drawer no longer advertises itself, and a tile's icon reads as a glyph.
|
|
@@ -78,7 +78,7 @@ export function CellActions({ className, children, align = "end", ...props
|
|
|
78
78
|
* Doküman: /docs/page-band
|
|
79
79
|
*/
|
|
80
80
|
export function PageBand({ eyebrow, title, subtitle, actions, className, ...rest }) {
|
|
81
|
-
return (_jsxs("div", { ...dataProps(rest), className: cn("flex flex-wrap items-end gap-4", className), children: [_jsxs("div", { className: "min-w-0 flex-1 basis-65", children: [eyebrow ? (_jsx("p", { className: "mb-1.5 text-small font-semibold text-ink-faint", children: eyebrow })) : null, _jsx("h1", { className: "flex flex-wrap items-center gap-x-3 gap-y-1.5 font-display text-display-
|
|
81
|
+
return (_jsxs("div", { ...dataProps(rest), className: cn("flex flex-wrap items-end gap-4", className), children: [_jsxs("div", { className: "min-w-0 flex-1 basis-65", children: [eyebrow ? (_jsx("p", { className: "mb-1.5 text-small font-semibold text-ink-faint", children: eyebrow })) : null, _jsx("h1", { className: "flex flex-wrap items-center gap-x-3 gap-y-1.5 font-display text-display-sm leading-tight font-extrabold text-ink", children: title }), subtitle ? _jsx("p", { className: "mt-1.5 text-body text-ink-soft", children: subtitle }) : null] }), actions ? _jsx("div", { className: "ml-auto flex flex-wrap items-center gap-2", children: actions }) : null] }));
|
|
82
82
|
}
|
|
83
83
|
/**
|
|
84
84
|
* Gezinen bağlantı. `Button variant="link"` DEĞİL: o bir `<button>`, yani orta
|
package/dist/fonts.css
CHANGED
package/dist/kit.css
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! tamga-ui 0.5.
|
|
1
|
+
/*! tamga-ui 0.5.5 · MIT · https://tamga.org.tr */
|
|
2
2
|
:root {
|
|
3
3
|
|
|
4
4
|
--overlay-gap: 8px;
|
|
@@ -440,9 +440,9 @@
|
|
|
440
440
|
|
|
441
441
|
.tamga-rail-link[data-active="true"] {
|
|
442
442
|
background: var(--color-shell);
|
|
443
|
-
border-color: var(--color-
|
|
443
|
+
border-color: var(--color-accent-shadow);
|
|
444
444
|
transform: translate(-1px, -1px);
|
|
445
|
-
box-shadow: 3px 3px 0 var(--color-
|
|
445
|
+
box-shadow: 3px 3px 0 var(--color-accent-shadow);
|
|
446
446
|
}
|
|
447
447
|
|
|
448
448
|
.tamga-rail-link[data-active="true"] svg {
|
|
@@ -451,7 +451,7 @@
|
|
|
451
451
|
|
|
452
452
|
.tamga-rail-link[data-active="true"]:active {
|
|
453
453
|
transform: translate(2px, 2px);
|
|
454
|
-
box-shadow: 0 0 0 var(--color-
|
|
454
|
+
box-shadow: 0 0 0 var(--color-accent-shadow);
|
|
455
455
|
}
|
|
456
456
|
|
|
457
457
|
.tamga-btn:not(:disabled):active,
|
|
@@ -8,8 +8,23 @@ import { type LinkComponent } from "./shared.js";
|
|
|
8
8
|
* yönlendiriciyi tanımaz. Gerekçe: docs/adr/0004-sablon-katmani.md
|
|
9
9
|
*/
|
|
10
10
|
export type NavEntry = {
|
|
11
|
+
/**
|
|
12
|
+
* The entry's identity. With `onSelect` it is also what `activePath` is compared against.
|
|
13
|
+
* TR: Girişin kimliği. `onSelect` ile birlikte `activePath`in karşılaştırıldığı değer de bu.
|
|
14
|
+
*/
|
|
11
15
|
key: string;
|
|
12
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Where the entry goes. A desktop app has no addresses: it gives `onSelect` instead, and one of
|
|
18
|
+
* the two is required.
|
|
19
|
+
* TR: Girişin gittiği yer. Masaüstü uygulamasının adresi yok; onun yerine `onSelect` veriyor ve
|
|
20
|
+
* ikisinden biri zorunlu.
|
|
21
|
+
*/
|
|
22
|
+
href?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Runs instead of navigating. For a shell whose screens are state, not addresses.
|
|
25
|
+
* TR: Gezinmenin yerine koşuyor · ekranları adres değil durum olan bir kabuk için.
|
|
26
|
+
*/
|
|
27
|
+
onSelect?: () => void;
|
|
13
28
|
/** The translated label. In the tooltip on a narrow rail, on the row itself on a wide one. TR: Çevrilmiş etiket. Dar rayda ipucunda, geniş rayda satırın kendisinde. */
|
|
14
29
|
label: string;
|
|
15
30
|
icon: ComponentProps<typeof Icon>["icon"];
|
|
@@ -56,6 +71,13 @@ export type AppShellProps = {
|
|
|
56
71
|
topbar?: ReactNode;
|
|
57
72
|
/** A control at the foot of the rail: an expand/collapse button, say. TR: Rayın dibine giren kontrol: genişlet/daralt düğmesi gibi. */
|
|
58
73
|
railFooter?: ReactNode;
|
|
74
|
+
/**
|
|
75
|
+
* A state class on the content surface, for something the shell cannot know: a window-wide drop
|
|
76
|
+
* target marking its edge, say. Layout stays the kit's.
|
|
77
|
+
* TR: İçerik yüzeyine binen durum sınıfı · kabuğun bilemeyeceği bir şey için: pencere genelinde
|
|
78
|
+
* bir bırakma hedefinin kenarını işaretlemesi gibi. Düzen kitte kalıyor.
|
|
79
|
+
*/
|
|
80
|
+
mainClassName?: string;
|
|
59
81
|
linkComponent?: LinkComponent;
|
|
60
82
|
labels: {
|
|
61
83
|
home: string;
|
|
@@ -63,5 +85,5 @@ export type AppShellProps = {
|
|
|
63
85
|
};
|
|
64
86
|
children: ReactNode;
|
|
65
87
|
};
|
|
66
|
-
export declare function AppShell({ brand, nav, activePath, rail, topbar, railFooter, linkComponent: Link, labels, children, }: AppShellProps): import("react").JSX.Element;
|
|
88
|
+
export declare function AppShell({ brand, nav, activePath, rail, topbar, railFooter, mainClassName, linkComponent: Link, labels, children, }: AppShellProps): import("react").JSX.Element;
|
|
67
89
|
//# sourceMappingURL=app-shell.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-shell.d.ts","sourceRoot":"","sources":["../../src/patterns/app-shell.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"app-shell.d.ts","sourceRoot":"","sources":["../../src/patterns/app-shell.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAG7C,OAAO,EAAa,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5D;;;;;GAKG;AAEH,MAAM,MAAM,QAAQ,GAAG;IACrB;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,wKAAwK;IACxK,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,cAAc,CAAC,OAAO,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC;IAC1C;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,wJAAwJ;IACxJ,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,GAAG,EAAE,SAAS,QAAQ,EAAE,CAAC;IACzB,mGAAmG;IACnG,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;;OAWG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IACzB;;;;OAIG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,uIAAuI;IACvI,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,GAAG,EACH,UAAU,EACV,IAAe,EACf,MAAM,EACN,UAAU,EACV,aAAa,EACb,aAAa,EAAE,IAAgB,EAC/B,MAAM,EACN,QAAQ,GACT,EAAE,aAAa,+BAsHf"}
|
|
@@ -3,16 +3,18 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
3
3
|
import { Fragment } from "react";
|
|
4
4
|
import { Icon } from "../components/icon.js";
|
|
5
5
|
import { RailLink } from "../components/rail-link.js";
|
|
6
|
+
import { cn } from "../lib/cn.js";
|
|
6
7
|
import { PlainLink } from "./shared.js";
|
|
7
|
-
export function AppShell({ brand, nav, activePath, rail = "narrow", topbar, railFooter, linkComponent: Link = PlainLink, labels, children, }) {
|
|
8
|
+
export function AppShell({ brand, nav, activePath, rail = "narrow", topbar, railFooter, mainClassName, linkComponent: Link = PlainLink, labels, children, }) {
|
|
8
9
|
/* Bir giriş kendi alt ağacına sahip, ve EN UZUN EŞLEŞEN KAZANIR: kökün `/`
|
|
9
10
|
olmadığı bir panelde kök giriş altındaki her rotayı yutuyordu.
|
|
10
11
|
Gerekçe: docs/gerekce/08-blok-ve-sablon.md */
|
|
11
12
|
const kapsiyor = (href) => activePath === href || activePath.startsWith(`${href}/`);
|
|
12
|
-
const enOzel = nav.reduce((kazanan, entry) => kapsiyor(entry.href) && (kazanan === null || entry.href.length > kazanan.length)
|
|
13
|
+
const enOzel = nav.reduce((kazanan, entry) => entry.href && kapsiyor(entry.href) && (kazanan === null || entry.href.length > kazanan.length)
|
|
13
14
|
? entry.href
|
|
14
15
|
: kazanan, null);
|
|
15
|
-
|
|
16
|
+
/* ADRESİ OLMAYAN GİRİŞ ANAHTARIYLA EŞLEŞİYOR: masaüstü kabuğunda ekran bir durum, yol değil. */
|
|
17
|
+
const isCurrent = (entry) => entry.href ? entry.href === enOzel : entry.key === activePath;
|
|
16
18
|
const wide = rail === "wide";
|
|
17
|
-
return (_jsxs("div", { className: "flex h-dvh w-full overflow-hidden bg-rail text-ink-soft", children: [_jsxs("aside", { className: `flex shrink-0 flex-col gap-2 bg-rail py-4 ${wide ? "w-60 px-3" : "w-20 items-center px-1"}`, "data-rail": rail, children: [brand ? (_jsxs(_Fragment, { children: [_jsx("span", { "aria-label": labels.home, className: `mb-2 flex h-10 shrink-0 items-center text-ink ${wide ? "px-2" : "w-10 justify-center"}`, children: brand }), _jsx("span", { className: `h-0 w-6 border-t border-line ${wide ? "ml-2" : ""}` })] })) : null, _jsx("nav", { "aria-label": labels.primaryNav, className: `tamga-rail-scroll flex w-full flex-1 flex-col gap-2 py-1 ${wide ? "" : "items-center"}`, children: nav.map((entry, i) => (_jsxs(Fragment, { children: [wide && entry.section && entry.section !== nav[i - 1]?.section ? (_jsx("p", { className: `px-2.5 text-caption font-bold uppercase tracking-label text-ink-faint ${i > 0 ? "mt-5 pb-1.5" : "pb-1.5"}`, children: entry.section })) : null, _jsx(RailLink, { href: entry.href, label: entry.label, active: isCurrent(entry
|
|
19
|
+
return (_jsxs("div", { className: "flex h-dvh w-full overflow-hidden bg-rail text-ink-soft", children: [_jsxs("aside", { className: `flex shrink-0 flex-col gap-2 bg-rail py-4 ${wide ? "w-60 px-3" : "w-20 items-center px-1"}`, "data-rail": rail, children: [brand ? (_jsxs(_Fragment, { children: [_jsx("span", { "aria-label": labels.home, className: `mb-2 flex h-10 shrink-0 items-center text-ink ${wide ? "px-2" : "w-10 justify-center"}`, children: brand }), _jsx("span", { className: `h-0 w-6 border-t border-line ${wide ? "ml-2" : ""}` })] })) : null, _jsx("nav", { "aria-label": labels.primaryNav, className: `tamga-rail-scroll flex w-full flex-1 flex-col gap-2 py-1 ${wide ? "" : "items-center"}`, children: nav.map((entry, i) => (_jsxs(Fragment, { children: [wide && entry.section && entry.section !== nav[i - 1]?.section ? (_jsx("p", { className: `px-2.5 text-caption font-bold uppercase tracking-label text-ink-faint ${i > 0 ? "mt-5 pb-1.5" : "pb-1.5"}`, children: entry.section })) : null, _jsx(RailLink, { href: entry.href, onClick: entry.onSelect, label: entry.label, active: isCurrent(entry), showLabel: wide, linkComponent: Link, "data-nav": entry.key, children: _jsx(Icon, { icon: entry.icon, size: "md", weight: isCurrent(entry) ? "fill" : "regular" }) })] }, entry.key))) }), railFooter ? _jsx("div", { className: "shrink-0", children: railFooter }) : null] }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [_jsx("header", { className: "tamga-gutter flex items-center gap-4 bg-band py-4", children: topbar }), _jsx("div", { className: "min-h-0 flex-1 overflow-hidden pr-4 pb-4", children: _jsx("main", { className: cn("tamga-surface tamga-app-main relative h-full min-h-0 overflow-y-auto", mainClassName), children: children }) })] })] }));
|
|
18
20
|
}
|
package/dist/styles.css
CHANGED
package/dist/theme.css
CHANGED