@cahyo-dimas/freeday 1.48.1 → 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
CHANGED
|
@@ -3,6 +3,25 @@
|
|
|
3
3
|
Semua perubahan penting dicatat di sini. Format longgar mengikuti
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/); tiap versi = git tag.
|
|
5
5
|
|
|
6
|
+
## [1.49.0] — 2026-08-20
|
|
7
|
+
### Added
|
|
8
|
+
- **`FdyTableColumn.labelHidden`** (#026). A column of row CONTROLS — an edit button, a row menu —
|
|
9
|
+
could be named or quiet, not both: `label` renders as bare text in the `<th>`, so a designer who
|
|
10
|
+
does not want a word above a column of icons was left with an empty header, which assistive tech
|
|
11
|
+
announces as nothing. With `labelHidden: true` the label renders inside `.fdy-visually-hidden`:
|
|
12
|
+
the cell looks empty and the column is still named. The label keeps naming the column's filter
|
|
13
|
+
popover and sort button, so it stays meaningful either way.
|
|
14
|
+
Contract and ALL THREE typed adapters — Vue, React and Blazor. Each renders its own header, so
|
|
15
|
+
each spends the flag itself; Blazor takes `LabelHidden` on `FdyTableColumn<TRow>`.
|
|
16
|
+
### Added — guards
|
|
17
|
+
- **The column contract now has to reach all three adapters** (#026). Vue and React consume
|
|
18
|
+
`table-model.d.ts` and TypeScript keeps them honest, but Blazor RE-DECLARES the column in C# — a
|
|
19
|
+
hand copy, and the surface that can fall behind silently. A test asserts every contract property
|
|
20
|
+
exists on Blazor's `FdyTableColumn<TRow>`; coverage, not equality, so it needs no exemption list.
|
|
21
|
+
- **A hidden label is clipped, not dropped** — asserted in a real browser for both JS adapters
|
|
22
|
+
(`browser/adapter.mjs`), because the claim is about computed geometry: a span carrying the class
|
|
23
|
+
with no CSS behind it passes any string match and still prints the word.
|
|
24
|
+
|
|
6
25
|
## [1.48.1] — 2026-08-20
|
|
7
26
|
### Fixed
|
|
8
27
|
- **A date column sorted correctly and filtered nothing** (#025). `FdyTable`'s client-mode date
|
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
<th scope="col" style="@AlignStyle(col)" aria-sort="@AriaSortOf(col)">
|
|
27
27
|
@if (col.Sortable)
|
|
28
28
|
{
|
|
29
|
-
<button type="button" class="fdy-table__sortbtn" @onclick="() => OnSortClick(col)">@col.Label</button>
|
|
29
|
+
<button type="button" class="fdy-table__sortbtn" @onclick="() => OnSortClick(col)"><span class="@(col.LabelHidden ? "fdy-visually-hidden" : null)">@col.Label</span></button>
|
|
30
30
|
}
|
|
31
31
|
else
|
|
32
32
|
{
|
|
33
|
-
@col.Label
|
|
33
|
+
<span class="@(col.LabelHidden ? "fdy-visually-hidden" : null)">@col.Label</span>
|
|
34
34
|
}
|
|
35
35
|
@if (col.Filter is { } ft)
|
|
36
36
|
{
|
|
@@ -47,6 +47,13 @@ public sealed class FdyTableColumn<TRow>
|
|
|
47
47
|
/// <summary>Header label.</summary>
|
|
48
48
|
public required string Label { get; init; }
|
|
49
49
|
|
|
50
|
+
/// <summary>Render the label for assistive tech only — the header cell looks empty.
|
|
51
|
+
/// For a column of row CONTROLS (an edit button, a row menu), where a visible heading is noise
|
|
52
|
+
/// above a column of icons but the column still has to be named: a <c>th</c> with no text is
|
|
53
|
+
/// announced as nothing, and a reader tabbing the header row cannot tell what it is. The label
|
|
54
|
+
/// still names the column's filter popover and its sort button, so it must stay meaningful.</summary>
|
|
55
|
+
public bool LabelHidden { get; init; }
|
|
56
|
+
|
|
50
57
|
/// <summary>Show a sort toggle in the header.</summary>
|
|
51
58
|
public bool Sortable { get; init; }
|
|
52
59
|
|
|
@@ -24,6 +24,16 @@ export interface FdyTableColumn<T> {
|
|
|
24
24
|
key: string;
|
|
25
25
|
/** Header label. */
|
|
26
26
|
label: string;
|
|
27
|
+
/**
|
|
28
|
+
* Render the label for assistive tech only — the header cell looks empty.
|
|
29
|
+
*
|
|
30
|
+
* For a column of row CONTROLS (an edit button, a row menu), where a visible
|
|
31
|
+
* heading is noise above a column of icons but the column still has to be
|
|
32
|
+
* named: a `<th>` with no text is announced as nothing, and a reader tabbing
|
|
33
|
+
* the header row cannot tell what it is. The label still names the column's
|
|
34
|
+
* filter popover and its sort button, so it must stay meaningful.
|
|
35
|
+
*/
|
|
36
|
+
labelHidden?: boolean;
|
|
27
37
|
/** Show a sort toggle in the header. */
|
|
28
38
|
sortable?: boolean;
|
|
29
39
|
/** Offer a column filter of this type. */
|
|
@@ -271,9 +271,11 @@ export function FdyTable<Row extends object>(props: FdyTableProps<Row>): JSX.Ele
|
|
|
271
271
|
{props.columns.map((col: FdyTableColumn<Row>): JSX.Element => (
|
|
272
272
|
<th key={col.key} scope="col" style={alignStyle(col)} aria-sort={ariaSortOf(col)}>
|
|
273
273
|
{col.sortable ? (
|
|
274
|
-
<button type="button" className="fdy-table__sortbtn" onClick={(): void => onSort(col)}>
|
|
274
|
+
<button type="button" className="fdy-table__sortbtn" onClick={(): void => onSort(col)}>
|
|
275
|
+
<span className={col.labelHidden ? 'fdy-visually-hidden' : undefined}>{col.label}</span>
|
|
276
|
+
</button>
|
|
275
277
|
) : (
|
|
276
|
-
col.label
|
|
278
|
+
<span className={col.labelHidden ? 'fdy-visually-hidden' : undefined}>{col.label}</span>
|
|
277
279
|
)}
|
|
278
280
|
{col.filter && (
|
|
279
281
|
<FdyTableFilter
|
|
@@ -280,8 +280,8 @@ function isExpanded(row: Row): boolean {
|
|
|
280
280
|
type="button"
|
|
281
281
|
class="fdy-table__sortbtn"
|
|
282
282
|
@click="onSort(col)"
|
|
283
|
-
>{{ col.label }}</button>
|
|
284
|
-
<
|
|
283
|
+
><span :class="col.labelHidden ? 'fdy-visually-hidden' : undefined">{{ col.label }}</span></button>
|
|
284
|
+
<span v-else :class="col.labelHidden ? 'fdy-visually-hidden' : undefined">{{ col.label }}</span>
|
|
285
285
|
<FdyTableFilter
|
|
286
286
|
v-if="col.filter"
|
|
287
287
|
:label="col.label"
|