Back to index

Proposal Scope Boundary

Two Column
Generates documents
Proposal Scope Boundary

Seen as a design

Take it with you

Copy and paste, or save a file and hand it over. For a machine with no network, one “Everything” file is enough.

Everything

proposal-scope-boundary-everything.md

Everything in this panel, including the contents behind each URL, in one Markdown file

Prompt

1.7 KB
Build an HTML document with "Proposal Scope Boundary". This layout runs, so there is no composition to rebuild — what it needs is content.

## What this layout does
Proposal Scope Boundary with explicit source values and reading conditions.

## What you have to supply
- Provide the source values, labels and decision conditions described by the schema.

## The shape of the input
- `title` — string — 結論を伝える見出し
- `subtitle` — string? — 出典・時点・母集団や仮定
- `inScope` — array (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) — 今回の対象
- `outOfScope` — array (0, 1, 2, 3, 4, 5, 6, 7, 8) — 今回の対象外
- `dependencies` — array (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) — 成立の前提となる依存事項
- `acceptance` — array (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) — 完了判定の条件
- `owner` — string — 範囲変更の判断責任者

schema.ts holds the machine-checkable validation. Ask rather than guess when an input is missing.

## When not to use it
- Do not compare values with incompatible units, populations, or assumptions.

## How to build it
Put the input in a JSON file and run:

```bash
node scripts/render.mjs proposal-scope-boundary <input.json> --theme ink -o out.html
```

The output is one self-contained file and fetches nothing at render time.

## The source
- https://design-vault.pages.dev/designs/proposal-scope-boundary/source/template.tsx
- https://design-vault.pages.dev/designs/proposal-scope-boundary/source/schema.ts
- https://design-vault.pages.dev/designs/proposal-scope-boundary/source/sample-data.json
- https://design-vault.pages.dev/designs/proposal-scope-boundary/sample.html

Files

Template, input schema, sample data and metadata. This document was generated from those four. The generated document

template.tsx

6.7 KB

/designs/proposal-scope-boundary/source/template.tsx

Show contents
import type { ReactNode } from "react";
import type { Props } from "./schema";
function Notes({children}:{children:ReactNode}) { return <details><summary>データ・判断条件を確認</summary>{children}</details>; }

