@telepath-computer/television 0.1.177 → 0.1.178
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/canonical/v1/components.js +13 -7
- package/dist/canonical/v1/styles.css +17 -1
- package/dist/cli.cjs +4 -4
- package/dist/onboarding/television-onboarding/index.html +3 -3
- package/dist/skills/television/SKILL.md +40 -0
- package/dist/skills/tv-tasks/SKILL.md +241 -0
- package/dist/skills/tv-tasks/task.css +205 -0
- package/dist/skills/tv-tasks/task.js +307 -0
- package/dist/web/assets/main-FDJtlHD7.js +768 -0
- package/dist/web/index.html +1 -1
- package/package.json +1 -1
- package/dist/web/assets/main-BSAIRhnY.js +0 -768
|
@@ -173,14 +173,20 @@ const ICONS = {
|
|
|
173
173
|
regular: `<path d="M104,40H56A16,16,0,0,0,40,56v48a16,16,0,0,0,16,16h48a16,16,0,0,0,16-16V56A16,16,0,0,0,104,40Zm0,64H56V56h48v48Zm96-64H152a16,16,0,0,0-16,16v48a16,16,0,0,0,16,16h48a16,16,0,0,0,16-16V56A16,16,0,0,0,200,40Zm0,64H152V56h48v48Zm-96,32H56a16,16,0,0,0-16,16v48a16,16,0,0,0,16,16h48a16,16,0,0,0,16-16V152A16,16,0,0,0,104,136Zm0,64H56V152h48v48Zm96-64H152a16,16,0,0,0-16,16v48a16,16,0,0,0,16,16h48a16,16,0,0,0,16-16V152A16,16,0,0,0,200,136Zm0,64H152V152h48v48Z"/>`,
|
|
174
174
|
duotone: `<path d="M112,56v48a8,8,0,0,1-8,8H56a8,8,0,0,1-8-8V56a8,8,0,0,1,8-8h48A8,8,0,0,1,112,56Zm88-8H152a8,8,0,0,0-8,8v48a8,8,0,0,0,8,8h48a8,8,0,0,0,8-8V56A8,8,0,0,0,200,48Zm-96,96H56a8,8,0,0,0-8,8v48a8,8,0,0,0,8,8h48a8,8,0,0,0,8-8V152A8,8,0,0,0,104,144Zm96,0H152a8,8,0,0,0-8,8v48a8,8,0,0,0,8,8h48a8,8,0,0,0,8-8V152A8,8,0,0,0,200,144Z" opacity="0.2"/><path d="M200,136H152a16,16,0,0,0-16,16v48a16,16,0,0,0,16,16h48a16,16,0,0,0,16-16V152A16,16,0,0,0,200,136Zm0,64H152V152h48v48ZM104,40H56A16,16,0,0,0,40,56v48a16,16,0,0,0,16,16h48a16,16,0,0,0,16-16V56A16,16,0,0,0,104,40Zm0,64H56V56h48v48Zm96-64H152a16,16,0,0,0-16,16v48a16,16,0,0,0,16,16h48a16,16,0,0,0,16-16V56A16,16,0,0,0,200,40Zm0,64H152V56h48v48Zm-96,32H56a16,16,0,0,0-16,16v48a16,16,0,0,0,16,16h48a16,16,0,0,0,16-16V152A16,16,0,0,0,104,136Zm0,64H56V152h48v48Z"/>`,
|
|
175
175
|
},
|
|
176
|
+
"calendar-blank": {
|
|
177
|
+
regular: `<path d="M208,32H184V24a8,8,0,0,0-16,0v8H88V24a8,8,0,0,0-16,0v8H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM72,48v8a8,8,0,0,0,16,0V48h80v8a8,8,0,0,0,16,0V48h24V80H48V48ZM208,208H48V96H208V208Z"/>`,
|
|
178
|
+
},
|
|
179
|
+
hash: {
|
|
180
|
+
regular: `<path d="M224,88H175.4l8.47-46.57a8,8,0,0,0-15.74-2.86l-9,49.43H111.4l8.47-46.57a8,8,0,0,0-15.74-2.86L95.14,88H48a8,8,0,0,0,0,16H92.23L83.5,152H32a8,8,0,0,0,0,16H80.6l-8.47,46.57a8,8,0,0,0,6.44,9.3A7.79,7.79,0,0,0,80,224a8,8,0,0,0,7.86-6.57l9-49.43H144.6l-8.47,46.57a8,8,0,0,0,6.44,9.3A7.79,7.79,0,0,0,144,224a8,8,0,0,0,7.86-6.57l9-49.43H208a8,8,0,0,0,0-16H163.77l8.73-48H224a8,8,0,0,0,0-16Zm-76.5,64H99.77l8.73-48h47.73Z"/>`,
|
|
181
|
+
},
|
|
176
182
|
};
|
|
177
183
|
const STYLES = `
|
|
178
184
|
:host {
|
|
179
185
|
display: inline-flex;
|
|
180
|
-
width: var(--
|
|
181
|
-
height: var(--
|
|
186
|
+
width: var(--tv-icon-size, 1em);
|
|
187
|
+
height: var(--tv-icon-size, 1em);
|
|
182
188
|
vertical-align: -0.125em;
|
|
183
|
-
color: var(--
|
|
189
|
+
color: var(--tv-icon-color, currentColor);
|
|
184
190
|
}
|
|
185
191
|
|
|
186
192
|
svg {
|
|
@@ -191,7 +197,7 @@ const STYLES = `
|
|
|
191
197
|
}
|
|
192
198
|
`;
|
|
193
199
|
function isIconName(value) {
|
|
194
|
-
return value === "plus" || value === "subtract-square" || value === "squares-four" || value === "television";
|
|
200
|
+
return value === "plus" || value === "subtract-square" || value === "squares-four" || value === "television" || value === "calendar-blank" || value === "hash";
|
|
195
201
|
}
|
|
196
202
|
function isIconWeight(value) {
|
|
197
203
|
return value === "regular" || value === "bold" || value === "duotone";
|
|
@@ -219,7 +225,7 @@ export class IconElement extends HTMLElement {
|
|
|
219
225
|
<style>${STYLES}</style>
|
|
220
226
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" aria-hidden="true" focusable="false">${source}</svg>
|
|
221
227
|
`;
|
|
222
|
-
this.style.setProperty("--
|
|
228
|
+
this.style.setProperty("--tv-icon-size", `${size}px`);
|
|
223
229
|
}
|
|
224
230
|
#name() {
|
|
225
231
|
const value = this.getAttribute("name");
|
|
@@ -234,7 +240,7 @@ export class IconElement extends HTMLElement {
|
|
|
234
240
|
return value === MEDIUM_ICON_SIZE || value === LARGE_ICON_SIZE ? value : DEFAULT_ICON_SIZE;
|
|
235
241
|
}
|
|
236
242
|
}
|
|
237
|
-
if (!customElements.get("
|
|
238
|
-
customElements.define("
|
|
243
|
+
if (!customElements.get("tv-icon")) {
|
|
244
|
+
customElements.define("tv-icon", IconElement);
|
|
239
245
|
}
|
|
240
246
|
|
|
@@ -327,7 +327,11 @@ body {
|
|
|
327
327
|
line-height: var(--leading-base);
|
|
328
328
|
letter-spacing: 0.015em;
|
|
329
329
|
color: var(--color-text);
|
|
330
|
-
|
|
330
|
+
/* The artifact page is the card surface — Television's artifact-view frames
|
|
331
|
+
the whole document as a card, so the default page background is the
|
|
332
|
+
surface color. A muted backdrop (--color-bg) is something an artifact
|
|
333
|
+
opts into, not the default. */
|
|
334
|
+
background: var(--color-surface);
|
|
331
335
|
-webkit-font-smoothing: antialiased;
|
|
332
336
|
-moz-osx-font-smoothing: grayscale;
|
|
333
337
|
}
|
|
@@ -378,6 +382,18 @@ table {
|
|
|
378
382
|
margin-top: var(--space-8);
|
|
379
383
|
}
|
|
380
384
|
|
|
385
|
+
/* Page-header idiom: a <header> holds a heading and optionally one <p>
|
|
386
|
+
subtitle — a date line, a description. A paragraph inside any header is a
|
|
387
|
+
subtitle: slightly smaller than body prose, at body weight, hugging its
|
|
388
|
+
heading — proximity and the heading above do the differentiating. */
|
|
389
|
+
header p {
|
|
390
|
+
font-size: var(--text-base);
|
|
391
|
+
font-weight: var(--font-weight-body);
|
|
392
|
+
}
|
|
393
|
+
header :is(h1, h2, h3, h4, h5, h6) + p {
|
|
394
|
+
margin-top: var(--space-2);
|
|
395
|
+
}
|
|
396
|
+
|
|
381
397
|
ul,
|
|
382
398
|
ol {
|
|
383
399
|
padding-left: var(--space-24);
|
package/dist/cli.cjs
CHANGED
|
@@ -52695,8 +52695,8 @@ var Server = class {
|
|
|
52695
52695
|
};
|
|
52696
52696
|
};
|
|
52697
52697
|
function readServerPackageVersion() {
|
|
52698
|
-
if ("0.1.
|
|
52699
|
-
return telemetryVersion("0.1.
|
|
52698
|
+
if ("0.1.178".length > 0) {
|
|
52699
|
+
return telemetryVersion("0.1.178");
|
|
52700
52700
|
}
|
|
52701
52701
|
const packageJsonPath = import_node_path11.default.resolve(import_node_path11.default.dirname((0, import_node_url.fileURLToPath)(import_meta.url)), "..", "package.json");
|
|
52702
52702
|
if (!(0, import_node_fs9.existsSync)(packageJsonPath)) return telemetryVersion("0.0.0");
|
|
@@ -53769,8 +53769,8 @@ function resolveVercelSkillsInstallerBin() {
|
|
|
53769
53769
|
return localRequire.resolve("skills/bin/cli.mjs");
|
|
53770
53770
|
}
|
|
53771
53771
|
function readCLIVersion() {
|
|
53772
|
-
if ("0.1.
|
|
53773
|
-
return "0.1.
|
|
53772
|
+
if ("0.1.178".length > 0) {
|
|
53773
|
+
return "0.1.178";
|
|
53774
53774
|
}
|
|
53775
53775
|
const devPackageJsonPath = import_node_path15.default.join(getDevPackageDir(), "package.json");
|
|
53776
53776
|
if (!(0, import_node_fs12.existsSync)(devPackageJsonPath)) {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
font-size: 15px;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
tv-icon {
|
|
27
27
|
position: relative;
|
|
28
28
|
top: 1px;
|
|
29
29
|
color: var(--color-text-muted);
|
|
@@ -181,9 +181,9 @@
|
|
|
181
181
|
|
|
182
182
|
<p class="lede">Television is the missing GUI for your personal agent, created by the team at Telepath. We’re glad you’re here.</p>
|
|
183
183
|
|
|
184
|
-
<p>This card is an <
|
|
184
|
+
<p>This card is an <tv-icon name="subtract-square" weight="duotone"></tv-icon> <strong>Artifact</strong>: a live surface your agent can create, edit, and update. Artifacts can be notes, editable documents, dashboards, web pages, reports, or custom web apps.</p>
|
|
185
185
|
|
|
186
|
-
<p>Artifacts live on <
|
|
186
|
+
<p>Artifacts live on <tv-icon name="squares-four" weight="duotone"></tv-icon> <strong>Screens</strong>. We put you on <strong>TV Guide</strong> to start. Double-click its name to rename it, use <tv-icon name="plus" weight="bold"></tv-icon> to add more screens, and drag artifacts to arrange them. Your open screens appear as tabs up the top. If you close one, you can find it again by clicking <tv-icon name="squares-four" weight="bold"></tv-icon>.</p>
|
|
187
187
|
|
|
188
188
|
<p>To create or change an artifact, just describe what you want to see. Try asking your agent…</p>
|
|
189
189
|
|
|
@@ -494,6 +494,29 @@ blockquotes, rules, images, and tables have readable defaults. Add local CSS for
|
|
|
494
494
|
artifact-specific layout, density, hierarchy, or specialized presentations; do
|
|
495
495
|
not recreate baseline prose styling in every artifact.
|
|
496
496
|
|
|
497
|
+
## Page header
|
|
498
|
+
|
|
499
|
+
A page header is optional — the Television card already names the artifact in
|
|
500
|
+
its title bar, so don't add one just to repeat that. Add one when the document
|
|
501
|
+
benefits from its own masthead: a title that differs from or says more than
|
|
502
|
+
the card name, or a subtitle line carrying context like a date, a person, or
|
|
503
|
+
a status.
|
|
504
|
+
|
|
505
|
+
When you do, use the house header idiom — a `<header>` holding an `<h1>` and
|
|
506
|
+
optionally one `<p>` subtitle:
|
|
507
|
+
|
|
508
|
+
```html
|
|
509
|
+
<header>
|
|
510
|
+
<h1>Quarterly plan</h1>
|
|
511
|
+
<p>Friday, June 26</p>
|
|
512
|
+
</header>
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
A `<p>` inside any `<header>` renders as a subtitle — slightly smaller than
|
|
516
|
+
body prose, at body weight, hugging its heading; proximity and the heading
|
|
517
|
+
above do the differentiating. The idiom is house language: use it as-is,
|
|
518
|
+
don't restyle it per artifact.
|
|
519
|
+
|
|
497
520
|
For prose-like documents, consider giving the content enough room above the bottom title bar. A reasonable starting point is 32px padding on the top and sides, with 64px at the bottom; adjust based on the content and layout:
|
|
498
521
|
|
|
499
522
|
```css
|
|
@@ -569,6 +592,23 @@ checkbox-item::part(box) {
|
|
|
569
592
|
}
|
|
570
593
|
```
|
|
571
594
|
|
|
595
|
+
### Icons
|
|
596
|
+
|
|
597
|
+
`<tv-icon name="…" size="16|24|32">` renders a glyph from the canonical
|
|
598
|
+
catalog. The catalog is small and closed — these are the only valid names:
|
|
599
|
+
|
|
600
|
+
- `calendar-blank`
|
|
601
|
+
- `hash`
|
|
602
|
+
- `plus`
|
|
603
|
+
- `squares-four`
|
|
604
|
+
- `subtract-square`
|
|
605
|
+
- `television`
|
|
606
|
+
|
|
607
|
+
Do not invent other names (an unknown name silently renders the
|
|
608
|
+
`subtract-square` fallback, which looks like a broken glyph). If no glyph
|
|
609
|
+
fits, use text without an icon; if a glyph is genuinely needed and none
|
|
610
|
+
fits, use an emoji instead of `<tv-icon>`.
|
|
611
|
+
|
|
572
612
|
## Viewport
|
|
573
613
|
|
|
574
614
|
Artifacts render inside a resizable Television card, not a full browser page.
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tv-tasks
|
|
3
|
+
description: Create to-do list HTML artifacts for Television, to visualize tasks, plans, check them off, etc.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Authoring a task list
|
|
7
|
+
|
|
8
|
+
Know the main `television` skill first (re-read only if it's not in context or
|
|
9
|
+
changed) — it covers the Television workflow, artifact registration, and the
|
|
10
|
+
canonical HTML house style. This skill only adds the task-list vocabulary.
|
|
11
|
+
|
|
12
|
+
A calm, scannable to-do list: sections of task rows, each with a checkbox,
|
|
13
|
+
title, optional note, and a metadata line (due date, project, tags). You author
|
|
14
|
+
plain `tv-task-*` markup; the CSS and two small components do the rest.
|
|
15
|
+
|
|
16
|
+
## Load these
|
|
17
|
+
|
|
18
|
+
Every artifact is self-contained. Carry `task.css` and `task.js` from this skill
|
|
19
|
+
folder into the output (don't reference `/skills/tv-tasks/…` URLs).
|
|
20
|
+
|
|
21
|
+
For a directory artifact, copy both next to `index.html` and load them with the
|
|
22
|
+
canonical boilerplate:
|
|
23
|
+
|
|
24
|
+
```html
|
|
25
|
+
<link rel="stylesheet" href="/canonical/v1/styles.css" />
|
|
26
|
+
<script type="module" src="/canonical/v1/components.js"></script>
|
|
27
|
+
<link rel="stylesheet" href="./task.css" />
|
|
28
|
+
<script type="module" src="./task.js"></script>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
For a single-file artifact, inline `task.css`/`task.js` into `<style>` and
|
|
32
|
+
`<script type="module">` tags instead. `components.js` gives you `<tv-icon>`;
|
|
33
|
+
`task.js` registers `<tv-task-checkbox>` and `<tv-task-meta-due>`.
|
|
34
|
+
|
|
35
|
+
A task list is not a prose document: don't add `body` padding (the house
|
|
36
|
+
style doc suggests it for prose) — `tv-task-list` and the page header supply
|
|
37
|
+
their own gutters. Leave the body at zero.
|
|
38
|
+
|
|
39
|
+
## Markup
|
|
40
|
+
|
|
41
|
+
Author this shape — a page header, then a list of sections and rows:
|
|
42
|
+
|
|
43
|
+
```html
|
|
44
|
+
<header>
|
|
45
|
+
<h1>Television</h1>
|
|
46
|
+
<p>Wednesday, June 25</p>
|
|
47
|
+
</header>
|
|
48
|
+
|
|
49
|
+
<tv-task-list>
|
|
50
|
+
<tv-task-section>
|
|
51
|
+
<header><h2>Today</h2></header>
|
|
52
|
+
|
|
53
|
+
<tv-task>
|
|
54
|
+
<tv-task-checkbox></tv-task-checkbox>
|
|
55
|
+
<tv-task-body>
|
|
56
|
+
<tv-task-title>Review the task-list example</tv-task-title>
|
|
57
|
+
<tv-task-note>Density, grouping, and Things-like hierarchy.</tv-task-note>
|
|
58
|
+
<tv-task-meta>
|
|
59
|
+
<tv-task-meta-due date="2026-06-26"></tv-task-meta-due>
|
|
60
|
+
<tv-task-meta-item><tv-icon name="hash"></tv-icon>TV Skills</tv-task-meta-item>
|
|
61
|
+
<tv-task-meta-tag>design</tv-task-meta-tag>
|
|
62
|
+
</tv-task-meta>
|
|
63
|
+
</tv-task-body>
|
|
64
|
+
</tv-task>
|
|
65
|
+
</tv-task-section>
|
|
66
|
+
</tv-task-list>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Components
|
|
70
|
+
|
|
71
|
+
### `<tv-task-list>`
|
|
72
|
+
The list root. One per view, holding the sections (or bare rows). It draws no
|
|
73
|
+
frame of its own — the page is the surface, and Television supplies the card
|
|
74
|
+
chrome around the artifact.
|
|
75
|
+
|
|
76
|
+
### Headers — `<header>` + `<h1>`/`<h2>` + optional `<p>`
|
|
77
|
+
|
|
78
|
+
A page title is optional — the Television card already names the artifact, so
|
|
79
|
+
a bare list is fine. Add one when the list benefits from its own masthead: a
|
|
80
|
+
date line ("Today" lists usually carry the date), a person, a context the
|
|
81
|
+
card name doesn't say. When you do, use the house header idiom *above*
|
|
82
|
+
`<tv-task-list>` (not inside it): a `<header>` with an `<h1>` and optionally
|
|
83
|
+
a `<p>` subtitle. House styles own its look; the skill only aligns it with
|
|
84
|
+
the list. Title each section with an `<h2>` inside the section's own
|
|
85
|
+
`<header>`. Keep these as real HTML headings, not `tv-task-*`, so the
|
|
86
|
+
document outline stays navigable.
|
|
87
|
+
|
|
88
|
+
### `<tv-task-section>`
|
|
89
|
+
A titled group of rows: a `<header>` then the `<tv-task>`s. Group by one
|
|
90
|
+
meaningful axis — a when-bucket (Today / Upcoming / Someday), a project, or an
|
|
91
|
+
area. A few purposeful groups read well; one section per task defeats the point,
|
|
92
|
+
and a flat handful of tasks needs no sections at all. Don't render a section
|
|
93
|
+
with no tasks — omit it entirely unless the user asked to see the empty group.
|
|
94
|
+
|
|
95
|
+
### `<tv-task-count>`
|
|
96
|
+
An optional task count beside a section heading:
|
|
97
|
+
`<header><h2>Today</h2><tv-task-count>3</tv-task-count></header>`. Renders
|
|
98
|
+
inline right of the heading — muted, unbolded, never floated to the far edge.
|
|
99
|
+
You write the number; nothing counts for you — keep it true to the rows
|
|
100
|
+
actually in the section, and skip it when it adds nothing.
|
|
101
|
+
|
|
102
|
+
### `<tv-task>`
|
|
103
|
+
One task row — a `<tv-task-checkbox>` followed by a `<tv-task-body>`. Give it a
|
|
104
|
+
plain `id` if you'll wire interactivity. One per task.
|
|
105
|
+
|
|
106
|
+
Add `highlighted` to emphasize a row: a soft wash, amber by default. The hue
|
|
107
|
+
is one knob — `--task-highlight` — settable inline for a single row (`<tv-task highlighted style="--task-highlight: #7C5CFF">`)
|
|
108
|
+
or on an ancestor to retint every highlight in the list. Highlight only with
|
|
109
|
+
a good reason: the user asked for it, or the emphasis clearly benefits them
|
|
110
|
+
(the one row they should see first). At more than one or two per list the
|
|
111
|
+
emphasis stops meaning anything.
|
|
112
|
+
|
|
113
|
+
### `<tv-task-checkbox>`
|
|
114
|
+
The circular checkbox at the head of each row; every row has exactly one. Add
|
|
115
|
+
`checked` to mark a task done (the row strikes through and mutes) or `disabled`
|
|
116
|
+
to mute a row without completing it. No label — it takes its accessible name from
|
|
117
|
+
the row's `<tv-task-title>`. On user toggle it emits a bubbling `toggle` event
|
|
118
|
+
and exposes a `checked` property (see Interactivity).
|
|
119
|
+
|
|
120
|
+
### `<tv-task-body>`
|
|
121
|
+
The content column right of the checkbox — wraps the title, note, and meta. One
|
|
122
|
+
per row, always present.
|
|
123
|
+
|
|
124
|
+
### `<tv-task-title>`
|
|
125
|
+
The task's name, as plain text. Required, one per row; keep it a short imperative
|
|
126
|
+
line.
|
|
127
|
+
|
|
128
|
+
### `<tv-task-note>`
|
|
129
|
+
A brief, muted one-line description under the title. Optional — add it only when
|
|
130
|
+
the title doesn't say enough, and keep it to a single line. Most tasks are
|
|
131
|
+
clearer without one.
|
|
132
|
+
|
|
133
|
+
### `<tv-task-meta>`
|
|
134
|
+
The metadata line under the title/note. It holds any mix of the three chips
|
|
135
|
+
below, in any order. Include it only when the task has metadata — otherwise omit
|
|
136
|
+
it.
|
|
137
|
+
|
|
138
|
+
### `<tv-task-meta-due>`
|
|
139
|
+
A due date: `<tv-task-meta-due date="YYYY-MM-DD">`. Give it only the machine
|
|
140
|
+
date — it computes urgency (today → amber, overdue → red, upcoming → muted),
|
|
141
|
+
writes the human label ("Today", "Tomorrow", "Jun 20"), and draws the calendar
|
|
142
|
+
glyph. Never hand-format the date or set a color. At most one per task.
|
|
143
|
+
|
|
144
|
+
### `<tv-task-meta-item>`
|
|
145
|
+
The escape hatch for metadata that isn't a date or tag — an `<tv-icon>` plus
|
|
146
|
+
text, like a project or context:
|
|
147
|
+
|
|
148
|
+
```html
|
|
149
|
+
<tv-task-meta-item><tv-icon name="hash"></tv-icon>TV Skills</tv-task-meta-item>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Useful, but restrained: one or two at most. A row crowded with chips stops being
|
|
153
|
+
scannable.
|
|
154
|
+
|
|
155
|
+
### `<tv-task-meta-tag>`
|
|
156
|
+
|
|
157
|
+
A small pill for a label or tag: `<tv-task-meta-tag>design</tv-task-meta-tag>`.
|
|
158
|
+
Repeatable, but a few keywords — not a tag soup. Two or three sharpen a row; six
|
|
159
|
+
bury it.
|
|
160
|
+
|
|
161
|
+
### `<tv-task-placeholder>`
|
|
162
|
+
|
|
163
|
+
A centered, muted empty-state message:
|
|
164
|
+
`<tv-task-placeholder>Nothing here yet</tv-task-placeholder>`. Rarely needed —
|
|
165
|
+
by default an empty section simply isn't rendered (see `<tv-task-section>`).
|
|
166
|
+
Use it only when showing the empty group is the point — the user asked to see
|
|
167
|
+
it, or an interactive list empties itself and the space must not collapse.
|
|
168
|
+
|
|
169
|
+
## Interactivity
|
|
170
|
+
|
|
171
|
+
- On user toggle a checkbox emits a bubbling `toggle` event; read the new state
|
|
172
|
+
from `e.checked`. Setting `el.checked = true/false` programmatically reflects
|
|
173
|
+
the attribute (completes/uncompletes the row) but emits nothing.
|
|
174
|
+
- Listen once on the list and delegate. Give each `<tv-task>` a plain `id` and
|
|
175
|
+
identify the toggled task with `e.target.closest("tv-task").id`.
|
|
176
|
+
- Nothing is persisted — wire the handler to whatever you want (localStorage, a
|
|
177
|
+
`fetch` to your own API, …). On load, restore state by setting `el.checked`.
|
|
178
|
+
|
|
179
|
+
```js
|
|
180
|
+
const list = document.querySelector("tv-task-list");
|
|
181
|
+
list.addEventListener("toggle", (e) => {
|
|
182
|
+
const id = e.target.closest("tv-task").id;
|
|
183
|
+
save(id, e.checked); // your persistence; nothing is stored for you
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Example variations
|
|
188
|
+
|
|
189
|
+
Completed and disabled rows:
|
|
190
|
+
|
|
191
|
+
```html
|
|
192
|
+
<tv-task>
|
|
193
|
+
<tv-task-checkbox checked></tv-task-checkbox>
|
|
194
|
+
<tv-task-body><tv-task-title>Ship the icon migration</tv-task-title></tv-task-body>
|
|
195
|
+
</tv-task>
|
|
196
|
+
<tv-task>
|
|
197
|
+
<tv-task-checkbox disabled></tv-task-checkbox>
|
|
198
|
+
<tv-task-body><tv-task-title>Blocked on review</tv-task-title></tv-task-body>
|
|
199
|
+
</tv-task>
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
An overdue date and multiple tags — same markup, the component colors it:
|
|
203
|
+
|
|
204
|
+
```html
|
|
205
|
+
<tv-task-meta>
|
|
206
|
+
<tv-task-meta-due date="2026-06-10"></tv-task-meta-due>
|
|
207
|
+
<tv-task-meta-tag>urgent</tv-task-meta-tag>
|
|
208
|
+
<tv-task-meta-tag>backend</tv-task-meta-tag>
|
|
209
|
+
</tv-task-meta>
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
A highlighted row, retinted to match the artifact's accent:
|
|
213
|
+
|
|
214
|
+
```html
|
|
215
|
+
<tv-task highlighted style="--task-highlight: #7C5CFF">
|
|
216
|
+
<tv-task-checkbox></tv-task-checkbox>
|
|
217
|
+
<tv-task-body><tv-task-title>Sign the lease by Friday</tv-task-title></tv-task-body>
|
|
218
|
+
</tv-task>
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Dark mode — set `data-theme="dark"` on `<html>` (the page header and body
|
|
222
|
+
background live outside the list, so scoping dark to the list would leave
|
|
223
|
+
them light):
|
|
224
|
+
|
|
225
|
+
```html
|
|
226
|
+
<html data-theme="dark">
|
|
227
|
+
…
|
|
228
|
+
</html>
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Guidelines
|
|
232
|
+
|
|
233
|
+
- **Icons are always `<tv-icon name="…">`** — never a span or inline SVG. In
|
|
234
|
+
metadata use `calendar-blank` (handled by the due component) and `hash`
|
|
235
|
+
(project); for other `tv-task-meta-item`s pick from the canonical icon
|
|
236
|
+
catalog (listed in the main `television` skill) — names outside it render
|
|
237
|
+
a broken-looking fallback.
|
|
238
|
+
- **Sizing is `size="16|24|32"`** on `<tv-icon>` — no em or inline sizes.
|
|
239
|
+
- **Rows are flat by default** — no backdrop, no dividers; whitespace does
|
|
240
|
+
the separating. If you restyle rows (background, radius, spacing), keep
|
|
241
|
+
that model in mind — deliberate, list-wide changes, not per-row chrome.
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Task styles for the tv-tasks artifact skill.
|
|
3
|
+
* Targets the `tv-task-*` element/attribute vocabulary (no classes); uses
|
|
4
|
+
* canonical design tokens (--color-*, --space-*, --radius-*, --text-*).
|
|
5
|
+
*
|
|
6
|
+
* Behavioral parts live in their own web components' shadow DOM:
|
|
7
|
+
* <tv-task-checkbox> — the circular pop checkbox + focus ring
|
|
8
|
+
* <tv-task-meta-due> — the due-date glyph + label; task.css only colors it.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
:root {
|
|
12
|
+
/* The amber for a task due today. Not a canonical token, so it gets one
|
|
13
|
+
named source here rather than being sprinkled as a literal. */
|
|
14
|
+
--task-due-today: #EA880B;
|
|
15
|
+
/* Highlight hue — the highlighted row's wash derives from this one knob.
|
|
16
|
+
Set it on any ancestor (or the row itself) to retint. */
|
|
17
|
+
--task-highlight: var(--task-due-today);
|
|
18
|
+
/* Skill-local muted: a shade darker than the canonical --color-text-muted
|
|
19
|
+
(neutral-500, L 0.553) so notes hold their own against the darker meta
|
|
20
|
+
treatment below. Declared at :root, so it recolors ALL muted text on the
|
|
21
|
+
page (canonical components included) — deliberate for a single-skill
|
|
22
|
+
artifact; revisit if skills ever share a page. */
|
|
23
|
+
--color-text-muted: oklch(0.52 0 0);
|
|
24
|
+
/* The meta line recedes a step behind the note: 85% of muted. */
|
|
25
|
+
--task-meta-text: color-mix(in srgb, var(--color-text-muted) 85%, transparent);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* One task row — a checkbox column + the body column. */
|
|
29
|
+
tv-task {
|
|
30
|
+
display: grid;
|
|
31
|
+
grid-template-columns: 18px 1fr;
|
|
32
|
+
column-gap: var(--space-12, 12px);
|
|
33
|
+
padding: var(--space-8, 8px) var(--space-4, 4px);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* The content column of a row (title / note / meta). */
|
|
37
|
+
tv-task-body {
|
|
38
|
+
display: block;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
tv-task-title {
|
|
42
|
+
display: block;
|
|
43
|
+
font-weight: var(--font-weight-body);
|
|
44
|
+
line-height: 1.35;
|
|
45
|
+
}
|
|
46
|
+
/* Completed — tracks the checkbox's reflected host attribute live, not a
|
|
47
|
+
static class. (The real <input> lives in the component's shadow DOM, where
|
|
48
|
+
:has() can't reach it.) */
|
|
49
|
+
tv-task:has(tv-task-checkbox[checked]) tv-task-title {
|
|
50
|
+
color: var(--color-text-muted);
|
|
51
|
+
text-decoration: line-through;
|
|
52
|
+
}
|
|
53
|
+
/* A completed task's due date no longer matters — always mute it, overriding
|
|
54
|
+
the today/overdue emphasis. */
|
|
55
|
+
tv-task:has(tv-task-checkbox[checked]) tv-task-meta-due {
|
|
56
|
+
color: var(--task-meta-text);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
tv-task-note {
|
|
60
|
+
display: block;
|
|
61
|
+
color: var(--color-text-muted);
|
|
62
|
+
font-size: calc(var(--text-sm) + 1px);
|
|
63
|
+
line-height: 1.4;
|
|
64
|
+
margin-top: 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* Shared metadata line under the title/note — holds the due date, project,
|
|
68
|
+
and label pills. */
|
|
69
|
+
tv-task-meta {
|
|
70
|
+
display: flex;
|
|
71
|
+
flex-wrap: wrap;
|
|
72
|
+
align-items: center;
|
|
73
|
+
gap: var(--space-8, 8px);
|
|
74
|
+
margin-top: var(--space-2, 2px);
|
|
75
|
+
font-size: var(--text-sm);
|
|
76
|
+
color: var(--task-meta-text);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* Generic icon + text meta item (project, area, …). The <tv-task-meta-due>
|
|
80
|
+
component supplies its own inline-flex/gap/icon, so it isn't styled here
|
|
81
|
+
beyond color. */
|
|
82
|
+
tv-task-meta-item {
|
|
83
|
+
display: inline-flex;
|
|
84
|
+
align-items: center;
|
|
85
|
+
gap: var(--space-2, 2px);
|
|
86
|
+
white-space: nowrap;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/* Due-date urgency — the <tv-task-meta-due> component reflects its computed
|
|
90
|
+
state; task.css only colors it. Default / upcoming stay muted (inherited
|
|
91
|
+
from tv-task-meta). */
|
|
92
|
+
tv-task-meta-due[state="today"] { color: var(--task-due-today); }
|
|
93
|
+
tv-task-meta-due[state="overdue"] { color: var(--color-danger); }
|
|
94
|
+
|
|
95
|
+
/* Label pill — labels, tags, and contexts are the same thing. */
|
|
96
|
+
tv-task-meta-tag {
|
|
97
|
+
display: inline-flex;
|
|
98
|
+
align-items: center;
|
|
99
|
+
height: 18px;
|
|
100
|
+
padding: 0 5px;
|
|
101
|
+
padding-bottom: 1px;
|
|
102
|
+
border-radius: 6px;
|
|
103
|
+
background: var(--color-bg-muted);
|
|
104
|
+
color: var(--task-meta-text);
|
|
105
|
+
font-size: var(--text-sm);
|
|
106
|
+
line-height: 1.5;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* Disabled — the row reads muted rather than dimmed. */
|
|
110
|
+
tv-task:has(tv-task-checkbox[disabled]) tv-task-title {
|
|
111
|
+
color: var(--color-text-muted);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* ---- List container ----
|
|
115
|
+
No frame of its own: the artifact page is the surface, and Television's
|
|
116
|
+
artifact-view supplies the card chrome around the document. (The frameset
|
|
117
|
+
design frame adds its own preview-only border.) */
|
|
118
|
+
|
|
119
|
+
tv-task-list {
|
|
120
|
+
display: block;
|
|
121
|
+
padding: 0 var(--space-16, 16px) var(--space-16, 16px);
|
|
122
|
+
}
|
|
123
|
+
/* Nothing above the list (no page heading): give it its own top breathing
|
|
124
|
+
room. When a header precedes it, the gap is the subtitle's house margin —
|
|
125
|
+
or the h1 rule below when there is no subtitle. */
|
|
126
|
+
tv-task-list:first-child {
|
|
127
|
+
padding-top: var(--space-16, 16px);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/* The artifact's own heading lives on the page, above the list, as the house
|
|
131
|
+
page-header idiom (header > h1 + p) — house typography styles it; the
|
|
132
|
+
skill only aligns it with the list's interior padding. */
|
|
133
|
+
header:has(+ tv-task-list) {
|
|
134
|
+
padding: var(--space-16, 16px) var(--space-16, 16px) 0;
|
|
135
|
+
}
|
|
136
|
+
/* A header whose last child is the h1 (no subtitle) has no house margin
|
|
137
|
+
below it — supply the gap the subtitle's margin would have given. */
|
|
138
|
+
header:has(+ tv-task-list) > h1:last-child {
|
|
139
|
+
margin-bottom: var(--space-12, 12px);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/* Section headers lay their title out inline. */
|
|
143
|
+
tv-task-section > header {
|
|
144
|
+
display: flex;
|
|
145
|
+
align-items: baseline;
|
|
146
|
+
gap: var(--space-6, 6px);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/* ---- Section ----
|
|
150
|
+
A titled group of tasks. Generic — the title can be a when-bucket (Today /
|
|
151
|
+
Upcoming / Someday), a project, or an area. Rows separate by whitespace;
|
|
152
|
+
sections by more whitespace + their header. */
|
|
153
|
+
tv-task-section {
|
|
154
|
+
display: block;
|
|
155
|
+
margin-top: var(--space-20, 20px);
|
|
156
|
+
}
|
|
157
|
+
tv-task-section:first-of-type { margin-top: 0; }
|
|
158
|
+
|
|
159
|
+
tv-task-section > header { padding-bottom: var(--space-6, 6px); }
|
|
160
|
+
tv-task-section > header h2 {
|
|
161
|
+
margin: 0;
|
|
162
|
+
font-size: var(--text-base);
|
|
163
|
+
font-weight: 600;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/* Task count beside a section heading — the author writes the number, the
|
|
167
|
+
skill only styles it. Inline right of the heading (the header's baseline
|
|
168
|
+
flex places it), never floated to the far edge. */
|
|
169
|
+
tv-task-count {
|
|
170
|
+
color: var(--task-meta-text);
|
|
171
|
+
font-size: var(--text-sm);
|
|
172
|
+
font-weight: var(--font-weight-body);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/* Empty state — shown when a section or list has no tasks. */
|
|
176
|
+
tv-task-placeholder {
|
|
177
|
+
display: block;
|
|
178
|
+
color: var(--color-text-muted);
|
|
179
|
+
text-align: center;
|
|
180
|
+
padding: var(--space-32, 32px) var(--space-16, 16px);
|
|
181
|
+
font-size: calc(var(--text-sm) + 1px);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
/* Highlighted row — sanctioned emphasis: a soft wash derived from
|
|
186
|
+
--task-highlight. No edge lines — rows are borderless throughout. */
|
|
187
|
+
tv-task[highlighted] {
|
|
188
|
+
background: color-mix(in srgb, var(--task-highlight) 10%, transparent);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/* ---- Dark mode ----
|
|
192
|
+
The canonical theme is light-only, so the skill carries its own dark token
|
|
193
|
+
set, applied when the document has data-theme="dark". */
|
|
194
|
+
[data-theme="dark"] {
|
|
195
|
+
--color-bg: var(--neutral-950);
|
|
196
|
+
--color-bg-muted: var(--neutral-900);
|
|
197
|
+
--color-surface: var(--neutral-800);
|
|
198
|
+
--color-text: var(--neutral-50);
|
|
199
|
+
--color-text-muted: var(--neutral-400);
|
|
200
|
+
/* Re-derive: custom properties resolve where declared, so without this the
|
|
201
|
+
meta tone would keep the light-mode muted it was mixed from. */
|
|
202
|
+
--task-meta-text: color-mix(in srgb, var(--color-text-muted) 85%, transparent);
|
|
203
|
+
--color-border: rgba(255, 255, 255, 0.14);
|
|
204
|
+
color-scheme: dark;
|
|
205
|
+
}
|