Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .github/workflows/deploy-website.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,18 +68,22 @@ jobs:
set -e
ls -la
test -f index.html || { echo "ERROR: index.html not found"; exit 1; }
test -f docs/index.html || { echo "ERROR: docs page not found"; exit 1; }
test -f main.client.dart.js || { echo "ERROR: client bundle not found"; exit 1; }
echo "Build output OK"

# The project Pages site lives at the /dnd_kit/ subpath. jaspr build has no
# --base-href flag and Document emits <base href="/"/>, so rewrite it here
# (asset URLs in index.html are relative and resolve against this base).
# on every generated page (relative asset and cross-page URLs resolve
# against this base).
- name: Set base href for the project subpath
working-directory: website/build/jaspr
run: |
set -e
sed -i 's|<base href="/"/>|<base href="/dnd_kit/"/>|' index.html
find . -name '*.html' -exec \
sed -i 's|<base href="/"/>|<base href="/dnd_kit/"/>|' {} +
grep -q '<base href="/dnd_kit/"/>' index.html
grep -q '<base href="/dnd_kit/"/>' docs/index.html
touch .nojekyll

- name: Upload Pages artifact
Expand Down
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,11 @@ workspace unification through `US-061`, and the Jaspr sortable preset through
axis-aware shared-core implementation slice, and the Flutter execution-layer
adoption through `US-065`, plus the Jaspr execution-layer adoption through
`US-066`, plus the Jaspr example feature gallery through `US-067`, plus the
Jaspr drag overlay controller rebind fix through `US-068`, and the shared
experimental multi-container parity slice through `US-076`.
Jaspr drag overlay controller rebind fix through `US-068`, the shared
experimental multi-container parity slice through `US-076`, the
production-ready multi-container graduation and website showcase through
`US-078`, and the coordinated family stable `0.4.0` publication (`dnd_kit`,
`dnd_kit_flutter`, `dnd_kit_jaspr`) through `US-079`.

The living source of truth is split from historical [SPEC.md](SPEC.md) input
material into product docs, story packets, validation expectations, and decision
Expand Down
28 changes: 28 additions & 0 deletions docs/product/release-roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,24 @@ publication after the multi-container graduation work has soaked:
Phase README:
`docs/stories/phase-31-coordinated-family-stable-0-4-0-release/README.md`.

## Phase 32 - Website Docs Page And Post-0.4.0 Doc Alignment

Close the docs/adoption gap left after the stable `0.4.0` publication:

- `US-080`: give the website a real Getting Started docs page on its own `/docs`
route (replacing the in-page `#docs` placeholder) and align the root README
status plus the Jaspr/Flutter package READMEs with the shipped stable `0.4.0`
family;
- `US-081`: expand `/docs` into a multi-page docs section (shared sidebar shell,
right-rail TOC, prev/next pager, Flutter|Jaspr code tabs) covering the nine
core pages;
- `US-082`: complete the coverage with four more Concepts pages (collision,
sensors, modifiers, auto-scroll), an API Reference page, and a collapsible
mobile docs menu.

Phase README:
`docs/stories/phase-32-website-docs-page-and-doc-alignment/README.md`.

## Current State

The repository has implemented work through `US-079`. The Flutter adapter, the
Expand Down Expand Up @@ -360,6 +378,16 @@ packet for that line: the prepared `0.4.0-dev.1` family metadata was promoted
to stable `0.4.0`, local release proof passed through the shared verifier, and
the three packages published to pub.dev in dependency order on 2026-06-24:
`dnd_kit 0.4.0` -> `dnd_kit_flutter 0.4.0` -> `dnd_kit_jaspr 0.4.0`.
Phase 32 then closed the post-release docs/adoption gap: `US-080` gave the
website a real Getting Started docs page on its own statically generated `/docs`
route (replacing the `#docs` placeholder) and aligned the root README plus the
Jaspr and Flutter package READMEs with the shipped stable `0.4.0` family, and
`US-081` expanded `/docs` into a multi-page docs section — a shared `DocsShell`
(grouped sidebar, right-rail TOC, prev/next pager), a Flutter|Jaspr code-tab
block, and nine core pages over the shared engine surface, and `US-082`
completed the coverage with four more Concepts pages (collision, sensors,
modifiers, auto-scroll), an API Reference page, and a collapsible mobile docs
menu.
Future work should keep extending this roadmap through new product docs, story
packets, and decisions rather than by reviving the old umbrella/core topology
from the historical specs.
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Phase 32 - Website Docs Page And Post-0.4.0 Doc Alignment

