@telepath-computer/television 0.1.97 → 0.1.99
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/dist/cli.cjs +444 -434
- package/dist/skills/television/SKILL.md +215 -198
- package/dist/skills/television-calendar/SKILL.md +99 -0
- package/dist/skills/television-table/SKILL.md +89 -0
- package/dist/views/markdown/manifest.json +1 -1
- package/dist/web/assets/{index-DOzy-86J.js → index-_dpb69va.js} +95 -95
- package/dist/web/index.html +1 -1
- package/package.json +1 -1
- package/dist/skills/artifact-calendar/SKILL.md +0 -151
- package/dist/skills/artifact-calendar/house-style.md +0 -67
- package/dist/skills/artifact-table/SKILL.md +0 -217
- package/dist/skills/artifact-table/house-style.md +0 -67
- package/dist/views/text/index.html +0 -38
- package/dist/views/text/manifest.json +0 -5
- /package/dist/skills/{artifact-calendar → television-calendar}/calendar.css +0 -0
- /package/dist/skills/{artifact-calendar → television-calendar}/calendar.js +0 -0
package/dist/web/index.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
|
6
6
|
<title>Television</title>
|
|
7
|
-
<script type="module" crossorigin src="./assets/index-
|
|
7
|
+
<script type="module" crossorigin src="./assets/index-_dpb69va.js"></script>
|
|
8
8
|
<link rel="stylesheet" crossorigin href="./assets/index-DXZ2UyQf.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body></body>
|
package/package.json
CHANGED
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: artifact-calendar
|
|
3
|
-
description: Author self-contained HTML calendar artifacts using the bundled calendar-week elements and copied calendar assets.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Authoring a calendar week
|
|
7
|
-
|
|
8
|
-
Before authoring the artifact, read `house-style.md` in this skill folder.
|
|
9
|
-
|
|
10
|
-
A working-week calendar with a generated header strip, all-day band, time axis,
|
|
11
|
-
and timed event grid. The agent only authors a single `<calendar-week>` plus
|
|
12
|
-
flat sibling `<calendar-event>` children. The component renders the rest.
|
|
13
|
-
|
|
14
|
-
## Required assets
|
|
15
|
-
|
|
16
|
-
Every calendar artifact must be self-contained. Read `calendar.css` and
|
|
17
|
-
`calendar.js` from this skill folder and carry them into the artifact output
|
|
18
|
-
instead of referencing `/skills/artifact-calendar/...` URLs.
|
|
19
|
-
|
|
20
|
-
For a Television internal artifact bundle, copy both files into the artifact's
|
|
21
|
-
`public/` directory and reference them relatively:
|
|
22
|
-
|
|
23
|
-
```html
|
|
24
|
-
<link rel="stylesheet" href="/canonical/v1/styles.css" />
|
|
25
|
-
<link rel="stylesheet" href="./calendar.css" />
|
|
26
|
-
<script type="module" src="./calendar.js"></script>
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
For a standalone single-file HTML artifact, inline the contents of
|
|
30
|
-
`calendar.css` and `calendar.js` directly into `<style>` and
|
|
31
|
-
`<script type="module">` tags so the output stays self-contained.
|
|
32
|
-
|
|
33
|
-
`calendar.js` registers the custom elements. `calendar.css` provides the
|
|
34
|
-
calendar-specific chrome styling. Do not reimplement those elements yourself.
|
|
35
|
-
|
|
36
|
-
## Markup contract
|
|
37
|
-
|
|
38
|
-
Author exactly this surface:
|
|
39
|
-
|
|
40
|
-
```html
|
|
41
|
-
<calendar-week start-date="YYYY-MM-DD" days="N" start-hour="8">
|
|
42
|
-
<calendar-event title="..." start="..." end="..." color="blue"></calendar-event>
|
|
43
|
-
<calendar-event title="..." start="..." end="..." all-day color="purple"></calendar-event>
|
|
44
|
-
</calendar-week>
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
`<calendar-week>` attributes:
|
|
48
|
-
|
|
49
|
-
- `start-date` is required and must be a real `YYYY-MM-DD` date.
|
|
50
|
-
- `days` is required and should usually be `5` or `7`.
|
|
51
|
-
- `start-hour` is optional. Omit it unless you need a fixed initial scroll
|
|
52
|
-
position.
|
|
53
|
-
|
|
54
|
-
`<calendar-event>` attributes:
|
|
55
|
-
|
|
56
|
-
- `title` is required.
|
|
57
|
-
- `start` is required.
|
|
58
|
-
- `end` is required.
|
|
59
|
-
- `all-day` is optional and presence-only. Use it only for all-day events.
|
|
60
|
-
- `color` is optional. Allowed values: `red`, `orange`, `yellow`, `green`,
|
|
61
|
-
`blue`, `purple`. Omitted or unknown values fall back to the neutral default.
|
|
62
|
-
|
|
63
|
-
## Timed vs. all-day events
|
|
64
|
-
|
|
65
|
-
Timed events:
|
|
66
|
-
|
|
67
|
-
- Omit `all-day`.
|
|
68
|
-
- Use `YYYY-MM-DDTHH:MM` wall-clock datetimes for both `start` and `end`.
|
|
69
|
-
- Keep each event within a single day.
|
|
70
|
-
|
|
71
|
-
All-day events:
|
|
72
|
-
|
|
73
|
-
- Include `all-day`.
|
|
74
|
-
- Use date-only `YYYY-MM-DD` values for both `start` and `end`.
|
|
75
|
-
- `end` is non-inclusive, following RFC 5545.
|
|
76
|
-
|
|
77
|
-
Examples:
|
|
78
|
-
|
|
79
|
-
- Single-day all-day holiday on Monday:
|
|
80
|
-
`start="2026-05-04" end="2026-05-05" all-day`
|
|
81
|
-
- Tue–Thu offsite:
|
|
82
|
-
`start="2026-05-05" end="2026-05-08" all-day`
|
|
83
|
-
- Timed design review from 11:00 to 12:30:
|
|
84
|
-
`start="2026-05-06T11:00" end="2026-05-06T12:30"`
|
|
85
|
-
|
|
86
|
-
Repeat the non-inclusive rule when you think about date spans. A Mon–Fri trip
|
|
87
|
-
is `start="2026-05-04" end="2026-05-09"`, not `end="2026-05-08"`.
|
|
88
|
-
|
|
89
|
-
## What the component auto-renders
|
|
90
|
-
|
|
91
|
-
Do not author any of these directly:
|
|
92
|
-
|
|
93
|
-
- `<calendar-headers>`
|
|
94
|
-
- `<calendar-day>`
|
|
95
|
-
- `<calendar-allday>`
|
|
96
|
-
- `<calendar-grid>`
|
|
97
|
-
- `<calendar-time-axis>`
|
|
98
|
-
- `<calendar-column>`
|
|
99
|
-
- `<calendar-cell>`
|
|
100
|
-
|
|
101
|
-
Those are internal chrome and CSS targets created by `<calendar-week>`.
|
|
102
|
-
|
|
103
|
-
## Behavior to rely on
|
|
104
|
-
|
|
105
|
-
- All-day events clip silently to the visible range.
|
|
106
|
-
- All-day events stack into lanes automatically when their visible spans
|
|
107
|
-
overlap.
|
|
108
|
-
- Timed events on the same day cascade to the right when their time ranges
|
|
109
|
-
overlap.
|
|
110
|
-
- Malformed events are silently dropped. There is no error pill or fallback UI.
|
|
111
|
-
|
|
112
|
-
## Content guidance
|
|
113
|
-
|
|
114
|
-
- Make the schedule feel real. Use plausible meeting names, owners, and time
|
|
115
|
-
blocks.
|
|
116
|
-
- Vary the event titles and use sensible durations.
|
|
117
|
-
- Use the color palette intentionally; don't paint everything the same color.
|
|
118
|
-
- Avoid placeholder text like "Lorem ipsum", "Event 1", or "Meeting".
|
|
119
|
-
|
|
120
|
-
## Minimal complete example
|
|
121
|
-
|
|
122
|
-
```html
|
|
123
|
-
<!doctype html>
|
|
124
|
-
<html lang="en">
|
|
125
|
-
<head>
|
|
126
|
-
<meta charset="UTF-8" />
|
|
127
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
128
|
-
<title>Team Week</title>
|
|
129
|
-
<link rel="stylesheet" href="/canonical/v1/styles.css" />
|
|
130
|
-
<link rel="stylesheet" href="./calendar.css" />
|
|
131
|
-
<script type="module" src="./calendar.js"></script>
|
|
132
|
-
<style>
|
|
133
|
-
html, body { margin: 0; min-height: 100vh; }
|
|
134
|
-
calendar-week { height: 100vh; }
|
|
135
|
-
</style>
|
|
136
|
-
</head>
|
|
137
|
-
<body>
|
|
138
|
-
<calendar-week start-date="2026-05-04" days="5">
|
|
139
|
-
<calendar-event title="Holiday" start="2026-05-04" end="2026-05-05" all-day color="red"></calendar-event>
|
|
140
|
-
<calendar-event title="Standup" start="2026-05-05T09:00" end="2026-05-05T09:30" color="blue"></calendar-event>
|
|
141
|
-
<calendar-event title="Design review" start="2026-05-06T11:00" end="2026-05-06T12:30" color="purple"></calendar-event>
|
|
142
|
-
</calendar-week>
|
|
143
|
-
</body>
|
|
144
|
-
</html>
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
## Non-goals
|
|
148
|
-
|
|
149
|
-
- Do not author internal chrome or custom day headers.
|
|
150
|
-
- Do not use timezones, UTC conversion, or seconds.
|
|
151
|
-
- Do not invent interaction, editing UI, filters, or legends unless asked.
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
# Authoring artifacts
|
|
2
|
-
|
|
3
|
-
You're writing a single self-contained HTML artifact that will be rendered
|
|
4
|
-
inside a Television viewer (or downloaded for offline viewing later). This
|
|
5
|
-
skill documents the conventions you must follow.
|
|
6
|
-
|
|
7
|
-
## House style
|
|
8
|
-
|
|
9
|
-
Artifacts inherit a versioned, canonical stylesheet served by the
|
|
10
|
-
Television runtime. Include it in `<head>`:
|
|
11
|
-
|
|
12
|
-
```html
|
|
13
|
-
<link rel="stylesheet" href="/canonical/v1/styles.css">
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
That stylesheet provides:
|
|
17
|
-
|
|
18
|
-
- A CSS reset and font-face declarations (Hind variable font, loaded
|
|
19
|
-
automatically — no extra link tags needed).
|
|
20
|
-
- The full design-system token catalog as CSS custom properties:
|
|
21
|
-
typography (`--text-*`, `--font-*`, `--leading-*`), spacing
|
|
22
|
-
(`--space-*`), color (`--color-*`, `--neutral-*`), radii
|
|
23
|
-
(`--radius-*`), and surfaces. The runtime source of truth is
|
|
24
|
-
`packages/ui/styles/tokens.css`; the bundle inlines it.
|
|
25
|
-
- Bare-tag styling. `body`, `a`, `h1`–`h6`, `code`, `pre`, and similar
|
|
26
|
-
semantic elements have built-in styling — you do not need to add
|
|
27
|
-
classes to make them look right.
|
|
28
|
-
|
|
29
|
-
**Lean on semantic HTML and the bare-tag styling.** Reach for `<h1>`,
|
|
30
|
-
`<p>`, `<ul>`, `<code>`, etc. before inventing custom classes. Use tokens
|
|
31
|
-
(`var(--space-8)`, `var(--color-text-muted)`, etc.) for any custom CSS
|
|
32
|
-
you do write — never hardcoded pixel values or hex colors.
|
|
33
|
-
|
|
34
|
-
## Document shape
|
|
35
|
-
|
|
36
|
-
Emit a complete HTML document, not a fragment:
|
|
37
|
-
|
|
38
|
-
```html
|
|
39
|
-
<!doctype html>
|
|
40
|
-
<html lang="en">
|
|
41
|
-
<head>
|
|
42
|
-
<meta charset="utf-8">
|
|
43
|
-
<title>{{title}}</title>
|
|
44
|
-
<link rel="stylesheet" href="/canonical/v1/styles.css">
|
|
45
|
-
</head>
|
|
46
|
-
<body>
|
|
47
|
-
<!-- artifact content -->
|
|
48
|
-
</body>
|
|
49
|
-
</html>
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## Conventions
|
|
53
|
-
|
|
54
|
-
- **Self-contained.** By default, emit one HTML file. If the active
|
|
55
|
-
kind skill ships local CSS or JS assets, copy or inline them from the
|
|
56
|
-
skill folder so the final artifact remains self-contained without any
|
|
57
|
-
`/skills/...` runtime dependency.
|
|
58
|
-
- **No arbitrary `<script>` tags.** Static HTML is the default. Only
|
|
59
|
-
include local, bundled scripts when the active kind skill explicitly
|
|
60
|
-
requires them.
|
|
61
|
-
- **No external network fetches.** No CDN links, no remote images, no
|
|
62
|
-
font URLs other than what `/canonical/v1/styles.css` already includes.
|
|
63
|
-
- **No inline `<style>` overrides for chrome-level concerns.** Small
|
|
64
|
-
layout-specific styles for the artifact's content are fine; redefining
|
|
65
|
-
brand colors or typography is not.
|
|
66
|
-
- **Use tokens, not hardcoded values.** `padding: var(--space-12)`, not
|
|
67
|
-
`padding: 12px`. `color: var(--color-text-muted)`, not `color: #999`.
|
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: artifact-table
|
|
3
|
-
description: Author dense Airtable-style HTML record tables using the shared Television house style.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Authoring a record table
|
|
7
|
-
|
|
8
|
-
Before authoring the artifact, read `house-style.md` in this skill folder.
|
|
9
|
-
|
|
10
|
-
A dense, Airtable-style table of records. Lots of cells, mixed cell types,
|
|
11
|
-
structured rows. Should look crisp at a glance and read like real software,
|
|
12
|
-
not a styled spreadsheet.
|
|
13
|
-
|
|
14
|
-
## Required content
|
|
15
|
-
|
|
16
|
-
- `<h1>` heading with a short title naming the table (e.g. "Tasks",
|
|
17
|
-
"Releases", "Customers").
|
|
18
|
-
- One paragraph (1–2 sentences) describing what the table contains and
|
|
19
|
-
how many rows it has.
|
|
20
|
-
- A `<table>` with:
|
|
21
|
-
- A `<thead>` row of column labels.
|
|
22
|
-
- 8–15 `<tbody>` rows of data.
|
|
23
|
-
- 4–6 columns covering a mix of cell types — at minimum:
|
|
24
|
-
- one **text** column (title / name)
|
|
25
|
-
- one **status** column (rendered as a small pill: a `<span>` with a
|
|
26
|
-
background color and rounded corners — done / open / blocked /
|
|
27
|
-
shipped etc.)
|
|
28
|
-
- one **date** column
|
|
29
|
-
- one **person** column (a name)
|
|
30
|
-
- one **numeric** or **tag** column (priority, count, label)
|
|
31
|
-
- Realistic-looking values, not "Lorem ipsum" or "Item 1, Item 2".
|
|
32
|
-
|
|
33
|
-
## Page layout
|
|
34
|
-
|
|
35
|
-
The artifact is a *full-width* table view, not a centered prose document.
|
|
36
|
-
Do NOT wrap the content in `<main>` or any other container that
|
|
37
|
-
constrains width — the table runs edge-to-edge.
|
|
38
|
-
|
|
39
|
-
**The default is a single ungrouped table.** Only consider sections
|
|
40
|
-
(see below) when the data has a categorical column that genuinely
|
|
41
|
-
chunks the records into meaningful groups — most tables do not.
|
|
42
|
-
|
|
43
|
-
Use this page structure:
|
|
44
|
-
|
|
45
|
-
```html
|
|
46
|
-
<body>
|
|
47
|
-
<header class="lead">
|
|
48
|
-
<h1>...</h1>
|
|
49
|
-
<p class="lede">...</p>
|
|
50
|
-
</header>
|
|
51
|
-
<table class="records">
|
|
52
|
-
...
|
|
53
|
-
</table>
|
|
54
|
-
</body>
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
The page is white throughout — no page wash, no contrasting bands. The
|
|
58
|
-
hairline borders around the thead and between rows do all the visual
|
|
59
|
-
work.
|
|
60
|
-
|
|
61
|
-
- `header.lead` padding: `var(--space-32) var(--space-32) var(--space-16)`.
|
|
62
|
-
- `table.records`: `width: 100%; border-collapse: collapse;`. Add
|
|
63
|
-
`font-variant-numeric: tabular-nums;` so numeric columns align.
|
|
64
|
-
|
|
65
|
-
## Edge gutters
|
|
66
|
-
|
|
67
|
-
The table runs full-width, but its content needs to line up with the
|
|
68
|
-
title section's gutter. Achieve this by padding the *first* and *last*
|
|
69
|
-
cells of every row (both `thead th` and `tbody td`):
|
|
70
|
-
|
|
71
|
-
```css
|
|
72
|
-
table.records thead th:first-child,
|
|
73
|
-
table.records tbody td:first-child { padding-left: var(--space-32); }
|
|
74
|
-
table.records thead th:last-child,
|
|
75
|
-
table.records tbody td:last-child { padding-right: var(--space-32); }
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
## Borders
|
|
79
|
-
|
|
80
|
-
The table has hairline borders on the **top of the thead** and the
|
|
81
|
-
**bottom of the last `tbody` row**, plus muted hairlines between rows.
|
|
82
|
-
No vertical column rules — the table feels like a list, not a grid.
|
|
83
|
-
|
|
84
|
-
```css
|
|
85
|
-
table.records thead th {
|
|
86
|
-
border-top: 0.5px solid var(--color-border);
|
|
87
|
-
border-bottom: 0.5px solid var(--color-border);
|
|
88
|
-
}
|
|
89
|
-
table.records tbody td {
|
|
90
|
-
border-bottom: 0.5px solid var(--color-border-muted);
|
|
91
|
-
}
|
|
92
|
-
table.records tbody tr:last-child td {
|
|
93
|
-
border-bottom: 0.5px solid var(--color-border);
|
|
94
|
-
}
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
## Cell styling
|
|
98
|
-
|
|
99
|
-
- Use semantic `<table>` / `<thead>` / `<tbody>` / `<tr>` / `<th>` /
|
|
100
|
-
`<td>`.
|
|
101
|
-
- Header row: small, muted, uppercase. `font-size: var(--text-sm);
|
|
102
|
-
text-transform: uppercase; letter-spacing: 0.04em; color:
|
|
103
|
-
var(--color-text-muted); font-weight: var(--font-weight-body);`.
|
|
104
|
-
Don't bold-bomb it.
|
|
105
|
-
- Cells: `padding: var(--space-8) var(--space-12);` (tight vertical,
|
|
106
|
-
generous horizontal). `vertical-align: baseline;`.
|
|
107
|
-
- Numeric and date columns: right-align via a `.num` / `.date` class
|
|
108
|
-
with `text-align: right; white-space: nowrap;`.
|
|
109
|
-
- Title cell: `font-weight: 500;` so it reads as the row's primary
|
|
110
|
-
label.
|
|
111
|
-
|
|
112
|
-
## Status pills
|
|
113
|
-
|
|
114
|
-
Inline, rounded, with subtle backgrounds — use `color-mix()` accents at
|
|
115
|
-
~14–16% opacity so they sit calmly in the row. Each status gets its own
|
|
116
|
-
class (e.g. `pill-done`, `pill-in-progress`, `pill-blocked`,
|
|
117
|
-
`pill-shipped`). Example:
|
|
118
|
-
|
|
119
|
-
```css
|
|
120
|
-
.pill {
|
|
121
|
-
display: inline-block;
|
|
122
|
-
padding: 1px var(--space-8);
|
|
123
|
-
border-radius: var(--radius-full);
|
|
124
|
-
font-size: var(--text-sm);
|
|
125
|
-
}
|
|
126
|
-
.pill-done {
|
|
127
|
-
background: color-mix(in srgb, var(--color-text-muted) 14%, transparent);
|
|
128
|
-
color: var(--color-text-muted);
|
|
129
|
-
}
|
|
130
|
-
.pill-in-progress {
|
|
131
|
-
background: color-mix(in srgb, royalblue 16%, transparent);
|
|
132
|
-
color: color-mix(in srgb, royalblue 80%, var(--color-text));
|
|
133
|
-
}
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
## Sections (optional)
|
|
137
|
-
|
|
138
|
-
**A single ungrouped table is the default. Most tables should not
|
|
139
|
-
use sections.** Only break into sections when *all* of the following
|
|
140
|
-
hold:
|
|
141
|
-
|
|
142
|
-
- The data has a categorical column (status, quarter, tier, severity)
|
|
143
|
-
whose values are stable, meaningful, and the primary thing the
|
|
144
|
-
reader scans for.
|
|
145
|
-
- That column has a small, fixed set of values — not many sparse ones.
|
|
146
|
-
- Each section will have at least ~3 rows on average. A section of one
|
|
147
|
-
row is noise.
|
|
148
|
-
- The grouping reflects how the user thinks about the data, not just
|
|
149
|
-
a sort order. If the answer is "you could just sort by it", don't
|
|
150
|
-
group.
|
|
151
|
-
|
|
152
|
-
Examples that justify sections: tasks grouped by status when status
|
|
153
|
-
*is* the lens (active vs done vs blocked); incidents by severity for
|
|
154
|
-
an on-call view; releases by quarter on a roadmap.
|
|
155
|
-
|
|
156
|
-
Examples that don't: a customer list grouped by signup month; a
|
|
157
|
-
products table grouped by alphabet; a uniform list of items where
|
|
158
|
-
every row is the same kind of thing. Default to one table.
|
|
159
|
-
|
|
160
|
-
When grouping is justified, render each group as its own `<table>`
|
|
161
|
-
inside a `<section class="group">`, with an `<h2>` heading above it.
|
|
162
|
-
Each table repeats the column headers — grouping doesn't change the
|
|
163
|
-
per-table contract, it just multiplies it.
|
|
164
|
-
|
|
165
|
-
```html
|
|
166
|
-
<header class="lead">…</header>
|
|
167
|
-
|
|
168
|
-
<section class="group">
|
|
169
|
-
<h2>In progress</h2>
|
|
170
|
-
<table class="records">
|
|
171
|
-
<colgroup>
|
|
172
|
-
<col /><col style="width: 9rem" /><col style="width: 9rem" />
|
|
173
|
-
<col style="width: 7rem" /><col style="width: 5rem" />
|
|
174
|
-
</colgroup>
|
|
175
|
-
<thead>
|
|
176
|
-
<tr><th>Title</th><th>Status</th><th>Owner</th><th>Area</th><th class="date">Due</th></tr>
|
|
177
|
-
</thead>
|
|
178
|
-
<tbody>…</tbody>
|
|
179
|
-
</table>
|
|
180
|
-
</section>
|
|
181
|
-
|
|
182
|
-
<section class="group">
|
|
183
|
-
<h2>Done</h2>
|
|
184
|
-
<table class="records">…same colgroup, same thead…</table>
|
|
185
|
-
</section>
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
Group heading — substantial enough to do the visual chunking on its
|
|
189
|
-
own (no background separation between sections):
|
|
190
|
-
|
|
191
|
-
```css
|
|
192
|
-
section.group h2 {
|
|
193
|
-
margin: 0;
|
|
194
|
-
padding: var(--space-16) var(--space-32) var(--space-8);
|
|
195
|
-
font-size: var(--text-lg);
|
|
196
|
-
font-weight: 600;
|
|
197
|
-
color: var(--color-text);
|
|
198
|
-
}
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
Repeat the same `<colgroup>` definition in every grouped table so
|
|
202
|
-
columns line up across sections. Pick widths once based on the longest
|
|
203
|
-
content across all groups. Without `<colgroup>` each table sizes its
|
|
204
|
-
own columns independently and they will drift.
|
|
205
|
-
|
|
206
|
-
Order groups so active states come before terminal states — e.g.
|
|
207
|
-
"In progress" before "Done", "Open" before "Closed". The most
|
|
208
|
-
actionable section reads first.
|
|
209
|
-
|
|
210
|
-
## Non-goals
|
|
211
|
-
|
|
212
|
-
- No filtering, sorting, search, or row selection — purely rendered.
|
|
213
|
-
- No icons unless they add real meaning (an empty/filled circle for
|
|
214
|
-
status is fine; decorative emoji is not).
|
|
215
|
-
- No nested tables, no expand/collapse, no sticky headers.
|
|
216
|
-
- No collapse/expand on section headers — sections are visual
|
|
217
|
-
grouping only.
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
# Authoring artifacts
|
|
2
|
-
|
|
3
|
-
You're writing a single self-contained HTML artifact that will be rendered
|
|
4
|
-
inside a Television viewer (or downloaded for offline viewing later). This
|
|
5
|
-
skill documents the conventions you must follow.
|
|
6
|
-
|
|
7
|
-
## House style
|
|
8
|
-
|
|
9
|
-
Artifacts inherit a versioned, canonical stylesheet served by the
|
|
10
|
-
Television runtime. Include it in `<head>`:
|
|
11
|
-
|
|
12
|
-
```html
|
|
13
|
-
<link rel="stylesheet" href="/canonical/v1/styles.css">
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
That stylesheet provides:
|
|
17
|
-
|
|
18
|
-
- A CSS reset and font-face declarations (Hind variable font, loaded
|
|
19
|
-
automatically — no extra link tags needed).
|
|
20
|
-
- The full design-system token catalog as CSS custom properties:
|
|
21
|
-
typography (`--text-*`, `--font-*`, `--leading-*`), spacing
|
|
22
|
-
(`--space-*`), color (`--color-*`, `--neutral-*`), radii
|
|
23
|
-
(`--radius-*`), and surfaces. The runtime source of truth is
|
|
24
|
-
`packages/ui/styles/tokens.css`; the bundle inlines it.
|
|
25
|
-
- Bare-tag styling. `body`, `a`, `h1`–`h6`, `code`, `pre`, and similar
|
|
26
|
-
semantic elements have built-in styling — you do not need to add
|
|
27
|
-
classes to make them look right.
|
|
28
|
-
|
|
29
|
-
**Lean on semantic HTML and the bare-tag styling.** Reach for `<h1>`,
|
|
30
|
-
`<p>`, `<ul>`, `<code>`, etc. before inventing custom classes. Use tokens
|
|
31
|
-
(`var(--space-8)`, `var(--color-text-muted)`, etc.) for any custom CSS
|
|
32
|
-
you do write — never hardcoded pixel values or hex colors.
|
|
33
|
-
|
|
34
|
-
## Document shape
|
|
35
|
-
|
|
36
|
-
Emit a complete HTML document, not a fragment:
|
|
37
|
-
|
|
38
|
-
```html
|
|
39
|
-
<!doctype html>
|
|
40
|
-
<html lang="en">
|
|
41
|
-
<head>
|
|
42
|
-
<meta charset="utf-8">
|
|
43
|
-
<title>{{title}}</title>
|
|
44
|
-
<link rel="stylesheet" href="/canonical/v1/styles.css">
|
|
45
|
-
</head>
|
|
46
|
-
<body>
|
|
47
|
-
<!-- artifact content -->
|
|
48
|
-
</body>
|
|
49
|
-
</html>
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## Conventions
|
|
53
|
-
|
|
54
|
-
- **Self-contained.** By default, emit one HTML file. If the active
|
|
55
|
-
kind skill ships local CSS or JS assets, copy or inline them from the
|
|
56
|
-
skill folder so the final artifact remains self-contained without any
|
|
57
|
-
`/skills/...` runtime dependency.
|
|
58
|
-
- **No arbitrary `<script>` tags.** Static HTML is the default. Only
|
|
59
|
-
include local, bundled scripts when the active kind skill explicitly
|
|
60
|
-
requires them.
|
|
61
|
-
- **No external network fetches.** No CDN links, no remote images, no
|
|
62
|
-
font URLs other than what `/canonical/v1/styles.css` already includes.
|
|
63
|
-
- **No inline `<style>` overrides for chrome-level concerns.** Small
|
|
64
|
-
layout-specific styles for the artifact's content are fine; redefining
|
|
65
|
-
brand colors or typography is not.
|
|
66
|
-
- **Use tokens, not hardcoded values.** `padding: var(--space-12)`, not
|
|
67
|
-
`padding: 12px`. `color: var(--color-text-muted)`, not `color: #999`.
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html>
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8" />
|
|
5
|
-
<title>Text view</title>
|
|
6
|
-
<style>
|
|
7
|
-
html,
|
|
8
|
-
body {
|
|
9
|
-
margin: 0;
|
|
10
|
-
padding: 0;
|
|
11
|
-
height: 100%;
|
|
12
|
-
background: #fff;
|
|
13
|
-
color: #000;
|
|
14
|
-
}
|
|
15
|
-
pre#content {
|
|
16
|
-
box-sizing: border-box;
|
|
17
|
-
margin: 0;
|
|
18
|
-
padding: 12px 16px;
|
|
19
|
-
min-height: 100%;
|
|
20
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
21
|
-
font-size: 13px;
|
|
22
|
-
line-height: 1.5;
|
|
23
|
-
white-space: pre-wrap;
|
|
24
|
-
word-break: break-word;
|
|
25
|
-
outline: none;
|
|
26
|
-
}
|
|
27
|
-
</style>
|
|
28
|
-
<script type="module">var I=e=>{throw TypeError(e)};var _=(e,n,t)=>n.has(e)||I("Cannot "+t);var c=(e,n,t)=>(_(e,n,"read from private field"),t?t.call(e):n.get(e)),u=(e,n,t)=>n.has(e)?I("Cannot add the same private member more than once"):n instanceof WeakSet?n.add(e):n.set(e,t),y=(e,n,t,r)=>(_(e,n,"write to private field"),r?r.call(e,t):n.set(e,t),t),p=(e,n,t)=>(_(e,n,"access private method"),t);(function(){const n=document.createElement("link").relList;if(n&&n.supports&&n.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))r(s);new MutationObserver(s=>{for(const o of s)if(o.type==="childList")for(const i of o.addedNodes)i.tagName==="LINK"&&i.rel==="modulepreload"&&r(i)}).observe(document,{childList:!0,subtree:!0});function t(s){const o={};return s.integrity&&(o.integrity=s.integrity),s.referrerPolicy&&(o.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?o.credentials="include":s.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function r(s){if(s.ep)return;s.ep=!0;const o=t(s);fetch(s.href,o)}})();const S=new Set(["target","currentTarget","eventPhase","defaultPrevented","isTrusted","timeStamp","srcElement","returnValue","cancelBubble","NONE","CAPTURING_PHASE","AT_TARGET","BUBBLING_PHASE","composedPath","stopPropagation","stopImmediatePropagation","preventDefault","initEvent"]);function O(e){for(const n of Object.keys(e))if(S.has(n))throw new Error(`Event payload key "${n}" is reserved; choose a different property name`)}function G(e,n){O(n);for(const t of Object.keys(n))Object.defineProperty(e,t,{value:n[t],writable:!0,enumerable:!0,configurable:!0})}function V(){class e extends Event{constructor(t,r){const{type:s,bubbles:o,cancelable:i,composed:v,...w}=r??{};if(s!==void 0)throw new Error('Do not pass "type" in init; use the constructor argument instead');super(t,{bubbles:o,cancelable:i,composed:v}),G(this,w)}}return e}class U extends globalThis.EventTarget{}function B(e,n,t){const r=e.dispose.bind(e);e.dispose=()=>{if(!n())return t(),r()}}function F(e){var t;class n extends e{constructor(...o){super(...o);u(this,t,!1);B(this,()=>c(this,t),()=>{y(this,t,!0)})}[Symbol.dispose](){this.dispose()}get disposed(){return c(this,t)}}return t=new WeakMap,n}const R="0123456789ABCDEFGHJKMNPQRSTVWXYZ",b=32,W=16,A=10,P=0xffffffffffff;var f;(function(e){e.Base32IncorrectEncoding="B32_ENC_INVALID",e.DecodeTimeInvalidCharacter="DEC_TIME_CHAR",e.DecodeTimeValueMalformed="DEC_TIME_MALFORMED",e.EncodeTimeNegative="ENC_TIME_NEG",e.EncodeTimeSizeExceeded="ENC_TIME_SIZE_EXCEED",e.EncodeTimeValueMalformed="ENC_TIME_MALFORMED",e.PRNGDetectFailure="PRNG_DETECT",e.ULIDInvalid="ULID_INVALID",e.Unexpected="UNEXPECTED",e.UUIDInvalid="UUID_INVALID"})(f||(f={}));class T extends Error{constructor(n,t){super(`${t} (${n})`),this.name="ULIDError",this.code=n}}function $(e){const n=Math.floor(e()*b)%b;return R.charAt(n)}function j(e){const n=H(),t=n&&(n.crypto||n.msCrypto)||null;if(typeof(t==null?void 0:t.getRandomValues)=="function")return()=>{const r=new Uint8Array(1);return t.getRandomValues(r),r[0]/256};if(typeof(t==null?void 0:t.randomBytes)=="function")return()=>t.randomBytes(1).readUInt8()/256;throw new T(f.PRNGDetectFailure,"Failed to find a reliable PRNG")}function H(){return X()?self:typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:null}function K(e,n){let t="";for(;e>0;e--)t=$(n)+t;return t}function k(e,n=A){if(isNaN(e))throw new T(f.EncodeTimeValueMalformed,`Time must be a number: ${e}`);if(e>P)throw new T(f.EncodeTimeSizeExceeded,`Cannot encode a time larger than ${P}: ${e}`);if(e<0)throw new T(f.EncodeTimeNegative,`Time must be positive: ${e}`);if(Number.isInteger(e)===!1)throw new T(f.EncodeTimeValueMalformed,`Time must be an integer: ${e}`);let t,r="";for(let s=n;s>0;s--)t=e%b,r=R.charAt(t)+r,e=(e-t)/b;return r}function X(){return typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope}function z(e,n){const t=j(),r=Date.now();return k(r,A)+K(W,t)}function N(e){return typeof e=="object"&&e!==null}function Y(e){return!N(e)||e.type!=="content-updated"||typeof e.content!="string"?!1:!("id"in e)}function Z(e){if(!N(e)||e.type!=="response"||typeof e.id!="string")return!1;const n="result"in e&&e.result!==void 0,t="error"in e&&e.error!==void 0;return!(n===t||n&&(!N(e.result)||Object.keys(e.result).length!==0)||t&&(!N(e.error)||typeof e.error.message!="string"))}const q=V(),J=F(U);var m,E,h,d,a,L,C,D,x;class Q extends J{constructor(t=globalThis){super();u(this,a);u(this,m);u(this,E);u(this,h);u(this,d,new Map);y(this,m,t);const r=t.parent;if(!r||r===t)throw new Error("ArtifactContext: window has no parent");y(this,E,r),y(this,h,s=>p(this,a,L).call(this,s)),c(this,m).addEventListener("message",c(this,h)),p(this,a,D).call(this,{type:"ready"})}updateContent(t){p(this,a,x).call(this);const r=z(),s={type:"update-content",id:r,content:t};return new Promise((o,i)=>{c(this,d).set(r,{resolve:o,reject:i}),p(this,a,D).call(this,s)})}dispose(){c(this,m).removeEventListener("message",c(this,h));const t=[...c(this,d).values()];c(this,d).clear();for(const{reject:r}of t)r(new Error("ArtifactContext disposed"))}}m=new WeakMap,E=new WeakMap,h=new WeakMap,d=new WeakMap,a=new WeakSet,L=function(t){if(this.disposed||t.source!==c(this,E))return;const r=t.data;if(Y(r)){this.dispatchEvent(new q("content-updated",{content:r.content}));return}if(Z(r)){p(this,a,C).call(this,r);return}},C=function(t){const r=c(this,d).get(t.id);if(r){if(c(this,d).delete(t.id),t.error!==void 0){r.reject(new Error(t.error.message));return}r.resolve()}},D=function(t){c(this,E).postMessage(t,"*")},x=function(){if(this.disposed)throw new Error("ArtifactContext is disposed")};const ee=500;function te(e){const{pre:n,ctx:t}=e,r=e.debounceMs??ee;let s=null,o=null,i=null;const v=async()=>{i=null;const g=n.textContent??"";s=g;try{await t.updateContent(g),o=g}catch{const l=o??"";n.textContent=l,s=l}},w=()=>{i!==null&&clearTimeout(i),i=setTimeout(()=>{v()},r)},M=g=>{const l=g.content;s!==null&&l===s||(n.textContent=l,o=l)};return t.addEventListener("content-updated",M),n.addEventListener("input",w),{dispose(){i!==null&&(clearTimeout(i),i=null),t.removeEventListener("content-updated",M),n.removeEventListener("input",w)}}}const ne=document.getElementById("content"),re=new URLSearchParams(window.location.search).get("debugWire")==="1";re&&window.addEventListener("message",e=>{e.source===window.parent&&window.parent.postMessage({type:"__wire-observed",direction:"host-to-view",message:e.data},"*")});const se=new Q;te({pre:ne,ctx:se});
|
|
29
|
-
</script>
|
|
30
|
-
</head>
|
|
31
|
-
<body>
|
|
32
|
-
<pre
|
|
33
|
-
id="content"
|
|
34
|
-
contenteditable="plaintext-only"
|
|
35
|
-
spellcheck="false"
|
|
36
|
-
></pre>
|
|
37
|
-
</body>
|
|
38
|
-
</html>
|
|
File without changes
|
|
File without changes
|