const CSS = String.raw`
.asset{font-family:var(--font-sans);color:var(--color-primary);background:var(--color-surface);max-width:var(--container-slide);margin:auto;padding:3rem 2rem;line-height:1.6;font-size:var(--text-body-sm)}
.asset *{box-sizing:border-box}.asset header{margin-bottom:2rem}.asset .eyebrow{font-family:var(--font-mono);font-size:var(--text-label);letter-spacing:.08em;color:var(--color-secondary);margin-bottom:.75rem}.asset h1{font-size:var(--text-h1);font-weight:700;line-height:1.35;letter-spacing:-.025em;max-width:32em}.asset h2{font-size:var(--text-h3);font-weight:600;margin-bottom:.75rem}.asset h3{font-size:var(--text-body-md);font-weight:600}.asset .subtitle,.asset .muted{color:var(--color-secondary)}.asset .subtitle{margin-top:.75rem}.asset .number{font-variant-numeric:tabular-nums;font-family:var(--font-mono)}.asset .hero-number{font-size:var(--text-display);line-height:1.2;font-weight:700;letter-spacing:-.04em}.asset .callout{border-left:.25rem solid var(--color-tertiary);padding:1rem 1.5rem;background:var(--color-surface-subtle);margin-bottom:1.5rem}.asset .grid2{display:grid;grid-template-columns:1fr 1fr;gap:1.5rem}.asset .grid3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1.5rem}.asset .panel{padding:1.5rem;background:var(--color-surface-subtle);border-radius:var(--radius-md);min-width:0}.asset .rule{border-top:1px solid var(--color-outline);padding-top:1rem;margin-top:1rem}.asset .pill{display:inline-block;padding:.25rem .75rem;border:1px solid var(--color-outline);border-radius:var(--radius-full);font-size:var(--text-label)}.asset .focus{background:var(--color-tertiary-container);color:var(--color-on-tertiary-container)}.asset .dark{background:var(--color-primary);color:var(--color-on-primary)}.asset .dark .muted{color:var(--color-on-primary-container)}.asset .row{display:grid;grid-template-columns:12rem minmax(0,1fr) 6rem;gap:1rem;align-items:center;padding:.75rem 0;border-bottom:1px solid var(--color-outline)}.asset .row>*{min-width:0}.asset .track{height:1rem;position:relative;background:var(--color-neutral);border-radius:var(--radius-sm)}.asset .bar{height:100%;background:var(--color-tertiary);border-radius:var(--radius-sm)}.asset .track.tall{height:2rem}.asset .flex{display:flex;gap:1rem;align-items:center;justify-content:space-between;flex-wrap:wrap}.asset .stack>*+*{margin-top:1rem}.asset ul{list-style:disc;padding-left:1.25rem}.asset li+li{margin-top:.5rem}.asset .plot{display:block;width:100%;height:auto;overflow:visible}.asset .plot text{font-family:var(--font-sans);font-size:14px;fill:var(--color-secondary)}.asset .plot .ink{fill:var(--color-primary)}.asset .plot .axis{stroke:var(--color-outline);stroke-width:1}.asset .plot .accent{stroke:var(--color-tertiary);fill:none;stroke-width:3}.asset .legend{display:flex;gap:1.5rem;flex-wrap:wrap;font-size:var(--text-label);margin-bottom:1rem}.asset .legend b{display:inline-block;width:.75rem;height:.75rem;margin-right:.5rem}.asset .ledger{border-collapse:collapse;width:100%;font-variant-numeric:tabular-nums}.asset .ledger caption{text-align:left;font-weight:600;margin:1rem 0}.asset .ledger th{font-weight:600;color:var(--color-secondary);text-align:left}.asset .ledger th,.asset .ledger td{padding:.75rem 1rem;border-bottom:1px solid var(--color-outline);vertical-align:top;overflow-wrap:anywhere}.asset .ledger th:first-child,.asset .ledger td:first-child{padding-left:0}.asset .ledger th:last-child,.asset .ledger td:last-child{padding-right:0}.asset .ledger tbody tr:hover{background:var(--color-surface-subtle)}.asset details{border-top:1px solid var(--color-outline);margin-top:1.5rem;padding-top:1rem}.asset summary{cursor:pointer;color:var(--color-secondary);padding:.5rem 0;min-height:2.75rem}.asset summary:focus-visible{outline:2px solid var(--color-tertiary);outline-offset:.25rem}.asset .small{font-size:var(--text-label)}.asset .mobile-only{display:none}.asset .horizontal-list{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1rem}.asset .board-column{border-top:.25rem solid var(--color-primary);padding-top:1rem;min-width:0}.asset .board-item{padding:1rem 0;border-bottom:1px solid var(--color-outline)}.asset .board-item p{margin-top:.5rem}.asset .statement{font-size:var(--text-h2);line-height:1.5;font-weight:600}.asset .meta-line{margin-top:.75rem;font-size:var(--text-label);color:var(--color-secondary)}.asset pre{white-space:pre-wrap;overflow-wrap:anywhere}.asset footer{margin-top:2rem;font-size:var(--text-label);color:var(--color-secondary)}
@media(max-width:640px){.asset{padding:1.5rem 1rem}.asset h1{font-size:var(--text-h2)}.asset header{margin-bottom:1.5rem}.asset .grid2,.asset .grid3,.asset .horizontal-list{grid-template-columns:1fr}.asset .row{grid-template-columns:minmax(0,1fr) 5rem;gap:.5rem}.asset .row>:first-child{grid-column:1/-1}.asset .desktop-only{display:none!important}.asset .mobile-only{display:block}.asset .panel{padding:1rem}.asset .ledger,.asset .ledger tbody,.asset .ledger tr,.asset .ledger td{display:block}.asset .ledger thead{display:none}.asset .ledger tr{padding:.75rem 0;border-bottom:1px solid var(--color-outline)}.asset .ledger td{display:grid;grid-template-columns:7rem minmax(0,1fr);gap:.75rem;border:0;padding:.25rem 0!important}.asset .ledger td:before{content:attr(data-label);color:var(--color-secondary);font-size:var(--text-label)}.asset .hero-number{font-size:var(--text-h1)}}
@media print{.asset{max-width:none;padding:1rem}.asset details>*{display:block}.asset summary{display:none}}
`;