The coordinated family stable `0.4.0` published on 2026-06-24 (Phase 31), but
public-facing docs still described the pre-release state: the website had only a
`#docs` placeholder, the root README status stopped at `US-076`, and the Jaspr
and Flutter package READMEs still carried "dev release" wording.

This phase closes that adoption gap across two normal-lane stories:

- `US-080` gave the website a real Getting Started docs page on its own `/docs`
route (the marketing site was previously a single page with an in-page
`#docs` anchor placeholder) and aligned the root README plus the Jaspr and
Flutter package READMEs with the shipped stable `0.4.0` family;
- `US-081` then expanded `/docs` from that single page into a dndkit.com-style
multi-page docs section: a shared `DocsShell` (grouped sidebar, right-rail
"On this page" TOC, previous/next pager), a Flutter|Jaspr `CodeTabs` block,
and nine core pages (Overview, Installation, Quickstart, Draggable,
Droppable, Drag overlay, Sortable lists, Multi-container, Accessibility);
- `US-082` completed the docs coverage: four more Concepts pages (Collision
detection, Sensors & activation, Modifiers, Auto-scroll) written against the
real engine API, an API Reference page (dartdoc + changelog links), and a
collapsible mobile docs menu so the section is navigable below the `lg`
breakpoint.

## Principle

Doc-alignment and website work in this phase must:

- introduce real on-site routing rather than another in-page anchor: the docs
page is a separate statically generated route (`docs/index.html`), reached
from the nav and footer;
- keep the static build deployable under the `/dnd_kit/` project Pages subpath —
every generated page needs its `<base href>` rewritten, and cross-page links
resolve relative to that base;
- describe only the already-shipped `0.4.0` surface; no new product behavior.

## Delivery Sequence

| Story | Scope | Decision |
| --- | --- | --- |
| **US-080** | Add the website `/docs` Getting Started page (jaspr_router) and align root/package READMEs + website docs link with stable `0.4.0` | No ADR (docs/adoption work under the existing website and package-topology decisions) |
| **US-081** | Expand `/docs` into a multi-page docs section: shared `DocsShell` (sidebar + TOC + pager), Flutter\|Jaspr `CodeTabs`, nine core pages | No ADR (unified single docs tree with per-snippet adapter tabs, under the existing website decisions) |
| **US-082** | Complete docs coverage: four Concepts pages (collision, sensors, modifiers, auto-scroll), an API Reference page, and a mobile docs menu | No ADR (docs content + responsive nav under the existing website decisions) |

## Validation Ladder

