diff --git a/src/data/roles.js b/src/data/roles.js new file mode 100644 index 000000000..6ba7e8ffa --- /dev/null +++ b/src/data/roles.js @@ -0,0 +1,13 @@ +/** + * roles.js — canonical role id list (R01..R12) and order. + * + * Single source of truth for which roles exist and in what order. Both the + * /roles documentation page and the share-url helpers consume this, so the + * role set can never drift between the two. + * + * Per-role colors live in mm-design (ROLE_COLORS in design/tokens); this file + * only owns the ids and their canonical order. + */ + +/** Valid role ids R01..R12, in canonical order. */ +export const ROLE_IDS = Array.from({ length: 12 }, (_, i) => `R${String(i + 1).padStart(2, '0')}`) diff --git a/src/pages/RolesPage.jsx b/src/pages/RolesPage.jsx index eb13e7bb8..9c0f170bc 100644 --- a/src/pages/RolesPage.jsx +++ b/src/pages/RolesPage.jsx @@ -7,36 +7,29 @@ import { useTranslation } from 'react-i18next' import { Card, SectionLabel } from '../components/ui' import { RoleIcon, ArrowRightIcon } from '../components/MoonIcons' import { usePageMeta } from '../hooks/usePageMeta' +import { ROLE_IDS } from '../data/roles' +import { ROLE_COLORS } from '../design/tokens' -const ROLES = [ - { key: 'R01', accent: 'text-emerald-600', bg: 'bg-emerald-50' }, // Dolphin P+ B+ - { key: 'R02', accent: 'text-red-500', bg: 'bg-red-50' }, // Wolf P+ B- - { key: 'R03', accent: 'text-teal-600', bg: 'bg-teal-50' }, // Elephant P- B+ - { key: 'R04', accent: 'text-slate-600', bg: 'bg-slate-50' }, // Owl P- B- - { key: 'R05', accent: 'text-amber-500', bg: 'bg-amber-50' }, // Eagle P+ V+ - { key: 'R06', accent: 'text-orange-500', bg: 'bg-orange-50' }, // Falcon P+ V- - { key: 'R07', accent: 'text-[var(--mm-color-green)]', bg: 'bg-[var(--mm-color-green-tint)]' }, // Octopus P- V+ - { key: 'R08', accent: 'text-stone-600', bg: 'bg-stone-50' }, // Tortoise P- V- - { key: 'R09', accent: 'text-yellow-600', bg: 'bg-yellow-50' }, // Bee B+ V+ - { key: 'R10', accent: 'text-amber-800', bg: 'bg-amber-100' }, // Bear B+ V- - { key: 'R11', accent: 'text-[var(--mm-color-green)]', bg: 'bg-[var(--mm-color-green-tint)]' }, // Fox B- V+ - { key: 'R12', accent: 'text-gray-600', bg: 'bg-gray-50' }, // Badger B- V- -] - -function RoleSummaryCard({ roleKey, accent, bg, t }) { +function RoleSummaryCard({ roleKey, t }) { const name = t(`roles.${roleKey}.name`) const ca = t(`roles.${roleKey}.ca`) const essence = t(`roles.${roleKey}.essence`) const profile = t(`roles.${roleKey}.profile`) const contributes = t(`roles.${roleKey}.contributes`) const misses = t(`roles.${roleKey}.misses`) + // Color comes from the canonical role palette (mm-design), not a local + // Tailwind class. The header strip is a soft tint mixed from that one color. + const color = ROLE_COLORS[roleKey] return ( -
- +
+
-

+

{name}{ca !== name ? ` · ${ca}` : ''}

{essence}

@@ -120,8 +113,8 @@ export default function RolesPage() { {t('rolesPage.grid.heading')}
- {ROLES.map(({ key, accent, bg }) => ( - + {ROLE_IDS.map(key => ( + ))}
diff --git a/src/utils/role-share.js b/src/utils/role-share.js index 72e43ca65..cf89ebf09 100644 --- a/src/utils/role-share.js +++ b/src/utils/role-share.js @@ -8,9 +8,11 @@ */ import { computeRole } from './role-scoring' import { encodeScores } from './share-url' +import { ROLE_IDS } from '../data/roles' -/** Valid role ids R01..R12. */ -export const ROLE_IDS = Array.from({ length: 12 }, (_, i) => `R${String(i + 1).padStart(2, '0')}`) +/** Re-exported so existing importers keep their `from '../role-share'` path. + * Canonical definition lives in data/roles. */ +export { ROLE_IDS } /** True if id is a known role id. */ export function isRoleId(id) {