@tristan2828/ui-foundation 4.30.1 → 4.31.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.
|
@@ -390,8 +390,11 @@ is a filled-in example while the Widgets demo is still here).
|
|
|
390
390
|
- **A source credit** (`footer`), only when the record's data comes
|
|
391
391
|
from an outside service whose terms ask for one (many free APIs
|
|
392
392
|
do: a film database, a games catalogue): `<SourceCredit sources={[{
|
|
393
|
-
name, href, note }]} />`, with `note` the sentence the terms ask
|
|
394
|
-
word for word
|
|
393
|
+
name, href, note, icon }]} />`, with `note` the sentence the terms ask
|
|
394
|
+
for, word for word, and `icon` the service's mark when the app has
|
|
395
|
+
one (the same component it shows for that service elsewhere; drawn
|
|
396
|
+
before the name, which stays the link's text). Logos and their rules
|
|
397
|
+
are the app's own.
|
|
395
398
|
- **Every value renders the way its table cell does**: badges, names
|
|
396
399
|
of linked records, a done-count, from the shared lookups in
|
|
397
400
|
`<entity>-format.ts`. Never re-derive one for the view.
|
|
@@ -104,7 +104,8 @@ lower; say so in a comment.
|
|
|
104
104
|
## Logos and brand marks
|
|
105
105
|
|
|
106
106
|
An app's own logo (`AppShell`'s `logo`) and the marks of the services it
|
|
107
|
-
links to (a video site's mark on "Open on …", on a `WidgetCard` about it
|
|
107
|
+
links to (a video site's mark on "Open on …", on a `WidgetCard` about it,
|
|
108
|
+
beside its name in a `SourceCredit`)
|
|
108
109
|
are **icon components** (`IconComponent`): sized by a `size-*` class,
|
|
109
110
|
`aria-hidden` passed through to the `<svg>`, with the same props as a
|
|
110
111
|
Lucide icon, so they go wherever an icon goes. Lucide has no brand logos,
|
|
@@ -143,7 +144,8 @@ Colour them in one of two ways:
|
|
|
143
144
|
one-colour mark there.
|
|
144
145
|
|
|
145
146
|
The package's own stories show the slots with made-up marks in
|
|
146
|
-
`currentColor` (`app/AppShell` With logo, `app/WidgetCard` Brand mark
|
|
147
|
+
`currentColor` (`app/AppShell` With logo, `app/WidgetCard` Brand mark,
|
|
148
|
+
`app/EntityView` Notice and footer).
|
|
147
149
|
|
|
148
150
|
## Categorical colour
|
|
149
151
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { IconComponent } from './icon-component.js';
|
|
1
2
|
export type Source = {
|
|
2
3
|
/** The service's name, the link's text: "TMDB". */
|
|
3
4
|
name: string;
|
|
@@ -5,6 +6,12 @@ export type Source = {
|
|
|
5
6
|
href: string;
|
|
6
7
|
/** A sentence the service's terms ask for, shown after the list as written. */
|
|
7
8
|
note?: string;
|
|
9
|
+
/**
|
|
10
|
+
* The service's mark, drawn before its name inside the link and hidden
|
|
11
|
+
* from screen readers: the name stays the link's text. The app's own
|
|
12
|
+
* component, the one it shows for this service elsewhere.
|
|
13
|
+
*/
|
|
14
|
+
icon?: IconComponent;
|
|
8
15
|
};
|
|
9
16
|
export type SourceCreditProps = {
|
|
10
17
|
sources: Source[];
|
|
@@ -2,8 +2,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
// Credits the outside services a record's data comes from, as many free
|
|
3
3
|
// APIs require on every screen showing their data ("This product uses the
|
|
4
4
|
// TMDB API but is not endorsed or certified by TMDB"). EntityView's
|
|
5
|
-
// `footer` is its usual home.
|
|
6
|
-
// its usage rules are the app's.
|
|
5
|
+
// `footer` is its usual home. A source's mark is the app's own icon
|
|
6
|
+
// component (`icon`), drawn before its name; its usage rules are the app's.
|
|
7
7
|
import { Fragment } from 'react';
|
|
8
8
|
import { ExternalLinkIcon } from 'lucide-react';
|
|
9
9
|
function joined(index, count) {
|
|
@@ -17,5 +17,5 @@ export function SourceCredit({ sources, lead = 'Data from' }) {
|
|
|
17
17
|
if (sources.length === 0)
|
|
18
18
|
return null;
|
|
19
19
|
const notes = sources.flatMap((source) => (source.note ? [source.note] : []));
|
|
20
|
-
return (_jsxs("p", { "data-slot": "source-credit", className: "type-caption text-muted-foreground", children: [lead, ' ', sources.map((source, index) => (_jsxs(Fragment, { children: [joined(index, sources.length), _jsxs("a", { href: source.href, target: "_blank", rel: "noreferrer", className: "rounded-sm underline underline-offset-2 outline-none hover:text-foreground focus-visible:ring-3 focus-visible:ring-ring/50", children: [source.name, _jsx(ExternalLinkIcon, { "aria-hidden": "true", className: "ml-0.5 inline size-3 align-baseline" }), _jsx("span", { className: "sr-only", children: " (opens in a new tab)" })] })] }, source.name))), ".", notes.map((note) => ` ${note}`).join('')] }));
|
|
20
|
+
return (_jsxs("p", { "data-slot": "source-credit", className: "type-caption text-muted-foreground", children: [lead, ' ', sources.map(({ icon: Icon, ...source }, index) => (_jsxs(Fragment, { children: [joined(index, sources.length), _jsxs("a", { href: source.href, target: "_blank", rel: "noreferrer", className: "rounded-sm underline underline-offset-2 outline-none hover:text-foreground focus-visible:ring-3 focus-visible:ring-ring/50", children: [Icon && _jsx(Icon, { "aria-hidden": "true", className: "mr-1 inline size-3.5 align-text-bottom" }), source.name, _jsx(ExternalLinkIcon, { "aria-hidden": "true", className: "ml-0.5 inline size-3 align-baseline" }), _jsx("span", { className: "sr-only", children: " (opens in a new tab)" })] })] }, source.name))), ".", notes.map((note) => ` ${note}`).join('')] }));
|
|
21
21
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tristan2828/ui-foundation",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.31.0",
|
|
4
4
|
"description": "Shared UI foundation for contract-first, database-backed React apps: shadcn primitives, DataTable/EntityForm composites, auth, the gateway error seam, design tokens, lint rules and the AI playbook.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|