@squadbase/vantage 0.6.2-dev1.05a930b → 0.6.2-dev1.0ad29b0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{build-X5NVCQKT.js → build-A23M4GCH.js} +7 -7
- package/dist/{build-X5NVCQKT.js.map → build-A23M4GCH.js.map} +1 -1
- package/dist/{check-ZBIH422T.js → check-FBHT6W6J.js} +5 -5
- package/dist/{check-ZBIH422T.js.map → check-FBHT6W6J.js.map} +1 -1
- package/dist/chunk-2IAPIOPS.js +152 -0
- package/dist/chunk-2IAPIOPS.js.map +1 -0
- package/dist/chunk-57GHR5LN.js +163 -0
- package/dist/chunk-57GHR5LN.js.map +1 -0
- package/dist/{chunk-7DZGJQ3P.js → chunk-5C2SEDPH.js} +21 -4
- package/dist/chunk-5C2SEDPH.js.map +1 -0
- package/dist/chunk-6OTTGAPO.js +44 -0
- package/dist/chunk-6OTTGAPO.js.map +1 -0
- package/dist/{chunk-V3LF7BE7.js → chunk-ANZLVSEP.js} +4 -5
- package/dist/chunk-ANZLVSEP.js.map +1 -0
- package/dist/{chunk-XQUSGIDG.js → chunk-CKWPK4RO.js} +10 -3
- package/dist/chunk-CKWPK4RO.js.map +1 -0
- package/dist/chunk-JXFCSF3K.js +673 -0
- package/dist/chunk-JXFCSF3K.js.map +1 -0
- package/dist/{chunk-IUPSBD6W.js → chunk-QOXXOFGL.js} +23 -886
- package/dist/chunk-QOXXOFGL.js.map +1 -0
- package/dist/{chunk-CEXAQQ5W.js → chunk-S5MDTHH7.js} +180 -18
- package/dist/chunk-S5MDTHH7.js.map +1 -0
- package/dist/{chunk-2ICNHUG6.js → chunk-SDJTTMLK.js} +64 -7
- package/dist/chunk-SDJTTMLK.js.map +1 -0
- package/dist/{chunk-WAMZWZJB.js → chunk-SHZM3EXB.js} +19 -8
- package/dist/chunk-SHZM3EXB.js.map +1 -0
- package/dist/{chunk-JKLLFVEU.js → chunk-UWSQUHX6.js} +4 -99
- package/dist/chunk-UWSQUHX6.js.map +1 -0
- package/dist/cli.js +6 -6
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.js +8 -2
- package/dist/client/index.js.map +1 -1
- package/dist/components/index.d.ts +11 -247
- package/dist/components/index.js +4 -1
- package/dist/delta-text-CvwBGJ95.d.ts +15 -0
- package/dist/{dev-4XEDTELV.js → dev-H4I2JL63.js} +7 -7
- package/dist/{dev-4XEDTELV.js.map → dev-H4I2JL63.js.map} +1 -1
- package/dist/doc/index.d.ts +215 -2
- package/dist/doc/index.js +307 -3
- package/dist/doc/index.js.map +1 -1
- package/dist/{doctor-5E2VEZPK.js → doctor-B2O3GJDU.js} +5 -5
- package/dist/{doctor-5E2VEZPK.js.map → doctor-B2O3GJDU.js.map} +1 -1
- package/dist/format-U0cQl069.d.ts +243 -0
- package/dist/query/index.js +2 -2
- package/dist/{routes-3SGAFDMC.js → routes-PVKNT777.js} +4 -4
- package/dist/{routes-3SGAFDMC.js.map → routes-PVKNT777.js.map} +1 -1
- package/dist/slide/index.d.ts +272 -1
- package/dist/slide/index.js +972 -2
- package/dist/slide/index.js.map +1 -1
- package/dist/table/index.js +6 -3
- package/dist/table/index.js.map +1 -1
- package/dist/{upgrade-JHXZBGQS.js → upgrade-6DT7ADRP.js} +4 -4
- package/dist/{upgrade-JHXZBGQS.js.map → upgrade-6DT7ADRP.js.map} +1 -1
- package/dist/vite/index.js +3 -3
- package/docs/en/changelog.md +2 -0
- package/docs/en/components.md +13 -2
- package/docs/en/doc/delta-text.md +40 -0
- package/docs/en/doc/doc-action-items.md +49 -0
- package/docs/en/doc/doc-callout.md +38 -0
- package/docs/en/doc/doc-data-table.md +60 -0
- package/docs/en/doc/doc-executive-summary.md +64 -0
- package/docs/en/doc/doc-figure.md +56 -0
- package/docs/en/doc/doc-key-findings.md +61 -0
- package/docs/en/doc/doc-kpi-scorecard.md +80 -0
- package/docs/en/doc/doc-notes-and-sources.md +43 -0
- package/docs/en/doc/doc-report-header.md +46 -0
- package/docs/en/pages-and-metadata.md +15 -0
- package/docs/en/parts/area-chart.md +99 -0
- package/docs/en/parts/bar-chart.md +91 -0
- package/docs/en/parts/bar-list.md +50 -0
- package/docs/en/parts/category-bar.md +37 -0
- package/docs/en/parts/chart-frame.md +39 -0
- package/docs/en/parts/delta.md +4 -3
- package/docs/en/parts/donut-chart.md +72 -0
- package/docs/en/parts/funnel-steps.md +2 -1
- package/docs/en/parts/heatmap.md +53 -0
- package/docs/en/parts/kpi-card.md +2 -1
- package/docs/en/parts/legend.md +35 -0
- package/docs/en/parts/line-chart.md +94 -0
- package/docs/en/parts/progress-circle.md +33 -0
- package/docs/en/parts/sample-data.md +39 -0
- package/docs/en/parts/scatter-chart.md +56 -0
- package/docs/en/parts/tracker.md +36 -0
- package/docs/en/parts/updated-at.md +30 -0
- package/docs/en/parts/waterfall-chart.md +56 -0
- package/docs/en/slide/slide-chart-full.md +48 -0
- package/docs/en/slide/slide-chart-insight.md +52 -0
- package/docs/en/slide/slide-columns.md +46 -0
- package/docs/en/slide/slide-comparison.md +68 -0
- package/docs/en/slide/slide-cover.md +39 -0
- package/docs/en/slide/slide-exec-summary.md +47 -0
- package/docs/en/slide/slide-heading.md +38 -0
- package/docs/en/slide/slide-kpi-grid.md +55 -0
- package/docs/en/slide/slide-kpi-hero.md +58 -0
- package/docs/en/slide/slide-next-actions.md +49 -0
- package/docs/en/slide/slide-scorecard-table.md +54 -0
- package/docs/en/slide/slide-section.md +44 -0
- package/docs/en/slide/slide-source-line.md +34 -0
- package/docs/en/ui/alert-dialog.md +42 -0
- package/docs/en/ui/avatar.md +31 -0
- package/docs/en/ui/combobox.md +74 -0
- package/docs/en/ui/drawer.md +41 -0
- package/docs/en/ui/empty.md +1 -1
- package/docs/en/ui/error-state.md +4 -3
- package/docs/en/ui/field.md +42 -0
- package/docs/en/ui/hover-card.md +21 -0
- package/docs/en/ui/kbd.md +17 -0
- package/docs/en/ui/loading.md +1 -1
- package/docs/en/ui/pagination.md +36 -0
- package/docs/en/ui/radio-group.md +21 -0
- package/docs/en/ui/toast.md +44 -0
- package/docs/en/ui/toggle-group.md +4 -3
- package/docs/index.json +857 -77
- package/docs/ja/changelog.md +2 -0
- package/docs/ja/components.md +12 -1
- package/docs/ja/doc/delta-text.md +40 -0
- package/docs/ja/doc/doc-action-items.md +49 -0
- package/docs/ja/doc/doc-callout.md +38 -0
- package/docs/ja/doc/doc-data-table.md +60 -0
- package/docs/ja/doc/doc-executive-summary.md +64 -0
- package/docs/ja/doc/doc-figure.md +56 -0
- package/docs/ja/doc/doc-key-findings.md +61 -0
- package/docs/ja/doc/doc-kpi-scorecard.md +80 -0
- package/docs/ja/doc/doc-notes-and-sources.md +43 -0
- package/docs/ja/doc/doc-report-header.md +46 -0
- package/docs/ja/page-types/slide.md +1 -0
- package/docs/ja/pages-and-metadata.md +15 -0
- package/docs/ja/parts/area-chart.md +49 -25
- package/docs/ja/parts/bar-chart.md +50 -24
- package/docs/ja/parts/bar-list.md +31 -8
- package/docs/ja/parts/chart-frame.md +36 -0
- package/docs/ja/parts/delta.md +5 -4
- package/docs/ja/parts/donut-chart.md +45 -26
- package/docs/ja/parts/funnel-steps.md +27 -8
- package/docs/ja/parts/heatmap.md +45 -0
- package/docs/ja/parts/kpi-card.md +2 -1
- package/docs/ja/parts/legend.md +36 -0
- package/docs/ja/parts/line-chart.md +48 -22
- package/docs/ja/parts/sample-data.md +61 -0
- package/docs/ja/parts/scatter-chart.md +69 -0
- package/docs/ja/parts/updated-at.md +27 -0
- package/docs/ja/parts/waterfall-chart.md +61 -0
- package/docs/ja/slide/slide-chart-full.md +48 -0
- package/docs/ja/slide/slide-chart-insight.md +52 -0
- package/docs/ja/slide/slide-columns.md +46 -0
- package/docs/ja/slide/slide-comparison.md +68 -0
- package/docs/ja/slide/slide-cover.md +39 -0
- package/docs/ja/slide/slide-exec-summary.md +47 -0
- package/docs/ja/slide/slide-heading.md +38 -0
- package/docs/ja/slide/slide-kpi-grid.md +55 -0
- package/docs/ja/slide/slide-kpi-hero.md +58 -0
- package/docs/ja/slide/slide-next-actions.md +49 -0
- package/docs/ja/slide/slide-scorecard-table.md +54 -0
- package/docs/ja/slide/slide-section.md +44 -0
- package/docs/ja/slide/slide-source-line.md +34 -0
- package/docs/ja/ui/empty.md +1 -1
- package/docs/ja/ui/error-state.md +4 -3
- package/docs/ja/ui/loading.md +1 -1
- package/docs/ja/ui/toggle-group.md +4 -3
- package/package.json +2 -2
- package/registry/ui/delta.tsx +7 -4
- package/registry/ui/echart.tsx +123 -1
- package/registry/ui/kpi-card.tsx +9 -4
- package/skills/vantage-design/SKILL.md +27 -25
- package/skills/vantage-design/references/extract.md +16 -14
- package/skills/vantage-design/references/format.md +6 -5
- package/skills/vantage-design/references/presets.md +60 -110
- package/skills/vantage-pitfalls/SKILL.md +5 -0
- package/skills/vantage-slide/SKILL.md +54 -36
- package/templates/AGENTS.md +4 -2
- package/templates/agents/doc.md +48 -0
- package/templates/agents/page.md +22 -1
- package/templates/agents/slide.md +70 -2
- package/theme.css +10 -7
- package/dist/chunk-2ICNHUG6.js.map +0 -1
- package/dist/chunk-7DZGJQ3P.js.map +0 -1
- package/dist/chunk-CEXAQQ5W.js.map +0 -1
- package/dist/chunk-IUPSBD6W.js.map +0 -1
- package/dist/chunk-JKLLFVEU.js.map +0 -1
- package/dist/chunk-V3LF7BE7.js.map +0 -1
- package/dist/chunk-WAMZWZJB.js.map +0 -1
- package/dist/chunk-XQUSGIDG.js.map +0 -1
package/registry/ui/echart.tsx
CHANGED
|
@@ -691,6 +691,116 @@ export function echartSetOptionOpts(prev: EChartsOption | null, next: EChartsOpt
|
|
|
691
691
|
return { notMerge: false, replaceMerge: [...types], lazyUpdate: true }
|
|
692
692
|
}
|
|
693
693
|
|
|
694
|
+
/**
|
|
695
|
+
* Component types that get a generated `id` when the option has none, so replaceMerge can match them across updates.
|
|
696
|
+
* Not `dataset` / `graphic` / `tooltip`: they are rebuilt on every update (there is nothing to transition).
|
|
697
|
+
*/
|
|
698
|
+
const ID_TYPES = [
|
|
699
|
+
"title", "legend", "grid", "xAxis", "yAxis", "polar", "radiusAxis", "angleAxis", "radar",
|
|
700
|
+
"dataZoom", "visualMap", "geo", "singleAxis", "calendar",
|
|
701
|
+
] as const
|
|
702
|
+
|
|
703
|
+
/**
|
|
704
|
+
* What `withStableIds` remembers between updates: per generated id, the shape last applied and how many
|
|
705
|
+
* times it changed (the id's `~v<n>` suffix); per component type, the order of its ids.
|
|
706
|
+
*/
|
|
707
|
+
export interface StableIdState {
|
|
708
|
+
ids: Map<string, { shape: string; version: number }>
|
|
709
|
+
order: Map<string, string[]>
|
|
710
|
+
}
|
|
711
|
+
export const createStableIdState = (): StableIdState => ({ ids: new Map(), order: new Map() })
|
|
712
|
+
|
|
713
|
+
/**
|
|
714
|
+
* Shape of a component: which keys it has, recursively (arrays only as "array", values not at all —
|
|
715
|
+
* except `type`). A merge keeps keys the new option dropped, so a changed shape must not be merged.
|
|
716
|
+
*/
|
|
717
|
+
function shapeOf(v: unknown): string {
|
|
718
|
+
if (Array.isArray(v)) return "[]"
|
|
719
|
+
if (!v || typeof v !== "object" || Object.getPrototypeOf(v) !== Object.prototype) return "."
|
|
720
|
+
const o = v as Record<string, unknown>
|
|
721
|
+
return `{${Object.keys(o)
|
|
722
|
+
.filter((k) => o[k] !== undefined)
|
|
723
|
+
.sort()
|
|
724
|
+
.map((k) => (k === "type" || k === "id" ? `${k}=${String(o[k])}` : `${k}:${shapeOf(o[k])}`))
|
|
725
|
+
.join(",")}}`
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
/**
|
|
729
|
+
* Gives every series (and the common components) an `id` it does not have yet —
|
|
730
|
+
* series: `series:<name ?? index>`, others `<type>:<index>` — so an update that
|
|
731
|
+
* only changes values is matched to the existing component and transitions
|
|
732
|
+
* instead of being rebuilt. If the component's shape changed since `state` last
|
|
733
|
+
* saw it (a key was removed or added, the type changed), the id gets a new
|
|
734
|
+
* `~v<n>` suffix so replaceMerge builds it from scratch: the result then always
|
|
735
|
+
* equals applying the option with `notMerge`. Explicit ids are kept; the input is not mutated.
|
|
736
|
+
*/
|
|
737
|
+
export function withStableIds(option: EChartsOption, state: StableIdState = createStableIdState()): EChartsOption {
|
|
738
|
+
const out: Record<string, unknown> = { ...(option as Record<string, unknown>) }
|
|
739
|
+
const taken = new Set<string>()
|
|
740
|
+
const list = (v: unknown): Record<string, unknown>[] | null =>
|
|
741
|
+
Array.isArray(v) ? (v as Record<string, unknown>[]) : v && typeof v === "object" ? [v as Record<string, unknown>] : null
|
|
742
|
+
const give = (key: string, pick: (c: Record<string, unknown>, i: number) => string) => {
|
|
743
|
+
const items = list(out[key])
|
|
744
|
+
if (!items) return
|
|
745
|
+
const used = new Set<string>(items.flatMap((c) => (c && c.id != null ? [String(c.id)] : [])))
|
|
746
|
+
const bases = items.map((c, i) => {
|
|
747
|
+
if (!c || typeof c !== "object" || c.id != null) return null
|
|
748
|
+
let base = pick(c, i)
|
|
749
|
+
for (let n = 2; used.has(base) || taken.has(`${key}\u0000${base}`); n++) base = `${pick(c, i)}#${n}`
|
|
750
|
+
used.add(base)
|
|
751
|
+
taken.add(`${key}\u0000${base}`)
|
|
752
|
+
return base
|
|
753
|
+
})
|
|
754
|
+
// A merge fills the empty slots a removal left and keeps the slot order of what exists, so after any
|
|
755
|
+
// change in which components there are (or their order) it would not match a fresh render: rebuild them all.
|
|
756
|
+
const prevOrder = state.order.get(key) ?? []
|
|
757
|
+
const cur = bases.filter((b): b is string => b !== null)
|
|
758
|
+
const inOrder = cur.length === prevOrder.length && cur.every((b, i) => b === prevOrder[i])
|
|
759
|
+
state.order.set(key, cur)
|
|
760
|
+
out[key] = items.map((c, i) => {
|
|
761
|
+
const base = bases[i]
|
|
762
|
+
if (base == null) return c
|
|
763
|
+
const shape = shapeOf(c)
|
|
764
|
+
const prev = state.ids.get(base)
|
|
765
|
+
const version = !prev ? 0 : prev.shape === shape && inOrder ? prev.version : prev.version + 1
|
|
766
|
+
state.ids.set(base, { shape, version })
|
|
767
|
+
return { ...c, id: version ? `${base}~v${version}` : base }
|
|
768
|
+
})
|
|
769
|
+
}
|
|
770
|
+
give("series", (c, i) => `series:${typeof c.name === "string" && c.name ? c.name : i}`)
|
|
771
|
+
for (const key of ID_TYPES) give(key, (_c, i) => `${key}:${i}`)
|
|
772
|
+
return out as EChartsOption
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
/** Copy of the plain objects / arrays of an option (functions, class instances, Dates stay shared), to compare against later in-place edits. */
|
|
776
|
+
export function snapshotOption<T>(v: T): T {
|
|
777
|
+
if (Array.isArray(v)) return v.map(snapshotOption) as T
|
|
778
|
+
if (v && typeof v === "object") {
|
|
779
|
+
const proto = Object.getPrototypeOf(v)
|
|
780
|
+
if (proto === Object.prototype || proto === null) {
|
|
781
|
+
return Object.fromEntries(Object.entries(v).map(([k, x]) => [k, snapshotOption(x)])) as T
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
return v
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
/** Structural equality for option trees; functions and other non-plain objects compare by reference. */
|
|
788
|
+
export function optionEquals(a: unknown, b: unknown): boolean {
|
|
789
|
+
if (Object.is(a, b)) return true
|
|
790
|
+
if (typeof a !== "object" || typeof b !== "object" || !a || !b) return false
|
|
791
|
+
if (Array.isArray(a) !== Array.isArray(b)) return false
|
|
792
|
+
if (Array.isArray(a)) {
|
|
793
|
+
const bb = b as unknown[]
|
|
794
|
+
return a.length === bb.length && a.every((v, i) => optionEquals(v, bb[i]))
|
|
795
|
+
}
|
|
796
|
+
if (a instanceof Date || b instanceof Date) return a instanceof Date && b instanceof Date && a.getTime() === b.getTime()
|
|
797
|
+
const pa = Object.getPrototypeOf(a)
|
|
798
|
+
if ((pa !== Object.prototype && pa !== null) || Object.getPrototypeOf(b) !== pa) return false
|
|
799
|
+
const ka = Object.keys(a)
|
|
800
|
+
const kb = Object.keys(b)
|
|
801
|
+
return ka.length === kb.length && ka.every((k) => Object.hasOwn(b, k) && optionEquals((a as Record<string, unknown>)[k], (b as Record<string, unknown>)[k]))
|
|
802
|
+
}
|
|
803
|
+
|
|
694
804
|
/** `graphic` text doesn't inherit the global `textStyle`, so give it the inherited font unless it sets its own. */
|
|
695
805
|
function withGraphicFont(option: EChartsOption, fontFamily: string | undefined): EChartsOption {
|
|
696
806
|
const graphic = (option as { graphic?: unknown }).graphic
|
|
@@ -748,6 +858,9 @@ export const EChart = forwardRef<HTMLDivElement, EChartProps>(function EChart(
|
|
|
748
858
|
const reducedMotion = usePrefersReducedMotion()
|
|
749
859
|
// What the current instance last received, to pick the merge mode of the next update.
|
|
750
860
|
const appliedRef = useRef<EChartsOption | null>(null)
|
|
861
|
+
// The option (before ids) as it was when applied, deep-copied; and the shape history behind the generated ids.
|
|
862
|
+
const snapshotRef = useRef<EChartsOption | null>(null)
|
|
863
|
+
const idStateRef = useRef<StableIdState>(createStableIdState())
|
|
751
864
|
|
|
752
865
|
const autoTheme = useMemo(() => (tokens ? buildChartTheme(tokens) : undefined), [tokens])
|
|
753
866
|
const resolvedTheme = theme ?? autoTheme
|
|
@@ -759,6 +872,7 @@ export const EChart = forwardRef<HTMLDivElement, EChartProps>(function EChart(
|
|
|
759
872
|
if (!container) return
|
|
760
873
|
const inst = init(container, resolvedTheme, { renderer: "canvas" })
|
|
761
874
|
appliedRef.current = null
|
|
875
|
+
snapshotRef.current = null
|
|
762
876
|
// `data-rendering` stays on until the (animated) paint is done, so anything
|
|
763
877
|
// capturing the page — printing a document — can wait for real pixels.
|
|
764
878
|
container.dataset.rendering = ""
|
|
@@ -786,10 +900,18 @@ export const EChart = forwardRef<HTMLDivElement, EChartProps>(function EChart(
|
|
|
786
900
|
|
|
787
901
|
useEffect(() => {
|
|
788
902
|
if (!instance || instance.isDisposed()) return
|
|
903
|
+
const prepared = withGraphicFont(
|
|
904
|
+
withMotionPreference(option, reducedMotion),
|
|
905
|
+
theme === undefined ? tokens?.fontFamily : undefined,
|
|
906
|
+
)
|
|
907
|
+
// Same content as last time (a re-render that built an equal option): nothing to redraw.
|
|
908
|
+
// Compared with a snapshot, so an in-place edit of a nested array of the caller's option still counts as a change.
|
|
909
|
+
if (snapshotRef.current && optionEquals(snapshotRef.current, prepared)) return
|
|
789
910
|
if (containerRef.current) containerRef.current.dataset.rendering = ""
|
|
790
|
-
const next =
|
|
911
|
+
const next = withStableIds(prepared, idStateRef.current)
|
|
791
912
|
instance.setOption(next, echartSetOptionOpts(appliedRef.current, next))
|
|
792
913
|
appliedRef.current = next
|
|
914
|
+
snapshotRef.current = snapshotOption(prepared)
|
|
793
915
|
}, [instance, option, reducedMotion, theme, tokens?.fontFamily])
|
|
794
916
|
|
|
795
917
|
useEffect(() => {
|
package/registry/ui/kpi-card.tsx
CHANGED
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
* line takes its name from it ("昨日 617"), the same way a `label` on any `vs` does.
|
|
44
44
|
* - **Two or more comparisons sit under the value**, not beside it, so the value
|
|
45
45
|
* keeps its place and its width whatever the card holds.
|
|
46
|
-
* -
|
|
46
|
+
* - **`betterWhen` drives everything.** With `betterWhen="down"` the target
|
|
47
47
|
* is met at or below it, and the record badge marks the lowest value.
|
|
48
48
|
* - **Rates change in points.** With a `percent` format the delta and
|
|
49
49
|
* `{difference}` are in percentage points ("-0.5pt"); `change="relative"` opts
|
|
@@ -147,7 +147,9 @@ export interface KpiCardProps extends Omit<ComponentProps<"div">, "children"> {
|
|
|
147
147
|
* @example provisional / provisional={{ label: "暫定" }}
|
|
148
148
|
*/
|
|
149
149
|
provisional?: boolean | { label?: string }
|
|
150
|
-
/**
|
|
150
|
+
/** Which direction is good: `"up"` (default) or `"down"` (churn, error rate). Wins over `polarity`. */
|
|
151
|
+
betterWhen?: "up" | "down"
|
|
152
|
+
/** @deprecated Older name of `betterWhen` (`"higher-is-better"` / `"lower-is-better"`). `"neutral"` (never colours the change, skips the target and record logic) is only reachable here. `betterWhen` wins if both are given. */
|
|
151
153
|
polarity?: Polarity
|
|
152
154
|
/** `"relative"` ("+12.4%"), `"points"` ("-0.5pt") or `"difference"` ("+¥530万", in `format`). Default: points for a `percent` format, else relative. */
|
|
153
155
|
change?: ChangeDisplay
|
|
@@ -160,7 +162,7 @@ export interface KpiCardProps extends Omit<ComponentProps<"div">, "children"> {
|
|
|
160
162
|
/**
|
|
161
163
|
* Target for the current period. Under the value it adds a 6px bar (actual, the pace
|
|
162
164
|
* projection, a tick at the target) and one line "目標の 49%・このペースなら 98%"
|
|
163
|
-
* (the projection only while `period` is in progress). With `
|
|
165
|
+
* (the projection only while `period` is in progress). With `betterWhen="down"`
|
|
164
166
|
* or a rate target (points) there is no bar: "目標 … まであと …" in the footer.
|
|
165
167
|
*/
|
|
166
168
|
target?: number
|
|
@@ -325,7 +327,8 @@ export function KpiCard({
|
|
|
325
327
|
comparison: comparisonProp,
|
|
326
328
|
comparisons,
|
|
327
329
|
provisional,
|
|
328
|
-
|
|
330
|
+
betterWhen,
|
|
331
|
+
polarity: polarityProp,
|
|
329
332
|
change,
|
|
330
333
|
neutralBand,
|
|
331
334
|
showPrevious = true,
|
|
@@ -352,6 +355,8 @@ export function KpiCard({
|
|
|
352
355
|
const isProvisional = provisional !== undefined && provisional !== false
|
|
353
356
|
const provisionalLabel = typeof provisional === "object" && provisional.label ? provisional.label : "速報"
|
|
354
357
|
const sample = useSampleMark()
|
|
358
|
+
// `betterWhen` is the documented name and wins over the older `polarity`.
|
|
359
|
+
const polarity: Polarity | undefined = betterWhen ? (betterWhen === "down" ? "lower-is-better" : "higher-is-better") : polarityProp
|
|
355
360
|
const neutral = polarity === "neutral"
|
|
356
361
|
const hasPrevious = comparison !== undefined && showPrevious
|
|
357
362
|
// Two or more badges would squeeze the value from the right; they get their own row under it instead.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: vantage-design
|
|
3
|
-
description: Vantage(@squadbase/vantage)アプリの見た目の意図 `DESIGN.md` と、実際の値を持つ `styles.css` をまとめて作る / 更新する手順。配色・ブランドカラー・テーマ・チャートの色・フォント・角丸・トーンを変えたいとき、既存サイトやロゴ・資料・外部の DESIGN.md に合わせたいとき、プロジェクト作成時の初期デザイン(
|
|
3
|
+
description: Vantage(@squadbase/vantage)アプリの見た目の意図 `DESIGN.md` と、実際の値を持つ `styles.css` をまとめて作る / 更新する手順。配色・ブランドカラー・テーマ・チャートの色・フォント・角丸・トーンを変えたいとき、既存サイトやロゴ・資料・外部の DESIGN.md に合わせたいとき、プロジェクト作成時の初期デザイン(テーマ neutral / ocean / forest / sunset / violet / rose / mono)を決めるときに使う。「色を変えて」「ブランドに合わせて」「このサイトに合わせて」「落ち着いた感じに」「フォントを変えて」「テーマを作って」「DESIGN.md を作って」、"change the colors", "match our brand", "match this website", "theme", "color palette", "font", "design system", "DESIGN.md" で起動。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# DESIGN.md と styles.css をまとめて更新する
|
|
@@ -23,7 +23,7 @@ Vantage アプリの見た目は 2 つのファイルで決まる。
|
|
|
23
23
|
| --- | --- |
|
|
24
24
|
| `references/format.md` | `DESIGN.md` を書く / 直すとき(書式・節の順番・雛形) |
|
|
25
25
|
| `references/extract.md` | URL・画像・pptx/pdf・言葉・外部 DESIGN.md から色と書体を取り出すとき |
|
|
26
|
-
| `references/presets.md` |
|
|
26
|
+
| `references/presets.md` | テーマ(`neutral` / `ocean` / `forest` / `sunset` / `violet` / `rose` / `mono`)の選び方と `theme` コマンド。旧プリセット id の読み替え |
|
|
27
27
|
| `scripts/contrast.mjs` | 文字色と背景色のコントラスト比を確かめるとき |
|
|
28
28
|
|
|
29
29
|
## 手順
|
|
@@ -43,29 +43,32 @@ Vantage アプリの見た目は 2 つのファイルで決まる。
|
|
|
43
43
|
各行に「何に合わせてその色にしたか」を 1 語添える。
|
|
44
44
|
- **トーンの説明**(2〜3 行。`DESIGN.md` の「全体のトーン」にそのまま入る文)。
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
テーマで足りる場合はテーマ id(`references/presets.md`)で提案してよい。旧プリセット id(`default` / `calm` / `vivid` / `mono`)で頼まれたら新 id に読み替える。
|
|
47
47
|
|
|
48
48
|
### 3. styles.css と DESIGN.md を同じステップで書く
|
|
49
49
|
|
|
50
50
|
`styles.css`:
|
|
51
51
|
|
|
52
|
-
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
(`
|
|
58
|
-
|
|
59
|
-
-
|
|
52
|
+
- **テーマ範囲・チャート範囲のマーカーの中は手で編集しない。** 色・角丸・書体の出発点は 7 テーマ
|
|
53
|
+
(`neutral` / `ocean` / `forest` / `sunset` / `violet` / `rose` / `mono`)から選び、コマンドで当てる:
|
|
54
|
+
`npx @squadbase/vantage-template theme <id>`(プロジェクトルートで実行。`--dry-run` で書き込まずに
|
|
55
|
+
結果を見られる)。``/* squadkit-theme — regenerated by `theme`; edits here are lost */`` 〜
|
|
56
|
+
`/* squadkit-theme:end */` の間はコマンドが丸ごと書き換える生成物で、手で直した値は次の適用で消える。
|
|
57
|
+
旧プリセット id(`default` → `neutral` / `calm` → `ocean` / `vivid` → `sunset` / `mono`)もコマンドが受ける。
|
|
58
|
+
- チャートの 5 色はテーマが持つ。テーマと別の配色にしたいときだけ
|
|
59
|
+
`npx @squadbase/vantage-template chart <preset>`(`blue` / `ocean` / `sunset` / `forest` / `berry` / `mono`)を使う。
|
|
60
|
+
``/* vantage-template:chart-preset … */`` 〜 `/* vantage-template:chart-preset:end */` の間が置き換わり、
|
|
61
|
+
テーマのチャート色より優先される。テーマに揃え直すには `theme <id> --reset-chart`。
|
|
62
|
+
- プリセットに無いチャート色(ブランド色を `--chart-1` にしたいなど)は、**マーカーブロックの後ろ**に
|
|
60
63
|
別の `:root { --chart-1: …; }` と `.dark, [data-theme="dark"] { --chart-1: …; }` を足して上書きする
|
|
61
|
-
(後に書いた方が勝つ)
|
|
62
|
-
- `--primary` / `--primary-foreground` / `--radius`
|
|
63
|
-
(
|
|
64
|
-
|
|
65
|
-
(`var(--color-sky-600)`)で書く。
|
|
66
|
-
-
|
|
67
|
-
(
|
|
68
|
-
|
|
64
|
+
(後に書いた方が勝つ)。上書きするのは変えたい番号だけにし、残りはテーマに任せる。
|
|
65
|
+
- `--primary` / `--primary-foreground` / `--radius` などテーマに無い値・ブランド色の上書きも、
|
|
66
|
+
**マーカーブロックの後ろ**(ファイル末尾)に書く。マーカーより前に書いた値はテーマに負ける。
|
|
67
|
+
色は `:root` と `.dark, [data-theme="dark"]` の**両方**に書く。片方だけだとダークモードでテーマの値に
|
|
68
|
+
戻る。値は `oklch()` か Tailwind のパレット変数(`var(--color-sky-600)`)で書く。
|
|
69
|
+
- 書体は既定でシステムフォント。**ページの書体は `--font-sans`**(`styles.css` の `body` が
|
|
70
|
+
`font-family: var(--font-sans)` で参照する。テーマ範囲も `--font-sans` を持つので、書体を変えるには
|
|
71
|
+
マーカーブロックの後ろで `:root { --font-sans: …; }` を上書きする)。スライドの書体は `:root` の
|
|
69
72
|
`--slide-font-display`(見出し)/ `--slide-font-body`(本文)で決まる。Web フォントを使うときの
|
|
70
73
|
レシピ:
|
|
71
74
|
1. Google Fonts の CSS
|
|
@@ -73,13 +76,11 @@ Vantage アプリの見た目は 2 つのファイルで決まる。
|
|
|
73
76
|
から使う subset の `@font-face` ブロックだけを `styles.css` の先頭に貼る。
|
|
74
77
|
**`@import url(...)` は使わない** ― `styles.css` はテーマの後ろに連結されるので
|
|
75
78
|
「@import rules must precede all rules」の警告とともにビルドで捨てられる。
|
|
76
|
-
2.
|
|
79
|
+
2. マーカーブロックの後ろに次を書く(フォールバックは `theme.css` の既定と同じ並び):
|
|
77
80
|
|
|
78
81
|
```css
|
|
79
|
-
body {
|
|
80
|
-
font-family: "<Font>", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Hiragino Sans", "Hiragino Kaku Gothic ProN", "Noto Sans JP", Meiryo, ui-sans-serif, system-ui, sans-serif;
|
|
81
|
-
}
|
|
82
82
|
:root {
|
|
83
|
+
--font-sans: "<Font>", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Hiragino Sans", "Hiragino Kaku Gothic ProN", "Noto Sans JP", Meiryo, ui-sans-serif, system-ui, sans-serif;
|
|
83
84
|
--slide-font-display: "<Font>", -apple-system, BlinkMacSystemFont, "Segoe UI", "Hiragino Kaku Gothic ProN", "Hiragino Sans", "Yu Gothic", Meiryo, system-ui, sans-serif;
|
|
84
85
|
--slide-font-body: var(--slide-font-display);
|
|
85
86
|
}
|
|
@@ -90,8 +91,9 @@ Vantage アプリの見た目は 2 つのファイルで決まる。
|
|
|
90
91
|
`ui-sans-serif` / `system-ui` は日本語の face より**後ろ**に置く。日本語の Windows ではどちらも
|
|
91
92
|
Yu Gothic UI(UI のリサイズを避けるために字幅を詰めた書体)に解決され、カナがここで決まって
|
|
92
93
|
半角風に見える。macOS の Chrome は `-apple-system` を解釈しないので `BlinkMacSystemFont` も並べる。
|
|
93
|
-
既存アプリの `styles.css` に `
|
|
94
|
-
|
|
94
|
+
既存アプリの `styles.css` の `body` に `font-family` が直書きされている(`var(--font-sans)` ではない)、
|
|
95
|
+
または `ui-sans-serif, system-ui, …` が先頭にある、`"Yu Gothic UI"` が残っているときは、
|
|
96
|
+
`body { font-family: var(--font-sans); }` に直し、書体は `--font-sans` に上の並びで書く。
|
|
95
97
|
日本語の Web フォントは face が 100 を超えるので原則使わない(pptx 書き出しも壊れる。
|
|
96
98
|
`vantage-slide` の `references/tokens.md` 参照)。
|
|
97
99
|
|
|
@@ -7,12 +7,13 @@
|
|
|
7
7
|
3. **書体**(見出しと本文の `font-family`。システムフォントで足りるか)
|
|
8
8
|
4. **トーン**(2〜3 語: 「落ち着いた」「明るい」「堅い」…)
|
|
9
9
|
|
|
10
|
-
チャートの 5
|
|
11
|
-
`npx @squadbase/vantage-template
|
|
12
|
-
配慮が済んでいる)
|
|
10
|
+
チャートの 5 色は、主色から直接作るより**主色に最も近いテーマ**を選び、
|
|
11
|
+
`npx @squadbase/vantage-template theme <id>` で適用する方が安全(5 色の明度差・色覚多様性への
|
|
12
|
+
配慮が済んでいる)。テーマと別のチャート配色が要るときは `chart <preset>`。`styles.css` の
|
|
13
|
+
`squadkit-theme` / `vantage-template:chart-preset` のマーカーブロックの中は
|
|
13
14
|
**手で編集しない**(次の適用で消える)。主色を `--chart-1` に入れたいときだけ、マーカーブロックの
|
|
14
15
|
**後ろ**に `:root` と `.dark, [data-theme="dark"]` の `--chart-1` 上書きを足し、残り 4 色は
|
|
15
|
-
プリセットに任せる。`--primary` や `--radius`
|
|
16
|
+
プリセットに任せる。`--primary` や `--radius` はマーカーブロックの後ろに書く。
|
|
16
17
|
|
|
17
18
|
## URL(既存サイトに合わせる)
|
|
18
19
|
|
|
@@ -36,7 +37,7 @@ grep -oE 'font-family:[^;]+' /tmp/site.css | sort | uniq -c | sort -rn | head
|
|
|
36
37
|
3. **ボタン・リンクの色**: `a {` `.btn` `button` `[class*=primary]` のセレクタの `color` /
|
|
37
38
|
`background-color`。出現回数の多い有彩色が主色。
|
|
38
39
|
4. **背景**: `body` / `html` の `background`。暗ければ「暗い基調」。
|
|
39
|
-
5. **書体**: `body` の `font-family
|
|
40
|
+
5. **書体**: `body` の `font-family`(書き込み先は `--font-sans`)。Google Fonts の `<link>` があればその family 名。
|
|
40
41
|
|
|
41
42
|
注意:
|
|
42
43
|
|
|
@@ -66,18 +67,19 @@ grep -oE 'font-family:[^;]+' /tmp/site.css | sort | uniq -c | sort -rn | head
|
|
|
66
67
|
|
|
67
68
|
## 言葉だけ(「落ち着いた感じに」)
|
|
68
69
|
|
|
69
|
-
形容詞を `presets.md` の
|
|
70
|
+
形容詞を `presets.md` の 7 テーマに寄せ、そのうえで主色だけを調整する。
|
|
70
71
|
|
|
71
72
|
| 言われたこと | 出発点 |
|
|
72
73
|
| --- | --- |
|
|
73
|
-
| 落ち着いた・信頼感・堅い・経営向け・青系 | `
|
|
74
|
-
| 明るい・元気・勢い・暖かい・営業向け | `
|
|
74
|
+
| 落ち着いた・信頼感・堅い・経営向け・青系 | `ocean` |
|
|
75
|
+
| 明るい・元気・勢い・暖かい・営業向け | `sunset` |
|
|
75
76
|
| シンプル・モノクロ・印刷する・資料に貼る | `mono` |
|
|
76
|
-
| 特に無し・標準・おまかせ | `
|
|
77
|
-
| 自然・環境・緑 | `
|
|
78
|
-
|
|
|
77
|
+
| 特に無し・標準・おまかせ | `neutral` |
|
|
78
|
+
| 自然・環境・緑 | `forest` |
|
|
79
|
+
| 華やか・ポップ・紫 | `violet` |
|
|
80
|
+
| 華やか・ポップ・ピンク | `rose` |
|
|
79
81
|
|
|
80
|
-
当てはまらない言葉は、2 案(例: `
|
|
82
|
+
当てはまらない言葉は、2 案(例: `ocean` と `neutral`)を並べて選んでもらう。
|
|
81
83
|
|
|
82
84
|
## 外部の DESIGN.md(Stitch などが書いたもの)
|
|
83
85
|
|
|
@@ -99,8 +101,8 @@ Vantage の `DESIGN.md` は値を持たないので、**値を `styles.css` へ
|
|
|
99
101
|
| error | `--destructive` |
|
|
100
102
|
| success / warning | 専用トークンなし → `--chart-*` のどれかに割り当てて `DESIGN.md` に書く |
|
|
101
103
|
| radius / corner | `--radius` |
|
|
102
|
-
| display / headline font | `--slide-font-display`(+ ページの見出しなら
|
|
103
|
-
| body font |
|
|
104
|
+
| display / headline font | `--slide-font-display`(+ ページの見出しなら `--font-sans`) |
|
|
105
|
+
| body font | `--font-sans`(ページ本文)と `--slide-font-body` |
|
|
104
106
|
|
|
105
107
|
3. `styles.css` のマーカーブロックの外に、`:root` と `.dark, [data-theme="dark"]` の両方で書く
|
|
106
108
|
(チャート色・書体の書き方は SKILL.md の手順 3)。外部の DESIGN.md に
|
|
@@ -50,8 +50,8 @@ Components → 「成果物の種類ごとの規則」/ Do's and Don'ts。値は
|
|
|
50
50
|
|
|
51
51
|
- `--muted` `--accent` `--secondary` `--border` は背景・境界用。文字色の役割に割り当てない。
|
|
52
52
|
- 良い / 注意の専用トークンは無い。`--chart-*` の中から割り当てるか、「専用トークンなし」と書く。
|
|
53
|
-
-
|
|
54
|
-
|
|
53
|
+
- ページ本文の書体は `--font-sans`(`styles.css` の `body` が `font-family: var(--font-sans)` で参照する。
|
|
54
|
+
テーマを当てると `--font-sans` もテーマの値になる。変えるときはテーマ範囲のマーカーの後ろで上書きする)。
|
|
55
55
|
- `--slide-bg` などは既定で `--background` などの別名。`.dark` に書き直す必要は無い。
|
|
56
56
|
|
|
57
57
|
## 雛形(中立の既定テーマ)
|
|
@@ -112,14 +112,15 @@ DESIGN.md — このアプリの「見た目の意図」を書くファイルで
|
|
|
112
112
|
- 系列は 5 つまで。それ以上はグループ化するか「その他」にまとめる。
|
|
113
113
|
- 禁止: 同じチャートで `--destructive` を普通の系列色として使う(悪い値に見える)。
|
|
114
114
|
- 禁止: 隣り合う系列に `--chart-3` と `--chart-4` を並べて細い線で描く(見分けにくい)。
|
|
115
|
-
- 配色を丸ごと変えるときは `npx @squadbase/vantage-template
|
|
116
|
-
(`
|
|
115
|
+
- 配色を丸ごと変えるときは `npx @squadbase/vantage-template theme <id>` を使う
|
|
116
|
+
(`neutral` / `ocean` / `forest` / `sunset` / `violet` / `rose` / `mono`)。チャートだけ別の配色にするときは
|
|
117
|
+
`chart <preset>`(`blue` / `ocean` / `sunset` / `forest` / `berry` / `mono`)。
|
|
117
118
|
|
|
118
119
|
## 書体 (Typography)
|
|
119
120
|
|
|
120
121
|
| 用途 | 指定 | 備考 |
|
|
121
122
|
| --- | --- | --- |
|
|
122
|
-
| 見出し・本文 | 日本語を含むシステムフォント(
|
|
123
|
+
| 見出し・本文 | 日本語を含むシステムフォント(`--font-sans`) | Web フォントは使わない |
|
|
123
124
|
| 数字 | 同上 + `tabular-nums` | 桁がそろうように必ず付ける |
|
|
124
125
|
| スライドの見出し | `--slide-font-display` | 既定は日本語を含むシステムフォント |
|
|
125
126
|
| スライドの本文 | `--slide-font-body` | 既定は見出しと同じ |
|
|
@@ -1,110 +1,60 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
-
|
|
49
|
-
|
|
50
|
-
- `--primary`
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
- `DESIGN.md` の差分: 「全体のトーン」を上の文に。チャートの色味を「スカイ → シアン → インディゴ →
|
|
65
|
-
ティール → スレート」に。良い = `--chart-4`(ティール)。1 系列の強調は `--chart-1` + 残り `--chart-5`。
|
|
66
|
-
禁止: `--chart-1` と `--chart-2` を隣り合う細い線で並べる(どちらも明るい青系)。
|
|
67
|
-
|
|
68
|
-
## `vivid`
|
|
69
|
-
|
|
70
|
-
- トーン: 明るく勢いのある暖色。KPI とトレンドを大きく見せ、強調色をはっきり使う。
|
|
71
|
-
- チャート: `sunset`(オレンジ → アンバー → ローズ → イエロー → ストーン)。
|
|
72
|
-
- `--primary`(オレンジ 600 は白文字で 4.5:1 に届かないので 700 を使う):
|
|
73
|
-
|
|
74
|
-
```css
|
|
75
|
-
:root {
|
|
76
|
-
--primary: var(--color-orange-700);
|
|
77
|
-
--primary-foreground: oklch(0.985 0 0);
|
|
78
|
-
}
|
|
79
|
-
.dark,
|
|
80
|
-
[data-theme="dark"] {
|
|
81
|
-
--primary: var(--color-orange-400);
|
|
82
|
-
--primary-foreground: oklch(0.205 0 0);
|
|
83
|
-
}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
- `DESIGN.md` の差分: トーンを上の文に。主色の行を「濃いオレンジ」に。良い = 専用色なし(▲ と
|
|
87
|
-
`--foreground`)、悪い = `--destructive`。禁止: `--chart-3`(ローズ)と `--destructive` を同じ
|
|
88
|
-
チャートに置く(悪い値と区別できない)。1 系列の強調は `--chart-1` + 残り `--chart-5`。
|
|
89
|
-
|
|
90
|
-
## `mono`
|
|
91
|
-
|
|
92
|
-
- トーン: 白黒と灰色だけ。色で意味を運ばず、太さ・順番・ラベルで読ませる。
|
|
93
|
-
- チャート: `mono`(ジンク 900 → 200。ダークでは反転)。
|
|
94
|
-
- `--primary`(チャートの両端と同じジンク):
|
|
95
|
-
|
|
96
|
-
```css
|
|
97
|
-
:root {
|
|
98
|
-
--primary: var(--color-zinc-900);
|
|
99
|
-
--primary-foreground: oklch(0.985 0 0);
|
|
100
|
-
}
|
|
101
|
-
.dark,
|
|
102
|
-
[data-theme="dark"] {
|
|
103
|
-
--primary: var(--color-zinc-200);
|
|
104
|
-
--primary-foreground: oklch(0.205 0 0);
|
|
105
|
-
}
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
- `DESIGN.md` の差分: トーンを上の文に。強調 = `--chart-1`(最も濃い灰)。良い = 専用色なし(▲ と
|
|
109
|
-
符号)、悪い = `--destructive`(**画面で唯一の有彩色**として使う)。チャートは系列を 3 つまでにし、
|
|
110
|
-
それ以上は直接ラベルを付ける。禁止: 隣り合う `--chart-4` と `--chart-5`(明度差が小さい)。
|
|
1
|
+
# 初期デザイン(テーマ)
|
|
2
|
+
|
|
3
|
+
プロジェクトの見た目の出発点は、SquadKit の 7 テーマから選ぶ。**テーマ id はプロジェクト作成の
|
|
4
|
+
ワークフローが参照するので変えないこと。** テーマは主色・背景・文字・境界・チャート 5 色・角丸・書体を
|
|
5
|
+
まとめて持つ(ライトとダークの両方)。
|
|
6
|
+
|
|
7
|
+
| id | トーン | 向く場面 |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| `neutral` | 既定。Vantage の素の見た目(青の主色と無彩色の面) | 迷ったとき・おまかせ |
|
|
10
|
+
| `ocean` | 青を基調にした落ち着いた信頼感。角丸はやや小さめ | 報告書・経営向け |
|
|
11
|
+
| `forest` | 緑を基調にした自然な印象。丸ゴシック系の書体、角丸はやや小さめ | 環境・ヘルスケア・自然 |
|
|
12
|
+
| `sunset` | 橙を基調にした温かみ。角丸はやや大きめ | 営業・マーケティング |
|
|
13
|
+
| `violet` | 紫を基調にしたやわらかい印象。角丸は大きめ | 華やかさ・ポップ |
|
|
14
|
+
| `rose` | 赤紫からピンクの落ち着いた色。角丸は大きめ(`--destructive` の赤とは別の色) | 華やかさ・ポップ |
|
|
15
|
+
| `mono` | 無彩色寄り。チャートも彩度を抑え、角丸は最小。等幅フォント | 印刷・資料への貼り付け |
|
|
16
|
+
|
|
17
|
+
## 当てる
|
|
18
|
+
|
|
19
|
+
プロジェクトルートで次を実行する。`--dry-run` で書き込まずに結果を見られる。
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npx @squadbase/vantage-template theme <id>
|
|
23
|
+
npx @squadbase/vantage-template theme ocean --reset-chart # chart コマンドで選んだ配色を捨て、テーマのチャート色に揃える
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
- `styles.css` の ``/* squadkit-theme — regenerated by `theme`; edits here are lost */`` 〜
|
|
27
|
+
`/* squadkit-theme:end */` の範囲(テーマ範囲)だけを差し替える。**範囲の中は手で編集しない**。
|
|
28
|
+
マーカーが無いファイルには自動で足される。同じ id を再実行しても変わらない。
|
|
29
|
+
- テーマ範囲はファイル先頭の `:root` より後ろに置かれ、同じ詳細度なら後ろが勝つ。
|
|
30
|
+
先頭の `:root` に手書きした `--primary` などはテーマに負ける。
|
|
31
|
+
- `chart <preset>` の範囲(`--chart-*` だけ)はテーマ範囲の**後ろ**に置かれ、テーマのチャート色に勝つ。
|
|
32
|
+
チャートの配色もテーマに任せるなら `--reset-chart` で外す。
|
|
33
|
+
|
|
34
|
+
## 旧プリセット id の読み替え
|
|
35
|
+
|
|
36
|
+
古い呼び出しの `default` / `calm` / `vivid` / `mono` は、`theme` コマンドがそのまま受けて次の id として扱う。
|
|
37
|
+
|
|
38
|
+
| 旧 | 新 |
|
|
39
|
+
| --- | --- |
|
|
40
|
+
| `default` | `neutral` |
|
|
41
|
+
| `calm` | `ocean` |
|
|
42
|
+
| `vivid` | `sunset` |
|
|
43
|
+
| `mono` | `mono` |
|
|
44
|
+
|
|
45
|
+
## テーマに無い値(ブランド色など)
|
|
46
|
+
|
|
47
|
+
テーマの `--primary` を変えたい、特定の色だけブランドに合わせたい、というときは、テーマを当てたうえで
|
|
48
|
+
**`/* squadkit-theme:end */`(チャート範囲があればその終端)より後ろ**に、変えたいトークンだけ
|
|
49
|
+
`:root` と `.dark, [data-theme="dark"]` の**両方**に書く。前に書くとテーマに負ける。
|
|
50
|
+
`scripts/contrast.mjs` で `--primary-foreground` / `--primary` をライトとダークで確かめる。
|
|
51
|
+
|
|
52
|
+
## DESIGN.md
|
|
53
|
+
|
|
54
|
+
`format.md` の雛形から作り、選んだテーマに合わせて次の行だけ書き換える。
|
|
55
|
+
|
|
56
|
+
- 「全体のトーン」: 上の表のトーンを 2〜3 行に。
|
|
57
|
+
- 主色の行: テーマの主色の色味(「青」「橙」など。**色コードは書かない**)。
|
|
58
|
+
- チャートの色味: テーマの `--chart-1..5` の並び(適用後の `styles.css` を見る)。
|
|
59
|
+
- 良い / 悪い / 注意: 専用トークンは無い。`--chart-*` から割り当てるか「専用トークンなし」と書く。
|
|
60
|
+
`--destructive` を普通の系列色に使わない。
|
|
@@ -94,6 +94,11 @@ Base UI の `SelectValue` は選択中の **value をそのまま描き**、`Sel
|
|
|
94
94
|
- 表示ルート `/sales/:customerId`
|
|
95
95
|
- リンク `to="/sales/$customerId"` + `params={{ customerId }}` / 取り出し `useParams().customerId`
|
|
96
96
|
|
|
97
|
+
## 日本語アプリは `lang` を指定する
|
|
98
|
+
|
|
99
|
+
ルート `src/_layout.tsx` に `export const lang = "ja"`(リテラル)が無いと `<html lang="en">` のままで、
|
|
100
|
+
スライドの見出しが文節の途中で折れる。内容が日本語なら必ず指定する。
|
|
101
|
+
|
|
97
102
|
## ページ:`definePage` の値はリテラルで書く
|
|
98
103
|
|
|
99
104
|
title/description/navLabel は**ビルド時に静的抽出**される。変数・関数呼び出し・テンプレート補間を
|