- Static-site proof: `tool/styles.sh --minify` plus
`dart pub global run jaspr_cli:jaspr build` generate both the `/` and `/docs`
routes, and `website/build/jaspr/docs/index.html` is present with the
per-route `<title>` and relative asset URLs.
- Analyzer/format proof: `fvm dart analyze` and `fvm dart format` stay clean for
the `website` package.
- Deploy proof: the deploy workflow rewrites `<base href>` on every generated
HTML file and verifies both `index.html` and `docs/index.html`.
2 changes: 1 addition & 1 deletion packages/dnd_kit_flutter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,5 +154,5 @@ drag runtime.
| Package | Use it for |
| ------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| [`dnd_kit_flutter`](https://pub.dev/packages/dnd_kit_flutter) | Flutter apps — widgets, sensors, overlays, and sortable presets. |
| [`dnd_kit_jaspr`](https://pub.dev/packages/dnd_kit_jaspr) | Jaspr (Dart web) apps — the current dev adapter release. |
| [`dnd_kit_jaspr`](https://pub.dev/packages/dnd_kit_jaspr) | Jaspr (Dart web) apps — the web adapter over the shared engine. |
| [`dnd_kit`](https://pub.dev/packages/dnd_kit) | The shared, framework-agnostic engine. |
2 changes: 1 addition & 1 deletion packages/dnd_kit_jaspr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Flutter behave as peer adapters over one drag runtime — the same domain model,
drag lifecycle, collision logic, modifiers, sortable math, and auto-scroll
curve. It depends only on `dnd_kit` and `jaspr` (no Flutter).

> Status: current public development release. This package provides `DndScope`,
> Status: stable `0.4.0` release. This package provides `DndScope`,
> `DndController`, `DndDraggable`, `DndDroppable`, `DndDragHandle`,
> `DndDragOverlay`, `DndAutoScroll`, `DndLiveRegion`, `SortableScope`, and
> `SortableItem` over the shared runtime. Shared modifiers and sortable
Expand Down
8 changes: 8 additions & 0 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.23.1"
jaspr_router:
dependency: transitive
description:
name: jaspr_router
sha256: "43abdfd63c19cae8faac50334c7f3065635bac3e85fd558b6076517978ade64a"
url: "https://pub.dev"
source: hosted
version: "0.8.2"
jaspr_test:
dependency: transitive
description:
Expand Down
4 changes: 3 additions & 1 deletion website/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,6 @@ static host (GitHub Pages, Netlify, Cloudflare Pages, …).

- GitHub: https://github.com/iamv4g/dnd_kit
- pub.dev: https://pub.dev/packages/dnd_kit_jaspr
- Docs: _coming soon_ (currently a `#docs` placeholder in the nav/footer)
- Docs: the multi-page documentation section under the `/docs` routes
(`lib/docs/`), linked from the nav and footer. `lib/docs/docs_nav.dart` is the
single source of truth for the sidebar, pager, and routes.
104 changes: 104 additions & 0 deletions website/lib/app.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import 'package:jaspr/jaspr.dart';
import 'package:jaspr_router/jaspr_router.dart';

import 'docs/pages/accessibility_page.dart';
import 'docs/pages/autoscroll_page.dart';
import 'docs/pages/collision_page.dart';
import 'docs/pages/draggable_page.dart';
import 'docs/pages/droppable_page.dart';
import 'docs/pages/install_page.dart';
import 'docs/pages/modifiers_page.dart';
import 'docs/pages/multi_container_page.dart';
import 'docs/pages/overlay_page.dart';
import 'docs/pages/overview_page.dart';
import 'docs/pages/quickstart_page.dart';
import 'docs/pages/reference_page.dart';
import 'docs/pages/sensors_page.dart';
import 'docs/pages/sortable_page.dart';
import 'site.dart';

/// Top-level routing. In static (SSG) mode jaspr generates one HTML file per
/// route, so this emits `index.html` (the marketing home) plus a page under
/// `docs/` for each documentation route.
class App extends StatelessComponent {
const App({super.key});

@override
Component build(BuildContext context) {
return Router(
routes: [
Route(path: '/', builder: (context, state) => const Site()),
Route(
path: '/docs',
title: 'Documentation · dnd_kit',
builder: (context, state) => const OverviewPage(),
),
Route(
path: '/docs/install',
title: 'Installation · dnd_kit',
builder: (context, state) => const InstallPage(),
),
Route(
path: '/docs/quickstart',
title: 'Quickstart · dnd_kit',
builder: (context, state) => const QuickstartPage(),
),
Route(
path: '/docs/draggable',
title: 'Draggable · dnd_kit',
builder: (context, state) => const DraggablePage(),
),
Route(
path: '/docs/droppable',
title: 'Droppable · dnd_kit',
builder: (context, state) => const DroppablePage(),
),
Route(
path: '/docs/overlay',
title: 'Drag overlay · dnd_kit',
builder: (context, state) => const OverlayPage(),
),
Route(
path: '/docs/collision',
title: 'Collision detection · dnd_kit',
builder: (context, state) => const CollisionPage(),
),
Route(
path: '/docs/sensors',
title: 'Sensors & activation · dnd_kit',
builder: (context, state) => const SensorsPage(),
),
Route(
path: '/docs/modifiers',
title: 'Modifiers · dnd_kit',
builder: (context, state) => const ModifiersPage(),
),
Route(
path: '/docs/auto-scroll',
title: 'Auto-scroll · dnd_kit',
builder: (context, state) => const AutoscrollPage(),
),
Route(
path: '/docs/sortable',
title: 'Sortable lists · dnd_kit',
builder: (context, state) => const SortablePage(),
),
Route(
path: '/docs/multi-container',
title: 'Multi-container sortable · dnd_kit',
builder: (context, state) => const MultiContainerPage(),
),
Route(
path: '/docs/accessibility',
title: 'Accessibility · dnd_kit',
builder: (context, state) => const AccessibilityPage(),
),
Route(
path: '/docs/reference',
title: 'API reference · dnd_kit',
builder: (context, state) => const ReferencePage(),
),
],
);
}
}
6 changes: 4 additions & 2 deletions website/lib/data/site_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ class SiteLinks {
static const pubFlutter = 'https://pub.dev/packages/dnd_kit_flutter';
static const pubJaspr = 'https://pub.dev/packages/dnd_kit_jaspr';

/// Docs site is built later; placeholder for now.
static const docs = '#docs';
/// The on-site Getting Started docs page (`/docs` route). Written relative so
/// it resolves against the document `<base href>` on both the project Pages
/// subpath (`/dnd_kit/docs/`) and a local server root (`/docs/`).
static const docs = 'docs/';
}

/// In-page nav targets (also the reorderable nav pills).
Expand Down
75 changes: 75 additions & 0 deletions website/lib/docs/code_tabs.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import 'package:jaspr/dom.dart';
import 'package:jaspr/jaspr.dart';

/// A code block with a Flutter / Jaspr toggle, so one snippet shows the same
/// API on both adapters. Server-rendered with the Flutter tab active, then
/// hydrated to switch tabs on the client.
@client
class CodeTabs extends StatefulComponent {
const CodeTabs({
required this.flutter,
required this.jaspr,
this.flutterFile = 'main.dart',
this.jasprFile = 'main.dart',
super.key,
});

final String flutter;
final String jaspr;
final String flutterFile;
final String jasprFile;

@override
State<CodeTabs> createState() => _CodeTabsState();
}

class _CodeTabsState extends State<CodeTabs> {
int _tab = 0; // 0 = Flutter, 1 = Jaspr

@override
Component build(BuildContext context) {
final tabs = ['Flutter', 'Jaspr'];
final code = _tab == 0 ? component.flutter : component.jaspr;
final file = _tab == 0 ? component.flutterFile : component.jasprFile;
return div(
classes:
'overflow-hidden rounded-2xl border border-line bg-surface shadow-lift',
[
div(
classes:
'flex items-center gap-3 border-b border-line bg-raised px-4 py-2.5',
[
div(
classes: 'flex items-center gap-1',
attributes: const {'role': 'tablist'},
[
for (var i = 0; i < tabs.length; i++)
button(
classes:
'rounded-full px-3 py-1 font-mono text-xs transition-colors '
'${i == _tab ? 'bg-accent text-white' : 'text-muted hover:text-ink'}',
attributes: {
'type': 'button',
'role': 'tab',
'aria-selected': (i == _tab).toString(),
},
onClick: () => setState(() => _tab = i),
[.text(tabs[i])],
),
],
),
span(classes: 'ml-auto font-mono text-xs text-muted', [
.text(file),
]),
],
),
Component.element(
tag: 'pre',
classes:
'overflow-x-auto p-5 font-mono text-sm leading-relaxed text-ink',
children: [.text(code)],
),
],
);
}
}
Loading
Loading