twico-ui 1.47.0 → 1.49.0
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 +19 -0
- package/dist/icons.d.cts +2 -1
- package/dist/icons.d.ts +2 -1
- package/dist/index.cjs +57 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +77 -12
- package/dist/index.d.ts +77 -12
- package/dist/index.mjs +57 -1
- package/dist/index.mjs.map +1 -1
- package/llms.txt +5 -2
- package/package.json +2 -2
- package/styles/twico-ui.css +28 -10
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to Twico UI are documented here (newest first). This file is generated automatically on each release by [semantic-release](https://semantic-release.gitbook.io/) from [Conventional Commits](https://www.conventionalcommits.org/) — do not edit it by hand. The same notes appear on each [GitHub Release](https://github.com/EncryptionL/twico-ui/releases).
|
|
4
4
|
|
|
5
|
+
# [1.49.0](https://github.com/EncryptionL/twico-ui/compare/v1.48.0...v1.49.0) (2026-11-05)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **tokens:** make the plain tones clear 4.5:1 against their own ink ([78a727d](https://github.com/EncryptionL/twico-ui/commit/78a727d193010a717405ee14af038e39f1baf65b)), closes [#455](https://github.com/EncryptionL/twico-ui/issues/455) [#504](https://github.com/EncryptionL/twico-ui/issues/504) [#504](https://github.com/EncryptionL/twico-ui/issues/504) [#1e1b4b](https://github.com/EncryptionL/twico-ui/issues/1e1b4b) [#e11d48](https://github.com/EncryptionL/twico-ui/issues/e11d48) [#1e1b4b](https://github.com/EncryptionL/twico-ui/issues/1e1b4b) [#818cf8](https://github.com/EncryptionL/twico-ui/issues/818cf8) [#052e1d](https://github.com/EncryptionL/twico-ui/issues/052e1d) [#10b981](https://github.com/EncryptionL/twico-ui/issues/10b981) [#2c0610](https://github.com/EncryptionL/twico-ui/issues/2c0610) [#f43f5e](https://github.com/EncryptionL/twico-ui/issues/f43f5e)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* **button:** widen tone to the full Tone scale, not just primary|danger ([ec640c3](https://github.com/EncryptionL/twico-ui/commit/ec640c3f4c0faa5c19b6cab4b73a8a5758628864)), closes [#451a03](https://github.com/EncryptionL/twico-ui/issues/451a03) [#082f49](https://github.com/EncryptionL/twico-ui/issues/082f49)
|
|
16
|
+
|
|
17
|
+
# [1.48.0](https://github.com/EncryptionL/twico-ui/compare/v1.47.0...v1.48.0) (2026-10-23)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* **datatable:** vertical alignment at three levels — table, row, column ([221978b](https://github.com/EncryptionL/twico-ui/commit/221978b1db3527d97b93335a9b36b9274d2c8b10))
|
|
23
|
+
|
|
5
24
|
# [1.47.0](https://github.com/EncryptionL/twico-ui/compare/v1.46.0...v1.47.0) (2026-10-23)
|
|
6
25
|
|
|
7
26
|
|
package/dist/icons.d.cts
CHANGED
|
@@ -56,4 +56,5 @@ declare const brandIcons: BrandIconMeta[];
|
|
|
56
56
|
/** Just the exported component names of every brand icon. */
|
|
57
57
|
declare const brandIconNames: string[];
|
|
58
58
|
|
|
59
|
-
export { AppleBrandIcon, BlueskyIcon,
|
|
59
|
+
export { AppleBrandIcon, BlueskyIcon, DiscordIcon, DockerIcon, DribbbleIcon, FacebookIcon, FigmaIcon, GithubIcon, GitlabIcon, GoogleIcon, InstagramIcon, MastodonIcon, MediumIcon, NextjsIcon, NodejsIcon, NpmIcon, PinterestIcon, ReactjsIcon, RedditIcon, SpotifyIcon, StackOverflowIcon, TailwindIcon, TelegramIcon, ThreadsIcon, TikTokIcon, TwitchIcon, TypeScriptIcon, VercelIcon, WhatsAppIcon, XTwitterIcon, YoutubeIcon, brandIconNames, brandIcons };
|
|
60
|
+
export type { BrandIcon, BrandIconMeta, BrandIconProps };
|
package/dist/icons.d.ts
CHANGED
|
@@ -56,4 +56,5 @@ declare const brandIcons: BrandIconMeta[];
|
|
|
56
56
|
/** Just the exported component names of every brand icon. */
|
|
57
57
|
declare const brandIconNames: string[];
|
|
58
58
|
|
|
59
|
-
export { AppleBrandIcon, BlueskyIcon,
|
|
59
|
+
export { AppleBrandIcon, BlueskyIcon, DiscordIcon, DockerIcon, DribbbleIcon, FacebookIcon, FigmaIcon, GithubIcon, GitlabIcon, GoogleIcon, InstagramIcon, MastodonIcon, MediumIcon, NextjsIcon, NodejsIcon, NpmIcon, PinterestIcon, ReactjsIcon, RedditIcon, SpotifyIcon, StackOverflowIcon, TailwindIcon, TelegramIcon, ThreadsIcon, TikTokIcon, TwitchIcon, TypeScriptIcon, VercelIcon, WhatsAppIcon, XTwitterIcon, YoutubeIcon, brandIconNames, brandIcons };
|
|
60
|
+
export type { BrandIcon, BrandIconMeta, BrandIconProps };
|
package/dist/index.cjs
CHANGED
|
@@ -455,6 +455,22 @@ var ICONBTN_CSS = `
|
|
|
455
455
|
--_accent-fg: var(--color-primary-fg); --_accent-subtle: var(--color-primary-subtle); --_accent-subtle-fg: var(--color-primary-subtle-fg); }
|
|
456
456
|
.twc-iconbtn[data-tone="danger"] { --_accent: var(--color-danger); --_accent-hover: var(--color-danger-hover);
|
|
457
457
|
--_accent-fg: var(--color-danger-fg); --_accent-subtle: var(--color-danger-subtle); --_accent-subtle-fg: var(--color-danger-subtle-fg); }
|
|
458
|
+
/* #504: the full Tone scale, not just primary|danger. A standalone affirmative action - a row-level
|
|
459
|
+
confirm sitting next to a danger sibling, reading as "yes / no" - could not be green, so the colour
|
|
460
|
+
that carried the distinction came out the same blue as every neutral action on the page.
|
|
461
|
+
success/warning/info now have real -hover/-active tokens (added in tokens/colors.css on the same
|
|
462
|
+
step rule as primary and danger: light goes darker, dark goes lighter), so hover always moves AWAY
|
|
463
|
+
from the ink and contrast only improves. neutral has no accent tokens anywhere and is mapped the way
|
|
464
|
+
Badge already maps it - --color-text on --color-surface solid, --color-surface-sunken soft - with its
|
|
465
|
+
hover mixed from currentColor, since there is no --color-text-hover to point at. */
|
|
466
|
+
.twc-iconbtn[data-tone="success"] { --_accent: var(--color-success); --_accent-hover: var(--color-success-hover);
|
|
467
|
+
--_accent-fg: var(--color-success-fg); --_accent-subtle: var(--color-success-subtle); --_accent-subtle-fg: var(--color-success-subtle-fg); }
|
|
468
|
+
.twc-iconbtn[data-tone="warning"] { --_accent: var(--color-warning); --_accent-hover: var(--color-warning-hover);
|
|
469
|
+
--_accent-fg: var(--color-warning-fg); --_accent-subtle: var(--color-warning-subtle); --_accent-subtle-fg: var(--color-warning-subtle-fg); }
|
|
470
|
+
.twc-iconbtn[data-tone="info"] { --_accent: var(--color-info); --_accent-hover: var(--color-info-hover);
|
|
471
|
+
--_accent-fg: var(--color-info-fg); --_accent-subtle: var(--color-info-subtle); --_accent-subtle-fg: var(--color-info-subtle-fg); }
|
|
472
|
+
.twc-iconbtn[data-tone="neutral"] { --_accent: var(--color-text); --_accent-hover: color-mix(in srgb, var(--color-text) 88%, var(--color-surface));
|
|
473
|
+
--_accent-fg: var(--color-surface); --_accent-subtle: var(--color-surface-sunken); --_accent-subtle-fg: var(--color-text-muted); }
|
|
458
474
|
.twc-iconbtn[data-variant="solid"] { background: var(--_accent); color: var(--_accent-fg); }
|
|
459
475
|
.twc-iconbtn[data-variant="solid"]:hover:not(:disabled) { background: var(--_accent-hover); box-shadow: var(--shadow-brand); }
|
|
460
476
|
.twc-iconbtn[data-variant="solid"]:active:not(:disabled) { filter: brightness(0.92); }
|
|
@@ -1832,6 +1848,31 @@ var CSS2 = `
|
|
|
1832
1848
|
--_accent: var(--color-danger); --_accent-hover: var(--color-danger-hover); --_accent-active: var(--color-danger-hover);
|
|
1833
1849
|
--_accent-fg: var(--color-danger-fg); --_accent-subtle: var(--color-danger-subtle); --_accent-subtle-fg: var(--color-danger-subtle-fg);
|
|
1834
1850
|
}
|
|
1851
|
+
/* #504: the full Tone scale, not just primary|danger. A standalone affirmative action - a row-level
|
|
1852
|
+
confirm sitting next to a danger sibling, reading as "yes / no" - could not be green, so the colour
|
|
1853
|
+
that carried the distinction came out the same blue as every neutral action on the page.
|
|
1854
|
+
success/warning/info now have real -hover/-active tokens (added in tokens/colors.css on the same
|
|
1855
|
+
step rule as primary and danger: light goes darker, dark goes lighter), so hover always moves AWAY
|
|
1856
|
+
from the ink and contrast only improves. neutral has no accent tokens anywhere and is mapped the way
|
|
1857
|
+
Badge already maps it - --color-text on --color-surface solid, --color-surface-sunken soft - with its
|
|
1858
|
+
hover mixed from currentColor, since there is no --color-text-hover to point at. */
|
|
1859
|
+
.twc-btn[data-tone="success"] {
|
|
1860
|
+
--_accent: var(--color-success); --_accent-hover: var(--color-success-hover); --_accent-active: var(--color-success-active);
|
|
1861
|
+
--_accent-fg: var(--color-success-fg); --_accent-subtle: var(--color-success-subtle); --_accent-subtle-fg: var(--color-success-subtle-fg);
|
|
1862
|
+
}
|
|
1863
|
+
.twc-btn[data-tone="warning"] {
|
|
1864
|
+
--_accent: var(--color-warning); --_accent-hover: var(--color-warning-hover); --_accent-active: var(--color-warning-active);
|
|
1865
|
+
--_accent-fg: var(--color-warning-fg); --_accent-subtle: var(--color-warning-subtle); --_accent-subtle-fg: var(--color-warning-subtle-fg);
|
|
1866
|
+
}
|
|
1867
|
+
.twc-btn[data-tone="info"] {
|
|
1868
|
+
--_accent: var(--color-info); --_accent-hover: var(--color-info-hover); --_accent-active: var(--color-info-active);
|
|
1869
|
+
--_accent-fg: var(--color-info-fg); --_accent-subtle: var(--color-info-subtle); --_accent-subtle-fg: var(--color-info-subtle-fg);
|
|
1870
|
+
}
|
|
1871
|
+
.twc-btn[data-tone="neutral"] {
|
|
1872
|
+
--_accent: var(--color-text); --_accent-hover: color-mix(in srgb, var(--color-text) 88%, var(--color-surface));
|
|
1873
|
+
--_accent-active: color-mix(in srgb, var(--color-text) 78%, var(--color-surface));
|
|
1874
|
+
--_accent-fg: var(--color-surface); --_accent-subtle: var(--color-surface-sunken); --_accent-subtle-fg: var(--color-text-muted);
|
|
1875
|
+
}
|
|
1835
1876
|
/* solid */
|
|
1836
1877
|
.twc-btn[data-variant="solid"] { background: var(--_accent); color: var(--_accent-fg); }
|
|
1837
1878
|
.twc-btn[data-variant="solid"]:hover:not(:disabled) { background: var(--_accent-hover); box-shadow: var(--shadow-brand); }
|
|
@@ -9378,9 +9419,20 @@ var DT_CSS = `
|
|
|
9378
9419
|
font-size: var(--text-sm); color: var(--color-text); background: var(--twc-dt-row-bg, var(--color-surface));
|
|
9379
9420
|
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 0; }
|
|
9380
9421
|
/* Wrap-text columns: content flows onto multiple lines (the row grows down) instead of
|
|
9381
|
-
clipping to one line. height stays a per-row minimum, so single-line cells are unchanged.
|
|
9422
|
+
clipping to one line. height stays a per-row minimum, so single-line cells are unchanged.
|
|
9423
|
+
The top alignment here is only a DEFAULT for wrapped cells - an explicit verticalAlign at any
|
|
9424
|
+
level resolves to data-valign below, which is more specific and wins. Before that existed, a row
|
|
9425
|
+
mixing a wrapped column with normal ones was silently inconsistent: the wrapped cell sat top and
|
|
9426
|
+
its neighbours sat middle, with no way to say otherwise. */
|
|
9382
9427
|
.twc-dt__td[data-wrap="true"] { white-space: normal; overflow: hidden; text-overflow: clip;
|
|
9383
9428
|
word-break: break-word; overflow-wrap: anywhere; vertical-align: top; padding-block: 10px; line-height: 1.45; }
|
|
9429
|
+
/* Vertical alignment. One attribute, already resolved: column > row > table default, computed in
|
|
9430
|
+
renderLeaf rather than left to three competing selectors, so the precedence is readable in the
|
|
9431
|
+
code and cannot be reordered by an unrelated CSS edit. Matters whenever rows vary in height -
|
|
9432
|
+
wrapText, a multi-line renderCell, or a drag-resized row. */
|
|
9433
|
+
.twc-dt__td[data-valign="top"] { vertical-align: top; }
|
|
9434
|
+
.twc-dt__td[data-valign="middle"] { vertical-align: middle; }
|
|
9435
|
+
.twc-dt__td[data-valign="bottom"] { vertical-align: bottom; }
|
|
9384
9436
|
/* #338: "combined" column cell \u2014 one column showing several source columns' values. */
|
|
9385
9437
|
.twc-dt__combine--stack { display: flex; flex-direction: column; gap: 1px; }
|
|
9386
9438
|
.twc-dt__combine-sep { color: var(--color-text-subtle); padding-inline: 3px; }
|
|
@@ -10149,6 +10201,8 @@ function Datatable({
|
|
|
10149
10201
|
batchActions = [],
|
|
10150
10202
|
onRowSelectionChange,
|
|
10151
10203
|
selectionSummary,
|
|
10204
|
+
verticalAlign,
|
|
10205
|
+
getRowVerticalAlign,
|
|
10152
10206
|
getRowStyle,
|
|
10153
10207
|
getRowClassName,
|
|
10154
10208
|
showExport = false,
|
|
@@ -12728,6 +12782,7 @@ function Datatable({
|
|
|
12728
12782
|
const h = rowHeights[k];
|
|
12729
12783
|
const userRowStyle = getRowStyle ? getRowStyle(row, ri) : void 0;
|
|
12730
12784
|
const userRowClass = getRowClassName ? getRowClassName(row, ri) : void 0;
|
|
12785
|
+
const rowValign = getRowVerticalAlign ? getRowVerticalAlign(row, ri) : void 0;
|
|
12731
12786
|
const { background: _rowBgShorthand, backgroundColor: _rowBgColor, ...restRowStyle } = userRowStyle || {};
|
|
12732
12787
|
const usable = (v) => typeof v === "string" && v.trim() !== "" ? v : void 0;
|
|
12733
12788
|
const rowBg = usable(_rowBgShorthand) ?? usable(_rowBgColor);
|
|
@@ -12838,6 +12893,7 @@ function Datatable({
|
|
|
12838
12893
|
"data-num": c.type === "number" || void 0,
|
|
12839
12894
|
"data-actions": isActions || void 0,
|
|
12840
12895
|
"data-align": c.align !== dtNaturalAlign(c) ? c.align : void 0,
|
|
12896
|
+
"data-valign": c.verticalAlign ?? rowValign ?? verticalAlign,
|
|
12841
12897
|
"data-editable": editable && !isEditing || void 0,
|
|
12842
12898
|
"data-editing": isEditing || void 0,
|
|
12843
12899
|
"data-cell-active": cellActive || void 0,
|