作品として見る 生成された文書そのもの — 切り替えも開閉もそのまま動きます
作品として見る 生成された文書そのもの — 切り替えも開閉もそのまま動きます
コピーして貼るか、ファイルに保存して渡す。ネットにつながらない環境には「全部入り」を 1 つ渡せば足りる。
このパネルの中身を、URL の先にあるファイルの中身まで含めて 1 つにまとめた Markdown — 大きいのでファイルで渡す(コピーは 32KB まで)
「変革影響評価」でHTML資料を作ってください。この型は実行できるので、版面を組み直す必要はありません — 必要なのは中身です。 ## この型がすること 対象グループごとに変更前後・影響の大きさ・準備状況と支援策を整理する。 ## 渡す必要があるもの - 影響グループ、変更前後の状態、方向・強さ、準備状況、支援策と責任者を定義する。 ## 入力の形 - `title` — string — 変革の要点 - `subtitle` — string? — 対象範囲・基準日・前提 - `initiative` — string — 対象の施策・変更 - `impacts` — array (3–10) — グループ別の状態変化、影響、準備、支援策 入力の機械可読な検証は schema.ts が持ちます。足りない入力は推測せず質問してください。 ## 向かない場合 - 発生可能性と損失の大きさを評価する場合は、risk-matrix-registerを使う。 - 周知相手・連絡手段・日程だけを決める場合は、stakeholder-engagement-planを使う。 ## 作り方 入力を JSON にまとめ、次を実行します。 ```bash node scripts/render.mjs change-impact-assessment <入力.json> --theme ink -o out.html ``` 出力は 1 ファイルで完結し、外部から何も読み込みません。 ## 原本 - https://design-vault.pages.dev/designs/change-impact-assessment/source/template.tsx - https://design-vault.pages.dev/designs/change-impact-assessment/source/schema.ts - https://design-vault.pages.dev/designs/change-impact-assessment/source/sample-data.json - https://design-vault.pages.dev/designs/change-impact-assessment/sample.html
テンプレート・入力スキーマ・サンプルデータ・メタ情報。この文書はこの 4 つから生成されています。 生成された文書
/designs/change-impact-assessment/source/template.tsx
import type { Props } from "./schema";
const CSS = String.raw`
.asset-change-impact-assessment{font-family:var(--font-sans);color:var(--color-primary);background:var(--color-surface);max-width:var(--container-slide);margin:auto;padding:3rem 2.5rem;line-height:1.6;font-size:var(--text-body-sm)}
.asset-change-impact-assessment *{box-sizing:border-box}.asset-change-impact-assessment header{margin-bottom:1.5rem}.asset-change-impact-assessment .eyebrow{font-family:var(--font-mono);font-size:var(--text-label);color:var(--color-tertiary);margin-bottom:.75rem}.asset-change-impact-assessment h1{font-size:var(--text-h1);line-height:1.3;max-width:28em}.asset-change-impact-assessment .subtitle{margin-top:.75rem;color:var(--color-secondary)}
.asset-change-impact-assessment .summary{display:flex;gap:1.5rem;flex-wrap:wrap;padding:.75rem 0;border-block:2px solid var(--color-primary);margin-bottom:1rem}.asset-change-impact-assessment .summary p{margin:0;color:var(--color-secondary);font-size:var(--text-label)}.asset-change-impact-assessment .summary strong{font-family:var(--font-mono);font-size:var(--text-h3);color:var(--color-primary);margin-right:.35rem}
.asset-change-impact-assessment .impact{display:grid;grid-template-columns:minmax(0,.9fr) minmax(0,1.3fr) minmax(0,1.3fr) minmax(0,1.4fr);gap:1rem;padding:1rem 0;border-bottom:1px solid var(--color-outline);min-width:0}.asset-change-impact-assessment .impact>*{min-width:0}.asset-change-impact-assessment .impact-head{display:flex;gap:.55rem;flex-wrap:wrap;align-items:baseline}.asset-change-impact-assessment .impact-id{font-family:var(--font-mono);font-size:var(--text-label);color:var(--color-tertiary)}.asset-change-impact-assessment .impact-head strong{font-size:var(--text-body-md)}.asset-change-impact-assessment .tag{display:inline-block;padding:.1rem .4rem;border:1px solid var(--color-outline);font-size:var(--text-label);color:var(--color-secondary)}.asset-change-impact-assessment .tag-emphasis{border-color:var(--color-tertiary);color:var(--color-primary)}.asset-change-impact-assessment .label{display:block;color:var(--color-secondary);font-size:var(--text-label);margin-bottom:.2rem}.asset-change-impact-assessment .state{overflow-wrap:anywhere}.asset-change-impact-assessment .arrow{display:block;color:var(--color-tertiary);font-size:var(--text-label);margin:.2rem 0}.asset-change-impact-assessment .support{overflow-wrap:anywhere}.asset-change-impact-assessment .owner{display:block;margin-top:.45rem;color:var(--color-secondary);font-size:var(--text-label)}.asset-change-impact-assessment footer{margin-top:1.1rem;padding-top:.7rem;border-top:1px solid var(--color-outline);font-size:var(--text-label);color:var(--color-secondary)}.asset-change-impact-assessment .still-svg{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
@media(max-width:760px){.asset-change-impact-assessment{padding:1.5rem 1rem}.asset-change-impact-assessment h1{font-size:var(--text-h2)}.asset-change-impact-assessment .impact{grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:.75rem;padding:.9rem 0}.asset-change-impact-assessment .impact-meta{grid-column:1/3}.asset-change-impact-assessment .support{grid-column:1/3}.asset-change-impact-assessment .summary{gap:1rem}}
@media(print){.asset-change-impact-assessment{max-width:none;padding:1rem}.asset-change-impact-assessment .impact{break-inside:avoid}}
`;
const areaNames = { process: "業務", role: "役割", technology: "技術", skill: "スキル", policy: "方針", data: "データ" };
const directionNames = { positive: "効果", negative: "負担", mixed: "効果と負担" };
const magnitudeNames = { low: "小", moderate: "中", high: "大", critical: "重大" };
const readinessNames = { ready: "準備済み", "support-needed": "支援が必要", unknown: "未確認" };
const compact = (value: string, max: number) => [...value].length > max ? `${[...value].slice(0, max - 1).join("")}…` : value;
function Still({ data }: { data: Props }) {
const rows = data.impacts.slice(0, 10);
const rowHeight = 51;
return <svg className="still-svg" data-layout-still="true" width="1280" height="720" viewBox="0 0 1280 720" aria-hidden="true">
<rect width="1280" height="720" fill="var(--color-surface)" />
<text x="48" y="48" fontSize="14" fontFamily="sans-serif" fill="var(--color-secondary)">{data.initiative}</text>
<text x="48" y="88" fontSize="28" fontWeight="700" fontFamily="sans-serif" fill="var(--color-on-surface)">{compact(data.title, 55)}</text>
<text x="48" y="118" fontSize="13" fontFamily="sans-serif" fill="var(--color-secondary)">変更前の状態 → 変更後の状態 → 支援策</text>
<text x="48" y="151" fontSize="12" fontFamily="sans-serif" fill="var(--color-secondary)">対象グループ</text>
<text x="320" y="151" fontSize="12" fontFamily="sans-serif" fill="var(--color-secondary)">変更前 → 変更後</text>
<text x="790" y="151" fontSize="12" fontFamily="sans-serif" fill="var(--color-secondary)">影響 / 準備</text>
<text x="1010" y="151" fontSize="12" fontFamily="sans-serif" fill="var(--color-secondary)">支援策</text>
{rows.map((impact, index) => {
const y = 181 + index * rowHeight;
return <g key={impact.id}>
<line x1="48" x2="1232" y1={y - 17} y2={y - 17} stroke="var(--color-outline)" />
<text x="50" y={y + 2} fontSize="10" fontFamily="sans-serif" fill="var(--color-tertiary)">{impact.id}</text>
<text x="50" y={y + 18} fontSize="12" fontWeight="600" fontFamily="sans-serif" fill="var(--color-on-surface)">{compact(impact.affectedGroup, 26)}</text>
<text x="320" y={y + 2} fontSize="11" fontFamily="sans-serif" fill="var(--color-on-surface)">{compact(impact.currentState, 36)}</text>
<text x="320" y={y + 18} fontSize="10" fontFamily="sans-serif" fill="var(--color-tertiary)">↓ {compact(impact.futureState, 36)}</text>
<text x="790" y={y + 2} fontSize="11" fontFamily="sans-serif" fill="var(--color-on-surface)">{directionNames[impact.direction]} · {magnitudeNames[impact.magnitude]}</text>
<text x="790" y={y + 18} fontSize="10" fontFamily="sans-serif" fill="var(--color-secondary)">{areaNames[impact.area]} · {readinessNames[impact.readiness]}</text>
<text x="1010" y={y + 2} fontSize="11" fontFamily="sans-serif" fill="var(--color-on-surface)">{compact(impact.supportAction, 29)}</text>
<text x="1010" y={y + 18} fontSize="10" fontFamily="sans-serif" fill="var(--color-secondary)">{compact(impact.owner, 22)}</text>
</g>;
})}
<text x="48" y="704" fontSize="12" fontFamily="sans-serif" fill="var(--color-secondary)">{data.impacts.length}件の影響 · 支援策を責任者へつなぐ</text>
</svg>;
}
export default function Template(data: Props) {
const supportCount = data.impacts.filter((impact) => impact.readiness !== "ready").length;
return <section className="asset asset-change-impact-assessment">
<style>{CSS}</style>
<header>
<p className="eyebrow">{data.initiative} · 変更の影響</p>
<h1>{data.title}</h1>
{data.subtitle && <p className="subtitle">{data.subtitle}</p>}
</header>
<div className="summary" aria-label="影響の集計">
<p><strong>{data.impacts.length}</strong>影響項目</p>
<p><strong>{supportCount}</strong>要確認・支援あり</p>
<p>影響の強さと準備状況を別々に確認</p>
</div>
<div>
{data.impacts.map((impact) => <article className="impact" key={impact.id}>
<div>
<div className="impact-head"><code className="impact-id">{impact.id}</code><strong>{impact.affectedGroup}</strong></div>
<p className="impact-meta"><span className="tag">{areaNames[impact.area]}</span> <span className="tag">{directionNames[impact.direction]}</span> <span className="tag tag-emphasis">影響 {magnitudeNames[impact.magnitude]}</span></p>
</div>
<div><span className="label">現在</span><div className="state">{impact.currentState}</div><span className="arrow">変更後</span><div className="state">{impact.futureState}</div></div>
<div><span className="label">準備状況</span><span className="tag tag-emphasis">{readinessNames[impact.readiness]}</span><p className="owner">支援責任者: {impact.owner}</p></div>
<div className="support"><span className="label">必要な支援</span>{impact.supportAction}</div>
</article>)}
</div>
<footer>変化の大きさ・方向と、受け入れ準備は別の観点として確認する。</footer>
<Still data={data} />
</section>;
}
/designs/change-impact-assessment/source/schema.ts
import { z } from "zod";
const text = z.string().trim().min(1).max(160);
const short = z.string().trim().min(1).max(48);
export const impactSchema = z.object({
id: short.describe("影響項目の一意な識別子"),
affectedGroup: short.describe("影響を受ける利用者・チーム"),
area: z.enum(["process", "role", "technology", "skill", "policy", "data"]).describe("変更が及ぶ領域"),
currentState: text.describe("変更前の状態"),
futureState: text.describe("変更後に期待する状態"),
direction: z.enum(["positive", "negative", "mixed"]).describe("期待効果・負担・両面の別"),
magnitude: z.enum(["low", "moderate", "high", "critical"]).describe("変化の大きさ"),
readiness: z.enum(["ready", "support-needed", "unknown"]).describe("受け入れ準備の状態"),
supportAction: text.describe("移行・習得・負担軽減のための支援"),
owner: short.describe("支援策の責任者"),
}).strict();
export const schema = z.object({
title: text.describe("変革の要点"),
subtitle: text.optional().describe("対象範囲・基準日・前提"),
initiative: short.describe("対象の施策・変更"),
impacts: z.array(impactSchema).min(3).max(10).describe("グループ別の変更前後・影響・支援策"),
}).strict().superRefine((data, ctx) => {
const ids = data.impacts.map((impact) => impact.id);
if (new Set(ids).size !== ids.length) {
ctx.addIssue({ code: "custom", path: ["impacts"], message: "影響IDは一意にすること" });
}
});
export type Props = z.infer<typeof schema>;
/designs/change-impact-assessment/source/meta.yaml
id: change-impact-assessment
name:
ja: 変革影響評価
en: Change Impact Assessment
purpose:
ja: 対象グループごとに変更前後・影響の大きさ・準備状況と支援策を整理する。
en: Map current and future states, impact magnitude, readiness, and support actions by affected group.
status: published
still: ./still.png
category: change-management
catalogOrder: 820
jobs:
- explain-structure
- assign-governance
useCases:
- process
layoutKinds:
- table
tags:
- change-impact
- adoption
- operations
- offline
- responsive
whenToUse:
- ja: 業務変更がグループごとに与える効果・負担と、必要な移行支援を計画するとき。
en: Use to plan transition support for the benefits and burdens a change creates for each group.
avoidWhen:
- ja: 発生可能性と損失の大きさを評価する場合は、risk-matrix-registerを使う。
en: Use a risk matrix to assess likelihood and loss magnitude.
- ja: 周知相手・連絡手段・日程だけを決める場合は、stakeholder-engagement-planを使う。
en: Use a stakeholder engagement plan to define audiences, channels, and timing.
requiredInputs:
- ja: 影響グループ、変更前後の状態、方向・強さ、準備状況、支援策と責任者を定義する。
en: Define affected groups, current and future states, direction, magnitude, readiness, support, and owner.
relatedLayouts:
- stakeholder-engagement-plan
- risk-matrix-register
dataSchema:
title: string — 変革の要点
subtitle: string? — 対象範囲・基準日・前提
initiative: string — 対象の施策・変更
impacts: array (3–10) — グループ別の状態変化、影響、準備、支援策
sources: []
/designs/change-impact-assessment/source/sample-data.json
{
"title": "現場の変化と移行支援をグループごとに整理する",
"subtitle": "架空の顧客管理刷新|部門ヒアリング後の計画案",
"initiative": "顧客管理刷新",
"impacts": [
{
"id": "IMP-01",
"affectedGroup": "営業担当",
"area": "process",
"currentState": "顧客情報を複数の表へ手作業で転記する",
"futureState": "新CRMへ一度入力し、関連部門と共有する",
"direction": "mixed",
"magnitude": "high",
"readiness": "support-needed",
"supportAction": "実データを使った移行リハーサルと操作演習を行う",
"owner": "営業企画"
},
{
"id": "IMP-02",
"affectedGroup": "顧客サポート",
"area": "technology",
"currentState": "問い合わせ履歴を個別のチケットで管理する",
"futureState": "顧客画面から履歴を横断して確認する",
"direction": "positive",
"magnitude": "moderate",
"readiness": "ready",
"supportAction": "検索手順の変更点を短いガイドにまとめる",
"owner": "サポート責任者"
},
{
"id": "IMP-03",
"affectedGroup": "データ管理担当",
"area": "role",
"currentState": "各部門が顧客項目を追加・修正する",
"futureState": "項目変更をデータ管理担当がレビューする",
"direction": "mixed",
"magnitude": "high",
"readiness": "unknown",
"supportAction": "判断基準と申請経路を共同で定義する",
"owner": "データ統括"
},
{
"id": "IMP-04",
"affectedGroup": "支店管理者",
"area": "skill",
"currentState": "月次の集計表をローカルで作成する",
"futureState": "権限に応じた支店レポートを画面で確認する",
"direction": "positive",
"magnitude": "low",
"readiness": "ready",
"supportAction": "既存集計表との対応関係を説明する",
"owner": "営業企画"
}
]
}