@atelic-action/artifact 1.1.0 → 1.3.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/README.md +8 -8
- package/package.json +3 -3
- package/src/documents/Note.tsx +6 -4
- package/src/documents/Read.tsx +26 -9
- package/src/documents/Writeup.tsx +3 -3
- package/src/documents/documents.css +38 -61
- package/src/documents/Paragraph.tsx +0 -65
- package/src/documents/Shot.tsx +0 -38
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ The documents the practice hands or sends a business, as a published package and
|
|
|
7
7
|
|
|
8
8
|
Three layers, each a version the next depends on (ATE-671): `@atelic-action/ui` holds the pieces, this package holds the documents built from them, and each business's folder holds only its content, routes, and config. A document fix reaches a folder by bumping this package; a piece fix by bumping ui here, then this package in the folder.
|
|
9
9
|
|
|
10
|
-
Five artifacts live in the template site: the **writeup** at `/writeup`, the graded document an owner gets, a web page first with its printed copy derived from it; the **read** at `/read`, what a customer gets at the end of an engagement's first week, the baseline's grades explained by cause with the plan in order; the **proposal** at `/proposal`, sealed into the page and opened by the reader's own email address; the **monthly page** at `/report`, what an Operate client gets each month on one letter sheet; and the **note** at `/notes`, the first touch for a business whose site publishes no email address, set as a short page. The bare host sends a reader to the writeup. Every artifact prerenders to static HTML, stays out of every index, and carries the practice's brand by default.
|
|
10
|
+
Five artifacts live in the template site: the **writeup** at `/writeup`, the graded document an owner gets, a web page first with its printed copy derived from it; the **read** at `/the-read`, what a customer gets at the end of an engagement's first week, the baseline's grades explained by cause with the plan in order; the **proposal** at `/proposal`, sealed into the page and opened by the reader's own email address; the **monthly page** at `/report`, what an Operate client gets each month on one letter sheet; and the **note** at `/notes`, the first touch for a business whose site publishes no email address, set as a short page. The bare host sends a reader to the writeup. Every artifact prerenders to static HTML, stays out of every index, and carries the practice's brand by default.
|
|
11
11
|
|
|
12
12
|
The method behind them (the seven sections, the four grades from A to D, the rented line, what moved, and when an artifact is private) is the practice repo's `FOOTPRINT.md`. This repo builds to it and never restates it.
|
|
13
13
|
|
|
@@ -24,9 +24,9 @@ Every export of the package, all from the one entry, `@atelic-action/artifact`.
|
|
|
24
24
|
| `Writeup`, `WriteupProps` | The graded document an owner gets: the overview, the three tiers of section cards, the close | `/writeup` |
|
|
25
25
|
| `ratingCell` | A star rating table cell for a writeup table, sorted by its figure | `/writeup` |
|
|
26
26
|
| `WriteupBlock`, `WriteupTopic`, `WriteupPart`, `WriteupSheet`, `WriteupSummary`, `WriteupSummaryRow`, `WriteupMarkets`, `WriteupRented`, `WriteupMark`, `WriteupCell`, `WriteupTone`, and the rest of the `Writeup*` types | The shapes a writeup's content is written in | none |
|
|
27
|
-
| `WriteupGrade`, `WriteupPerson`, `WriteupShot` | The grade letter, the sign off person, and the owner's screen, shared by every document
|
|
28
|
-
| `Read`, `ReadProps` | The baseline's grades explained by cause: the gist table; each section read top to bottom as where we looked (the tools, linked, at the top), what it showed (a short paragraph or two, a compact table of facts, lists of examples under their own headings, and any proof pictures), why (one sentence on a tinted panel), today and after (a two column table), and what we recommend (a checklist); then the plan in order. A beat with no data is left out, heading and all | `/read` |
|
|
29
|
-
| `readLabels`, `ReadLabels` | The fixed words the read sets (Prepared for, the gist table's columns, Where We Looked, What It Showed, Why, Today, After, What We Recommend, the plan's heading), each overridable through `labels` | `/read` |
|
|
27
|
+
| `WriteupGrade`, `WriteupPerson`, `WriteupShot` | The grade letter, the sign off person, and the owner's screen, shared by every document, all three re exported from ui | none |
|
|
28
|
+
| `Read`, `ReadProps` | The baseline's grades explained by cause: the gist table, with an optional `note` callout under it for what the read leaves out; each section under its trade name with the owner's question beneath it, read top to bottom as where we looked (the tools, linked, at the top), what it showed (a short paragraph or two, a compact table of facts, lists of examples under their own headings, and any proof pictures), why (one sentence on a tinted panel), today and after (a two column table), and what we recommend (a checklist); then the plan in order. A beat with no data is left out, heading and all | `/the-read` |
|
|
29
|
+
| `readLabels`, `ReadLabels` | The fixed words the read sets (Prepared for, the gist table's columns, Where We Looked, What It Showed, Why, Today, After, What We Recommend, the plan's heading), each overridable through `labels` | `/the-read` |
|
|
30
30
|
| `ReadTier`, `ReadSection`, `ReadTool`, `ReadFact`, `ReadExamples`, `ReadChange`, `ReadStep`, `ReadPlan`, `ReadClose`, `ReadLink`, `ReadParagraph` | The shapes a read's content is written in, all plain data so a routine can write a read as JSON. A section's `tools` were its `sources` in 1.0.0; `sources` is still read, and rendered at the top as tools, and `ReadSource` names the same shape as `ReadTool` | none |
|
|
31
31
|
| `Report`, `ReportProps` | The monthly page: the four questions, the seven grades now and before, the sign off, on one letter sheet | `/report` |
|
|
32
32
|
| `ReportLead`, `ReportLeads`, `ReportGradeRow` | The shapes a monthly page's content is written in | none |
|
|
@@ -36,7 +36,7 @@ Every export of the package, all from the one entry, `@atelic-action/artifact`.
|
|
|
36
36
|
| `normalizeEmail` | How a typed address becomes the key a payload opens with; the sealing command mirrors it | none |
|
|
37
37
|
| `documents.css` | The documents' styles, at `@atelic-action/artifact/styles/documents.css` | every route |
|
|
38
38
|
|
|
39
|
-
What a document is built from stays in `@atelic-action/ui`, and this package imports it rather than copying it: `GradeChip`, `gradeLabel`, `SignOff`, and `newTabProps` from `@atelic-action/ui/artifact`; `Callout`, `Checklist`, `ColumnChart`, `DataTable`, `Disclosure`, `StackedBar`, `StatRow`, `ThresholdScale`, and their types from `@atelic-action/ui/components`; `Button` from `@atelic-action/ui/primitives`. The shell around a page (`ArtifactShell`), the head (`buildPageHead`), the contract (`ArtifactConfig`), the reader helpers, the error boundary, the access wall, the Vite configuration, and the commands are ui's too, and a site imports them from there.
|
|
39
|
+
What a document is built from stays in `@atelic-action/ui`, and this package imports it rather than copying it: `GradeChip`, `gradeLabel`, `SignOff`, `Shot` (the owner's screen), `Paragraph`, `Runs`, `isEmpty`, `ArtifactAnchor` (the plain data paragraph of the note and the read), and `newTabProps` from `@atelic-action/ui/artifact`; `Callout`, `Checklist`, `ColumnChart`, `DataTable`, `Disclosure`, `StackedBar`, `StatRow`, `ThresholdScale`, and their types from `@atelic-action/ui/components`; `Button` from `@atelic-action/ui/primitives`. The shell around a page (`ArtifactShell`), the head (`buildPageHead`), the contract (`ArtifactConfig`), the reader helpers, the error boundary, the access wall, the Vite configuration, and the commands are ui's too, and a site imports them from there.
|
|
40
40
|
|
|
41
41
|
## Install
|
|
42
42
|
|
|
@@ -44,7 +44,7 @@ What a document is built from stays in `@atelic-action/ui`, and this package imp
|
|
|
44
44
|
bun add @atelic-action/artifact @atelic-action/ui
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
Peer dependencies: `@atelic-action/ui` at `^
|
|
47
|
+
Peer dependencies: `@atelic-action/ui` at `^2.0.0`, `react` at `^19.0.0`, and `lucide-react` at `^1.23.0`. The package ships TSX and CSS as source, compiled inside the site's own Vite like ui's; a site whose `vite.config.ts` is one `artifactConfig` call from `@atelic-action/ui/vite` needs nothing more, for the build, the prerender, and the dev server alike. The default labels a document sets live in the document: the read's `readLabels` and the sealed document's gate copy are overridden through props, and the monthly page's four questions are fixed on purpose, since they are its contract with the Statement of Work.
|
|
48
48
|
|
|
49
49
|
```tsx
|
|
50
50
|
import { Writeup } from "@atelic-action/artifact";
|
|
@@ -57,13 +57,13 @@ The documents' sheet goes after every ui sheet and before the site's `theme.css`
|
|
|
57
57
|
|
|
58
58
|
1. The site's fonts (`fonts.css`)
|
|
59
59
|
2. `@atelic-action/ui/styles/base.css`, `chrome.css`, `components.css`, `primitives.css`, and `gate.css`, in that order
|
|
60
|
-
3. `@atelic-action/ui/styles/artifact.css`, the pieces the documents share (the grade chip, the sign off, the shell's logo)
|
|
60
|
+
3. `@atelic-action/ui/styles/artifact.css`, the pieces the documents share (the grade chip, the sign off, the shot, the shell's logo, and the shell's print rules that drop the header, the credit band, and the skip link); it sets no `@page`
|
|
61
61
|
4. `@atelic-action/artifact/styles/documents.css`
|
|
62
62
|
5. The site's `theme.css`, last
|
|
63
63
|
|
|
64
64
|
Every rule in the sheet sits in the `atelic-ui` layer and under the `.atelic-ui` root class, exactly as ui's sheets do, so any rule a site writes outside a layer still wins over it. The sheet holds two `@page` rules, the monthly page's and then the writeup's, and the later one wins for every page a site prints; their order is load bearing.
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
From 1.2.0 the two sheets do not overlap: ui 2.0.0's `artifact.css` holds only the pieces, and this sheet holds only the documents and both `@page` rules. A site on ui 1.x stays on artifact 1.1.x, which carries the shot's rules and the shell's print rules itself.
|
|
67
67
|
|
|
68
68
|
## Tech Stack
|
|
69
69
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atelic-action/artifact",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "The composed documents the Atelic practice hands or sends a business (the writeup, the read, the monthly page, the note, and the sealed document), built from the pieces in @atelic-action/ui",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -37,12 +37,12 @@
|
|
|
37
37
|
"format": "biome format . --write"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
|
-
"@atelic-action/ui": "^
|
|
40
|
+
"@atelic-action/ui": "^2.0.0",
|
|
41
41
|
"lucide-react": "^1.23.0",
|
|
42
42
|
"react": "^19.0.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@atelic-action/ui": "^
|
|
45
|
+
"@atelic-action/ui": "^2.0.0",
|
|
46
46
|
"@biomejs/biome": "^2.0.0",
|
|
47
47
|
"@playwright/test": "^1.60.0",
|
|
48
48
|
"@sentry/react": "^10.0.0",
|
package/src/documents/Note.tsx
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import { SignOff, type WriteupPerson } from "@atelic-action/ui/artifact";
|
|
2
|
-
import { Callout } from "@atelic-action/ui/components";
|
|
3
1
|
import {
|
|
4
2
|
type ArtifactLink,
|
|
5
3
|
type ArtifactParagraph,
|
|
6
4
|
isEmpty,
|
|
7
5
|
ArtifactAnchor as NoteAnchor,
|
|
8
6
|
Paragraph,
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
Shot,
|
|
8
|
+
SignOff,
|
|
9
|
+
type WriteupPerson,
|
|
10
|
+
type WriteupShot,
|
|
11
|
+
} from "@atelic-action/ui/artifact";
|
|
12
|
+
import { Callout } from "@atelic-action/ui/components";
|
|
11
13
|
|
|
12
14
|
/**
|
|
13
15
|
* The note: the first touch, for a business whose site publishes no email
|
package/src/documents/Read.tsx
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
|
+
type ArtifactLink,
|
|
3
|
+
type ArtifactParagraph,
|
|
2
4
|
GradeChip,
|
|
3
5
|
gradeLabel,
|
|
6
|
+
isEmpty,
|
|
4
7
|
newTabProps,
|
|
8
|
+
Paragraph,
|
|
9
|
+
Runs,
|
|
10
|
+
Shot,
|
|
5
11
|
SignOff,
|
|
6
12
|
type WriteupGrade,
|
|
7
13
|
type WriteupPerson,
|
|
14
|
+
type WriteupShot,
|
|
8
15
|
} from "@atelic-action/ui/artifact";
|
|
9
16
|
import { ArrowUpRight, Check } from "lucide-react";
|
|
10
|
-
import { type ArtifactLink, type ArtifactParagraph, isEmpty, Paragraph, Runs } from "./Paragraph";
|
|
11
|
-
import { Shot, type WriteupShot } from "./Shot";
|
|
12
17
|
|
|
13
18
|
/**
|
|
14
19
|
* The read: what a customer gets at the end of an engagement's first week,
|
|
@@ -19,7 +24,8 @@ import { Shot, type WriteupShot } from "./Shot";
|
|
|
19
24
|
* plan, in order; then one closing line and the sign off.
|
|
20
25
|
*
|
|
21
26
|
* Each section reads as an aggregator of the tools we looked through, top to
|
|
22
|
-
* bottom
|
|
27
|
+
* bottom, under its trade name with the owner's question beneath it: where
|
|
28
|
+
* we looked (the tools, linked, each with an optional line);
|
|
23
29
|
* what it showed (a short paragraph or two, a compact table of facts, lists
|
|
24
30
|
* of examples, and any proof pictures); why, in one sentence on a tinted
|
|
25
31
|
* panel; today and after, a two column table of what a thing is and what it
|
|
@@ -31,7 +37,8 @@ import { Shot, type WriteupShot } from "./Shot";
|
|
|
31
37
|
* (the `.op` classes), and adds only what is its own (the `.rd` classes).
|
|
32
38
|
* The gist table is drawn from the tiers, so a tier added later (Conversion,
|
|
33
39
|
* once the analytics access lands) is one more entry in `tiers` and appears
|
|
34
|
-
* in the table and the body alike, with no change to the props
|
|
40
|
+
* in the table and the body alike, with no change to the props; until then
|
|
41
|
+
* `note` says so in a callout under the table. Every prop
|
|
35
42
|
* is plain data, so a routine can write a read as JSON; the one exception is
|
|
36
43
|
* the sign off person's `role`, which takes a node and is equally happy with
|
|
37
44
|
* a string.
|
|
@@ -76,9 +83,9 @@ export interface ReadChange {
|
|
|
76
83
|
export interface ReadSection {
|
|
77
84
|
/** The anchor the gist table links to, e.g. "technical-seo". */
|
|
78
85
|
id: string;
|
|
79
|
-
/** The section's trade name, e.g. "Technical SEO": the
|
|
86
|
+
/** The section's trade name, e.g. "Technical SEO": the section's heading, and the gist table's Section column. */
|
|
80
87
|
name: string;
|
|
81
|
-
/** The question the section answers, in the owner's words, e.g. "Can Google read the site?"
|
|
88
|
+
/** The question the section answers, in the owner's words, e.g. "Can Google read the site?", set under the heading. */
|
|
82
89
|
question: string;
|
|
83
90
|
/** The baseline's grade. Omit for a section not yet graded; the table shows a quiet dash. */
|
|
84
91
|
grade?: WriteupGrade;
|
|
@@ -195,6 +202,8 @@ export interface ReadProps {
|
|
|
195
202
|
lede: ReadParagraph;
|
|
196
203
|
/** The heading over the gist table, e.g. "At a Glance". */
|
|
197
204
|
gistTitle?: string;
|
|
205
|
+
/** A callout under the gist table, e.g. what the read leaves out and when it follows. */
|
|
206
|
+
note?: ReadParagraph;
|
|
198
207
|
/** The key: what each letter means, in a few words each. */
|
|
199
208
|
gradeKey?: Array<{ grade: WriteupGrade; label: string }>;
|
|
200
209
|
/** The tiers in order. Each section appears in the gist table and in the body. */
|
|
@@ -403,8 +412,8 @@ function Section({ section, labels }: { section: ReadSection; labels: ReadLabels
|
|
|
403
412
|
<section className="op-topic rd-section" id={section.id}>
|
|
404
413
|
<header className="op-topic-head">
|
|
405
414
|
<div>
|
|
406
|
-
<
|
|
407
|
-
<
|
|
415
|
+
<h3>{section.name}</h3>
|
|
416
|
+
<p className="rd-question">{section.question}</p>
|
|
408
417
|
</div>
|
|
409
418
|
{section.grade && (
|
|
410
419
|
<>
|
|
@@ -495,6 +504,7 @@ export function Read({
|
|
|
495
504
|
date,
|
|
496
505
|
lede,
|
|
497
506
|
gistTitle,
|
|
507
|
+
note,
|
|
498
508
|
gradeKey,
|
|
499
509
|
tiers,
|
|
500
510
|
plan,
|
|
@@ -518,7 +528,14 @@ export function Read({
|
|
|
518
528
|
{filled(lede) && <Paragraph paragraph={lede} className="op-intro rd-lede" />}
|
|
519
529
|
</header>
|
|
520
530
|
{shownTiers.length > 0 && (
|
|
521
|
-
|
|
531
|
+
<>
|
|
532
|
+
<Gist tiers={shownTiers} title={gistTitle} gradeKey={gradeKey} labels={labels} />
|
|
533
|
+
{filled(note) && (
|
|
534
|
+
<div className="rd-note" role="note">
|
|
535
|
+
<Paragraph paragraph={note} />
|
|
536
|
+
</div>
|
|
537
|
+
)}
|
|
538
|
+
</>
|
|
522
539
|
)}
|
|
523
540
|
{shownTiers.map((tier) => (
|
|
524
541
|
<div className="rd-tier" key={tier.title}>
|
|
@@ -2,9 +2,11 @@ import {
|
|
|
2
2
|
GradeChip,
|
|
3
3
|
gradeLabel,
|
|
4
4
|
newTabProps,
|
|
5
|
+
Shot,
|
|
5
6
|
SignOff,
|
|
6
7
|
type WriteupGrade,
|
|
7
8
|
type WriteupPerson,
|
|
9
|
+
type WriteupShot,
|
|
8
10
|
} from "@atelic-action/ui/artifact";
|
|
9
11
|
import {
|
|
10
12
|
Callout,
|
|
@@ -25,10 +27,8 @@ import {
|
|
|
25
27
|
} from "@atelic-action/ui/components";
|
|
26
28
|
import { ArrowUpRight, ChevronRight, CircleAlert, CircleCheck, CircleX, Star } from "lucide-react";
|
|
27
29
|
import type { ReactNode } from "react";
|
|
28
|
-
import { Shot, type WriteupShot } from "./Shot";
|
|
29
30
|
|
|
30
|
-
export type { WriteupGrade, WriteupPerson } from "@atelic-action/ui/artifact";
|
|
31
|
-
export type { WriteupShot } from "./Shot";
|
|
31
|
+
export type { WriteupGrade, WriteupPerson, WriteupShot } from "@atelic-action/ui/artifact";
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* The writeup: the graded document an owner gets. It is a web page first: an
|
|
@@ -7,11 +7,14 @@
|
|
|
7
7
|
writeup's stays the one that wins.
|
|
8
8
|
|
|
9
9
|
The pieces the documents share stay in @atelic-action/ui: the grade chip
|
|
10
|
-
(.op-grade), the sign off (.op-who, .op-sign),
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
(.op-grade), the sign off (.op-who, .op-sign), the shot (.op-shot), the
|
|
11
|
+
shell's logo rule, and the shell's print rules that drop the header, the
|
|
12
|
+
credit band, and the skip link on every artifact page, in its
|
|
13
|
+
styles/artifact.css, which sets no @page; the login screen's vocabulary
|
|
14
|
+
the sealed stage reuses, in its styles/gate.css; the page components (the
|
|
15
|
+
callout, the checklist, the table, the charts), in its
|
|
16
|
+
styles/components.css. Import this sheet after all of them and before the
|
|
17
|
+
site's theme.css. Both @page rules live only here.
|
|
15
18
|
|
|
16
19
|
Every rule sits in the same atelic-ui layer as the package sheets, so any
|
|
17
20
|
rule a site writes outside a layer still wins over it whatever its
|
|
@@ -521,7 +524,8 @@
|
|
|
521
524
|
never reflowed, so a print of one sheet is the check.
|
|
522
525
|
|
|
523
526
|
Tokens only (theme.css), except the printed sheet's white. The grade
|
|
524
|
-
chip
|
|
527
|
+
chip, the sign off, and the print rule that drops the header and the
|
|
528
|
+
credit band are the shared classes in @atelic-action/ui's
|
|
525
529
|
styles/artifact.css.
|
|
526
530
|
================================================================= */
|
|
527
531
|
.atelic-ui .rp {
|
|
@@ -797,11 +801,6 @@
|
|
|
797
801
|
padding: 0;
|
|
798
802
|
background: none;
|
|
799
803
|
}
|
|
800
|
-
.atelic-ui:has(.rp) .nav,
|
|
801
|
-
.atelic-ui:has(.rp) .skip-link,
|
|
802
|
-
.atelic-ui:has(.rp) .credit-bar {
|
|
803
|
-
display: none;
|
|
804
|
-
}
|
|
805
804
|
.atelic-ui .rp {
|
|
806
805
|
padding: 0;
|
|
807
806
|
background: none;
|
|
@@ -1345,33 +1344,6 @@
|
|
|
1345
1344
|
gap: 14px;
|
|
1346
1345
|
max-width: 340px;
|
|
1347
1346
|
}
|
|
1348
|
-
.atelic-ui .op-shot {
|
|
1349
|
-
display: flex;
|
|
1350
|
-
flex-direction: column;
|
|
1351
|
-
gap: 6px;
|
|
1352
|
-
margin: 0;
|
|
1353
|
-
}
|
|
1354
|
-
.atelic-ui .op-shot a,
|
|
1355
|
-
.atelic-ui .op-shot-frame {
|
|
1356
|
-
display: block;
|
|
1357
|
-
width: 100%;
|
|
1358
|
-
border-radius: var(--radius-sm);
|
|
1359
|
-
overflow: hidden;
|
|
1360
|
-
border: 1px solid var(--neutral-200);
|
|
1361
|
-
background: var(--op-card);
|
|
1362
|
-
}
|
|
1363
|
-
.atelic-ui .op-shot a {
|
|
1364
|
-
cursor: zoom-in;
|
|
1365
|
-
}
|
|
1366
|
-
/* The expand badge on a linked crop: off here, the note turns it on. */
|
|
1367
|
-
.atelic-ui .op-shot-open {
|
|
1368
|
-
display: none;
|
|
1369
|
-
}
|
|
1370
|
-
.atelic-ui .op-shot img {
|
|
1371
|
-
width: 100%;
|
|
1372
|
-
height: auto;
|
|
1373
|
-
display: block;
|
|
1374
|
-
}
|
|
1375
1347
|
.atelic-ui .op-shot-brief {
|
|
1376
1348
|
display: grid;
|
|
1377
1349
|
place-items: center;
|
|
@@ -1384,11 +1356,6 @@
|
|
|
1384
1356
|
padding: 12px;
|
|
1385
1357
|
text-align: center;
|
|
1386
1358
|
}
|
|
1387
|
-
.atelic-ui .op-shot figcaption {
|
|
1388
|
-
font-size: 12.5px;
|
|
1389
|
-
line-height: 1.45;
|
|
1390
|
-
color: var(--op-ink-faint);
|
|
1391
|
-
}
|
|
1392
1359
|
|
|
1393
1360
|
/* sources: the tools the readings came from */
|
|
1394
1361
|
.atelic-ui .op-sources {
|
|
@@ -1715,9 +1682,6 @@
|
|
|
1715
1682
|
html:has(.atelic-ui .op-doc) {
|
|
1716
1683
|
zoom: 0.74;
|
|
1717
1684
|
}
|
|
1718
|
-
.atelic-ui .nav,
|
|
1719
|
-
.atelic-ui .credit-bar,
|
|
1720
|
-
.atelic-ui .skip-link,
|
|
1721
1685
|
.atelic-ui .op-ov-go,
|
|
1722
1686
|
.atelic-ui .op-topic h3 a svg {
|
|
1723
1687
|
display: none;
|
|
@@ -1808,9 +1772,6 @@
|
|
|
1808
1772
|
.atelic-ui .data-table thead {
|
|
1809
1773
|
break-after: avoid;
|
|
1810
1774
|
}
|
|
1811
|
-
.atelic-ui .op-shot a {
|
|
1812
|
-
cursor: auto;
|
|
1813
|
-
}
|
|
1814
1775
|
.atelic-ui .op-twin {
|
|
1815
1776
|
display: flex;
|
|
1816
1777
|
align-items: center;
|
|
@@ -1851,17 +1812,17 @@
|
|
|
1851
1812
|
aligned; the screen's column sizes to the picture, a phone crop
|
|
1852
1813
|
about 260px and a wide card up to 45% of the row. A finding
|
|
1853
1814
|
with no screen takes the full width.
|
|
1854
|
-
- Print: one letter sheet. The chrome steps aside (
|
|
1855
|
-
|
|
1856
|
-
|
|
1815
|
+
- Print: one letter sheet. The chrome steps aside (ui's artifact.css
|
|
1816
|
+
hides the header and the credit band on any artifact page), the
|
|
1817
|
+
type comes down, and the screens shrink. The note sets
|
|
1857
1818
|
no @page of its own: the writeup's, the later one in this sheet,
|
|
1858
1819
|
sets letter paper for every artifact page.
|
|
1859
1820
|
|
|
1860
1821
|
Tokens only. The finding is the shared Callout (@atelic-action/ui's components.css),
|
|
1861
|
-
the screen the
|
|
1822
|
+
the screen the shared .op-shot, the sign off the shared .op-who;
|
|
1862
1823
|
this sheet sets the letter around them and their sizes here.
|
|
1863
1824
|
================================================================= */
|
|
1864
|
-
/* The
|
|
1825
|
+
/* The shared .op-shot reads the writeup's own two tokens, mapped here as
|
|
1865
1826
|
the writeup's .op root maps them. */
|
|
1866
1827
|
.atelic-ui .nt {
|
|
1867
1828
|
--op-card: var(--card);
|
|
@@ -2210,6 +2171,7 @@
|
|
|
2210
2171
|
|
|
2211
2172
|
/* Prose links read as links here, where the writeup's are quiet. */
|
|
2212
2173
|
.atelic-ui .rd-lede a,
|
|
2174
|
+
.atelic-ui .rd-note a,
|
|
2213
2175
|
.atelic-ui .rd-beat a,
|
|
2214
2176
|
.atelic-ui .rd-gist-read a,
|
|
2215
2177
|
.atelic-ui .rd-plan a,
|
|
@@ -2290,13 +2252,13 @@
|
|
|
2290
2252
|
}
|
|
2291
2253
|
|
|
2292
2254
|
/* ---- a section: the trade name over the question, then its beats ---- */
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
font-size:
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2255
|
+
/* The owner's question sits under the section's name. */
|
|
2256
|
+
.atelic-ui .rd-question {
|
|
2257
|
+
margin: 4px 0 0;
|
|
2258
|
+
font-size: 15.5px;
|
|
2259
|
+
line-height: 1.4;
|
|
2260
|
+
color: var(--op-ink-soft);
|
|
2261
|
+
text-wrap: pretty;
|
|
2300
2262
|
}
|
|
2301
2263
|
.atelic-ui .rd-grade .op-grade {
|
|
2302
2264
|
width: 42px;
|
|
@@ -2422,6 +2384,20 @@
|
|
|
2422
2384
|
.atelic-ui .rd-examples li + li {
|
|
2423
2385
|
margin-top: 4px;
|
|
2424
2386
|
}
|
|
2387
|
+
/* The note under the gist table: what the read leaves out, on the why panel's tint. */
|
|
2388
|
+
.atelic-ui .rd-note {
|
|
2389
|
+
margin-top: 18px;
|
|
2390
|
+
padding: 12px 14px;
|
|
2391
|
+
border-left: 3px solid var(--op-accent);
|
|
2392
|
+
border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
|
|
2393
|
+
background: var(--surface-alt);
|
|
2394
|
+
}
|
|
2395
|
+
.atelic-ui .rd-note p {
|
|
2396
|
+
font-size: 15.5px;
|
|
2397
|
+
line-height: 1.5;
|
|
2398
|
+
color: var(--op-ink);
|
|
2399
|
+
text-wrap: pretty;
|
|
2400
|
+
}
|
|
2425
2401
|
/* Why is one sentence, set apart: a tinted panel with the accent's rule. */
|
|
2426
2402
|
.atelic-ui .rd-why {
|
|
2427
2403
|
padding: 12px 14px;
|
|
@@ -2707,6 +2683,7 @@
|
|
|
2707
2683
|
.atelic-ui .rd-tools,
|
|
2708
2684
|
.atelic-ui .rd-checks li,
|
|
2709
2685
|
.atelic-ui .rd-closing,
|
|
2686
|
+
.atelic-ui .rd-note,
|
|
2710
2687
|
.atelic-ui .rd-why,
|
|
2711
2688
|
.atelic-ui .rd-step,
|
|
2712
2689
|
.atelic-ui .rd-close,
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { newTabProps } from "@atelic-action/ui/artifact";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Plain data text for the documents a routine can write as JSON (the note
|
|
5
|
-
* and the read): a paragraph is a string, or runs of text and links in
|
|
6
|
-
* order. A link opens in a new tab when it leaves the page, and in place
|
|
7
|
-
* when it is an anchor or a mail link.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
/** A link inside running text: the words the reader clicks and where they go. */
|
|
11
|
-
export interface ArtifactLink {
|
|
12
|
-
text: string;
|
|
13
|
-
href: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/** A paragraph: a plain string, or runs of text and links in order. */
|
|
17
|
-
export type ArtifactParagraph = string | Array<string | ArtifactLink>;
|
|
18
|
-
|
|
19
|
-
/** A link opens in a new tab when it leaves the page, and in place when it is an anchor or a mail link. */
|
|
20
|
-
export function ArtifactAnchor({ href, children }: { href: string; children: string }) {
|
|
21
|
-
return (
|
|
22
|
-
<a href={href} {...newTabProps(href, /^https?:/i.test(href))}>
|
|
23
|
-
{children}
|
|
24
|
-
</a>
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/** A paragraph with nothing to read: a blank string, or runs that are all blank strings. A link always counts. */
|
|
29
|
-
export function isEmpty(paragraph: ArtifactParagraph): boolean {
|
|
30
|
-
const runs = typeof paragraph === "string" ? [paragraph] : paragraph;
|
|
31
|
-
return runs.every((run) => typeof run === "string" && run.trim() === "");
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/** The runs alone, for a container that is not a paragraph (a list item, a table cell). */
|
|
35
|
-
export function Runs({ paragraph }: { paragraph: ArtifactParagraph }) {
|
|
36
|
-
const runs = typeof paragraph === "string" ? [paragraph] : paragraph;
|
|
37
|
-
return (
|
|
38
|
-
<>
|
|
39
|
-
{runs.map((run, i) =>
|
|
40
|
-
typeof run === "string" ? (
|
|
41
|
-
run
|
|
42
|
-
) : (
|
|
43
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: runs are static content in a fixed order
|
|
44
|
-
<ArtifactAnchor href={run.href} key={i}>
|
|
45
|
-
{run.text}
|
|
46
|
-
</ArtifactAnchor>
|
|
47
|
-
),
|
|
48
|
-
)}
|
|
49
|
-
</>
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export function Paragraph({
|
|
54
|
-
paragraph,
|
|
55
|
-
className,
|
|
56
|
-
}: {
|
|
57
|
-
paragraph: ArtifactParagraph;
|
|
58
|
-
className?: string;
|
|
59
|
-
}) {
|
|
60
|
-
return (
|
|
61
|
-
<p className={className}>
|
|
62
|
-
<Runs paragraph={paragraph} />
|
|
63
|
-
</p>
|
|
64
|
-
);
|
|
65
|
-
}
|
package/src/documents/Shot.tsx
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { newTabProps } from "@atelic-action/ui/artifact";
|
|
2
|
-
import { Maximize2 } from "lucide-react";
|
|
3
|
-
|
|
4
|
-
export interface WriteupShot {
|
|
5
|
-
/** The crop shown on the page. */
|
|
6
|
-
src: string;
|
|
7
|
-
alt: string;
|
|
8
|
-
/** The full screenshot the crop opens in a new tab; omit to render the crop alone. */
|
|
9
|
-
href?: string;
|
|
10
|
-
caption: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* The owner's own screen: the crop, opening the full screenshot in a new tab
|
|
15
|
-
* when it has one, over its caption. The writeup and the note both wear it;
|
|
16
|
-
* its styles (.op-shot) are the writeup's, and the note only sizes it. A
|
|
17
|
-
* linked crop says it opens: a hover title, and an expand badge the note
|
|
18
|
-
* shows on its thumbnails and the writeup keeps hidden.
|
|
19
|
-
*/
|
|
20
|
-
export function Shot({ shot }: { shot: WriteupShot }) {
|
|
21
|
-
return (
|
|
22
|
-
<figure className="op-shot">
|
|
23
|
-
{shot.href ? (
|
|
24
|
-
<a href={shot.href} title="Open the full picture" {...newTabProps(shot.href, true)}>
|
|
25
|
-
<img src={shot.src} alt={shot.alt} loading="lazy" />
|
|
26
|
-
<span className="op-shot-open" aria-hidden="true">
|
|
27
|
-
<Maximize2 size={12} />
|
|
28
|
-
</span>
|
|
29
|
-
</a>
|
|
30
|
-
) : (
|
|
31
|
-
<span className="op-shot-frame">
|
|
32
|
-
<img src={shot.src} alt={shot.alt} loading="lazy" />
|
|
33
|
-
</span>
|
|
34
|
-
)}
|
|
35
|
-
<figcaption>{shot.caption}</figcaption>
|
|
36
|
-
</figure>
|
|
37
|
-
);
|
|
38
|
-
}
|