Back to index

Fit Gap Assessment

Table
Generates documents
Fit Gap Assessment

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

fit-gap-assessment-everything.md

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

Prompt

1.3 KB
Build an HTML document with "Fit Gap Assessment". This layout runs, so there is no composition to rebuild — what it needs is content.

## What this layout does
Fit Gap Assessment 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? — 出典・時点・母集団や仮定
- `requirements` — array (id, label, status, evidence, owner) — 要件ID、適合区分、検証根拠、確認責任者

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 fit-gap-assessment <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/fit-gap-assessment/source/template.tsx
- https://design-vault.pages.dev/designs/fit-gap-assessment/source/schema.ts
- https://design-vault.pages.dev/designs/fit-gap-assessment/source/sample-data.json
- https://design-vault.pages.dev/designs/fit-gap-assessment/sample.html

Files

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

template.tsx

7.1 KB

/designs/fit-gap-assessment/source/template.tsx

Show contents
import type { ReactNode } from "react";
import type { Props } from "./schema";
function Ledger({heads,rows,caption}:{heads:string[];rows:ReactNode[][];caption?:string}) { return <table className="ledger">{caption && <caption>{caption}</caption>}<thead><tr>{heads.map((h,i)=><th key={i} scope="col">{h}</th>)}</tr></thead><tbody>{rows.map((r,i)=><tr key={i}>{r.map((v,j)=><td key={j} data-label={heads[j]}>{v}</td>)}</tr>)}</tbody></table>; }
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) {
const names={fit:"標準適合",configure:"設定対応",extend:"拡張必要",unknown:"未確認"};const states=["fit","configure","extend","unknown"] as const;
return <section className="asset asset-fit-gap-assessment"><style>{CSS}</style><header><p className="eyebrow">FIT GAP ASSESSMENT</p><h1>{d.title}</h1>{d.subtitle && <p className="subtitle">{d.subtitle}</p>}</header>
<div style={{display:"grid",gridTemplateColumns:"repeat(4,minmax(0,1fr))",gap:"1rem",marginBottom:"1.5rem"}}>{states.map(s=><div key={s}><p className="small muted">{names[s]}</p><strong className="hero-number">{d.requirements.filter(r=>r.status===s).length}</strong></div>)}</div><Ledger heads={["要件","判断","根拠","責任者"]} rows={d.requirements.map(r=>[r.id+" / "+r.label,<span className="pill" key={r.id}>{names[r.status]}</span>,r.evidence,r.owner])}/><Notes><p>未確認をGapに混ぜません。業務を標準に合わせる判断と、機能拡張の判断はそれぞれ根拠を残します。</p></Notes>
<footer>評価根拠と確認責任者を省略しない。</footer></section>;
}

schema.ts

790 B

/designs/fit-gap-assessment/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();
const unique = (values: string[]) => new Set(values).size === values.length;

export const schema = z.object({
  title: text.describe("結論を伝える見出し"),
  subtitle: text.optional().describe("出典・時点・母集団や仮定"),
  requirements:z.array(z.object({id:short,label:short,status:z.enum(["fit","configure","extend","unknown"]),evidence:text,owner:short}).strict()).min(3).max(10).describe("要件ID、適合区分、検証根拠、確認責任者"),
}).strict().refine(d=>unique(d.requirements.map(r=>r.id)),"要件IDは一意");
export type Props = z.infer<typeof schema>;

meta.yaml

1.3 KB

/designs/fit-gap-assessment/source/meta.yaml

Show contents
id: fit-gap-assessment
name:
  ja: 要件のFit・Gap評価
  en: Fit Gap Assessment
purpose:
  ja: 要件ごとの標準適合・設定対応・拡張・未確認を根拠付きで整理する。
  en: Fit Gap Assessment with explicit source values and reading conditions.
status: published
still: ./still.png
category: decision
catalogOrder: 440
jobs:
  - compare-choose
useCases:
  - comparison
layoutKinds:
  - table
tags:
  - fit-gap-assessment
  - decision
  - offline
  - responsive
whenToUse:
  - ja: 要件ごとの標準適合・設定対応・拡張・未確認を根拠付きで整理する。
    en: Use to communicate fit gap assessment.
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:
  - comparison-table
  - release-readiness
dataSchema:
  title: string — 結論を伝える見出し
  subtitle: string? — 出典・時点・母集団や仮定
  requirements: array (id, label, status, evidence, owner) — 要件ID、適合区分、検証根拠、確認責任者
sources: []

sample-data.json

986 B

/designs/fit-gap-assessment/source/sample-data.json

Show contents
{
  "title": "標準適合と未確認を分けて、拡張判断を進める",
  "subtitle": "架空サンプル|レイアウトの使用例",
  "requirements": [
    {
      "id": "F1",
      "label": "申込受付",
      "status": "fit",
      "evidence": "標準デモで確認",
      "owner": "業務担当"
    },
    {
      "id": "F2",
      "label": "本人確認",
      "status": "configure",
      "evidence": "設定項目で対応を確認",
      "owner": "基盤担当"
    },
    {
      "id": "F3",
      "label": "独自帳票",
      "status": "extend",
      "evidence": "標準出力に不足",
      "owner": "開発担当"
    },
    {
      "id": "F4",
      "label": "監査出力",
      "status": "unknown",
      "evidence": "実機検証を未実施",
      "owner": "監査担当"
    },
    {
      "id": "F5",
      "label": "進捗照会",
      "status": "fit",
      "evidence": "画面操作で確認",
      "owner": "業務担当"
    }
  ]
}