feat(canon): add contribution-convention v0.1, contrib/ templates, and first UPR artifact
- canon/standards/contribution-convention_v0.1.md: master spec for BR/FR/EP/UPR artifact types, directory layout, frontmatter schema, ID schemes (EP-DOMAIN-NNN for extension points), status lifecycle, and relationship to State Hub - canon/standards/contrib-templates/: four template files (br, fr, ep, upr) - contrib/upstream-prs/2026-02-26--observablehq--framework--toc-sidebar-inject.md: first real UPR artifact — proposes injectTocTop() to Observable Framework Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
---
|
||||
id: upr-2026-02-26--observablehq--framework--toc-sidebar-inject
|
||||
type: upr
|
||||
target_org: observablehq
|
||||
target_repo: framework
|
||||
title: "Add injectTocTop() utility for injecting elements into the TOC sidebar"
|
||||
status: draft
|
||||
domain: custodian
|
||||
related_workstream: contribution-tracking-sbom
|
||||
state_hub_contribution_id: null
|
||||
created: "2026-02-26"
|
||||
updated: "2026-02-28"
|
||||
local_component_path: "state-hub/dashboard/src/components/toc-sidebar.js"
|
||||
target_upstream_file: "src/client/toc.ts"
|
||||
upstream_pr_url: null
|
||||
---
|
||||
|
||||
# Upstream PR: Add injectTocTop() utility for injecting elements into the TOC sidebar
|
||||
|
||||
## Summary
|
||||
|
||||
Propose adding an `injectTocTop(id, element)` utility to Observable Framework
|
||||
that allows dashboard pages to prepend arbitrary HTML elements at the top of the
|
||||
automatically-generated table-of-contents sidebar. This enables KPI cards, live
|
||||
status indicators, and other contextual widgets to live alongside the page's
|
||||
section links.
|
||||
|
||||
## Motivation
|
||||
|
||||
Observable Framework generates a TOC sidebar from headings automatically, but
|
||||
provides no standard way to inject content into it from page JavaScript. As a
|
||||
result, every project that wants sidebar widgets must implement its own DOM
|
||||
manipulation workaround.
|
||||
|
||||
By upstreaming a small, focused utility, the community gets a stable API for
|
||||
sidebar injection that doesn't depend on Observable Framework's internal DOM
|
||||
structure.
|
||||
|
||||
## Local Component
|
||||
|
||||
**Path in this repo**: `state-hub/dashboard/src/components/toc-sidebar.js`
|
||||
**Origin story**: Created 2026-02-26 during implementation of the Decisions KPI
|
||||
dashboard (State Hub v0.2). The component provides two utilities:
|
||||
- `injectTocTop(id, element)`: remove-then-prepend to the TOC aside element
|
||||
- `withDocHelp(element, docPath)`: attaches a `?` button that opens a doc page
|
||||
as an iframe overlay
|
||||
|
||||
## Target Upstream Location
|
||||
|
||||
**Repo**: `observablehq/framework`
|
||||
**File**: `src/client/toc.ts` (or a new `src/client/toc-inject.ts`)
|
||||
|
||||
## Draft PR Body
|
||||
|
||||
```markdown
|
||||
## Summary
|
||||
|
||||
Add `injectTocTop(id, element)` — a small utility for injecting custom elements
|
||||
at the top of the Observable Framework table-of-contents sidebar.
|
||||
|
||||
## Motivation
|
||||
|
||||
Dashboard pages frequently need contextual widgets (KPI boxes, live status
|
||||
indicators, navigation aids) that belong alongside the TOC, not in the page
|
||||
content flow. Currently this requires each project to directly manipulate the
|
||||
`#observablehq-toc` DOM element, coupling page code to an internal DOM detail.
|
||||
|
||||
`injectTocTop` provides a stable API for this pattern:
|
||||
|
||||
```js
|
||||
import {injectTocTop} from "observablehq:toc";
|
||||
|
||||
const myWidget = html`<div class="kpi-box">...</div>`;
|
||||
injectTocTop("my-kpi-box", myWidget);
|
||||
```
|
||||
|
||||
## Changes
|
||||
|
||||
- Add `injectTocTop(id: string, element: HTMLElement): void` to Framework's
|
||||
client runtime
|
||||
- Export from the `observablehq:toc` module (or equivalent public API)
|
||||
- Add documentation page: "Customising the sidebar"
|
||||
|
||||
## Testing
|
||||
|
||||
- [ ] Unit test: `injectTocTop` prepends element to `#observablehq-toc aside`
|
||||
- [ ] Unit test: calling again with same `id` removes old element before
|
||||
inserting new one (idempotent)
|
||||
- [ ] Integration test: injected element appears above TOC links in rendered page
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- The local implementation (`toc-sidebar.js`) uses `querySelector('#observablehq-toc aside')`
|
||||
— this should be replaced with a stable API reference once upstreamed.
|
||||
- The `withDocHelp` utility in the same file is a separate feature; this PR
|
||||
focuses solely on `injectTocTop`.
|
||||
- Observable Framework issue tracker should be checked for any existing
|
||||
discussion of sidebar customisation before opening a new issue.
|
||||
Reference in New Issue
Block a user