export default function Template(d: Props) {

return <section className="asset asset-proposal-scope-boundary"><style>{CSS}</style><header><p className="eyebrow">PROPOSAL SCOPE BOUNDARY</p><h1>{d.title}</h1>{d.subtitle && <p className="subtitle">{d.subtitle}</p>}</header>
<div className="grid2"><article className="panel focus"><h2>今回の対象</h2><ul>{d.inScope.map((s,i)=><li key={i}>{s}</li>)}</ul></article><article className="panel"><h2>今回の対象外</h2><ul>{d.outOfScope.map((s,i)=><li key={i}>{s}</li>)}</ul></article></div><div className="grid2 rule"><article><h2>依存事項</h2><ul>{d.dependencies.map((s,i)=><li key={i}>{s}</li>)}</ul></article><article><h2>受入条件</h2><ul>{d.acceptance.map((s,i)=><li key={i}>{s}</li>)}</ul></article></div><Notes><p>範囲変更の判断責任者:{d.owner}</p><p>対象外は永久に実施しないという意味ではありません。追加する場合は範囲・期間・費用を再合意します。</p></Notes>
<footer>対象外と未確認を混同せず、完了を観察できる受入条件を書く。</footer></section>;
}

schema.ts

886 B

/designs/proposal-scope-boundary/source/schema.ts

Show contents
import { z } from "zod";
const text = z.string().trim().min(1).max(160);
const short = z.string().trim().min(1).max(48);
const value = z.number().finite();
const positive = value.positive();

export const schema = z.object({
  title: text.describe("結論を伝える見出し"),
  subtitle: text.optional().describe("出典・時点・母集団や仮定"),
  inScope:z.array(text).min(2).max(5).describe("今回の対象"),outOfScope:z.array(text).min(1).max(5).describe("今回の対象外"),dependencies:z.array(text).min(1).max(4).describe("成立の前提となる依存事項"),acceptance:z.array(text).min(2).max(5).describe("完了判定の条件"),owner:short.describe("範囲変更の判断責任者"),
}).strict().refine(d=>!d.inScope.some(s=>d.outOfScope.includes(s)),"同じ項目を対象と対象外の両方に置かない");
export type Props = z.infer<typeof schema>;

meta.yaml

1.6 KB

/designs/proposal-scope-boundary/source/meta.yaml

Show contents
id: proposal-scope-boundary
name:
  ja: 提案範囲と受入条件
  en: Proposal Scope Boundary
purpose:
  ja: 対象・対象外・依存事項・受入条件を対比し、範囲の認識を揃える。
  en: Proposal Scope Boundary with explicit source values and reading conditions.
status: published
still: ./still.png
category: specification
catalogOrder: 710
jobs:
  - assign-governance
useCases:
  - summary
layoutKinds:
  - 2-column
tags:
  - proposal-scope-boundary
  - specification
  - offline
  - responsive
whenToUse:
  - ja: 対象・対象外・依存事項・受入条件を対比し、範囲の認識を揃える。
    en: Use to communicate proposal scope boundary.
avoidWhen:
  - ja: 同じ条件・単位で比較できないデータには使わない
    en: Do not compare values with incompatible units, populations, or assumptions.
requiredInputs:
  - ja: 対象外と未確認を混同せず、完了を観察できる受入条件を書く。
    en: Provide the source values, labels and decision conditions described by the schema.
relatedLayouts:
  - fit-gap-assessment
  - decision-record
dataSchema:
  title: string — 結論を伝える見出し
  subtitle: string? — 出典・時点・母集団や仮定
  inScope: array (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) — 今回の対象
  outOfScope: array (0, 1, 2, 3, 4, 5, 6, 7, 8) — 今回の対象外
  dependencies: array (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) — 成立の前提となる依存事項
  acceptance: array (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) — 完了判定の条件
  owner: string — 範囲変更の判断責任者
sources: []

sample-data.json

679 B

/designs/proposal-scope-boundary/source/sample-data.json

Show contents
{
  "title": "初期導入の範囲と、完了判定を先に合意する",
  "subtitle": "架空サンプル|レイアウトの使用例",
  "inScope": [
    "Web申込の入力支援",
    "受付通知の改善",
    "2拠点での試行"
  ],
  "outOfScope": [
    "審査ロジックの変更",
    "全拠点への展開",
    "旧帳票の全面置換"
  ],
  "dependencies": [
    "審査APIの仕様確定",
    "試行拠点の担当者確保"
  ],
  "acceptance": [
    "主要な受付ケースで受入試験を完了",
    "運用手順と問合せ窓口を確定",
    "試行の評価結果を責任者へ提示"
  ],
  "owner": "業務・IT合同責任者"
}