Add checklist switching and contextual memo ticker
All checks were successful
Deploy Sokko G / deploy (push) Successful in 19s
All checks were successful
Deploy Sokko G / deploy (push) Successful in 19s
This commit is contained in:
parent
273bc5d528
commit
bd4059c9c1
16 changed files with 231 additions and 28 deletions
33
website/src/features/toolboxes/GlobalMemosTicker.jsx
Normal file
33
website/src/features/toolboxes/GlobalMemosTicker.jsx
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Rôle : affiche en bas de page les mémos actifs de la toolbox courante ou liée au jeu.
|
||||
import { useMemo } from "react";
|
||||
import { moduleStorageKey, normalizeMemosData } from "./storage/toolboxStorage.js";
|
||||
import { MemosTicker } from "./modules/MemosTicker.jsx";
|
||||
|
||||
function getRouteToolboxId(route, links) {
|
||||
const toolboxMatch = route.match(/^\/toolbox\/([^/]+)/);
|
||||
if (toolboxMatch) return decodeURIComponent(toolboxMatch[1]);
|
||||
const gameMatch = route.match(/^\/games\/([^/]+)/);
|
||||
return gameMatch ? links[gameMatch[1]] || "" : "";
|
||||
}
|
||||
|
||||
export function GlobalMemosTicker({ route, toolboxes, links, moduleData, textContent }) {
|
||||
const items = useMemo(() => {
|
||||
const toolboxId = getRouteToolboxId(route, links);
|
||||
const toolbox = toolboxes.find((item) => item.id === toolboxId);
|
||||
if (!toolbox) return [];
|
||||
return toolbox.modules
|
||||
.filter((module) => module.type === "memos")
|
||||
.flatMap((module) => {
|
||||
const data = normalizeMemosData(moduleData[moduleStorageKey(toolbox.id, module.id)]);
|
||||
if (!data.tickerEnabled) return [];
|
||||
return data.items.map((memo) => ({ ...memo, id: `${module.id}:${memo.id}` }));
|
||||
});
|
||||
}, [route, toolboxes, links, moduleData]);
|
||||
|
||||
if (!items.length) return null;
|
||||
return (
|
||||
<aside className="global-memos-ticker" aria-label={textContent?.tickerLabel || "Mémos"}>
|
||||
<MemosTicker items={items} label={textContent?.tickerLabel || "Mémos"} />
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import { Icon } from "../../../components/Icon.jsx";
|
|||
import { moveItem, useGroupedReorder } from "../../../hooks/useGroupedReorder.js";
|
||||
import { useMemo } from "react";
|
||||
import { MemoTextEditor } from "./MemoTextEditor.jsx";
|
||||
import { MemosTicker } from "./MemosTicker.jsx";
|
||||
import { TextExchangeActions } from "./TextExchangeActions.jsx";
|
||||
import { TEXT_COLORS } from "./notepadUtils.js";
|
||||
|
||||
|
|
@ -92,21 +93,12 @@ export function MemosModule({ toolboxId, moduleId, context, editing, textExchang
|
|||
type="button"
|
||||
onClick={() => save({ ...data, tickerEnabled: !data.tickerEnabled })}
|
||||
aria-pressed={data.tickerEnabled}
|
||||
aria-label={data.tickerEnabled ? textContent.hideTickerTitle || "Masquer la bande" : textContent.showTickerTitle || "Afficher la bande"}
|
||||
title={data.tickerEnabled ? textContent.hideTickerTitle || "Masquer la bande" : textContent.showTickerTitle || "Afficher la bande"}
|
||||
>
|
||||
<Icon name={data.tickerEnabled ? "eye-open" : "eye-closed"} />
|
||||
</button>
|
||||
{tickerItems.length > 0 && (
|
||||
<div className="memos-ticker" aria-label={textContent.tickerLabel || "Mémos"}>
|
||||
<div className="memos-ticker-track">
|
||||
{[...tickerItems, ...tickerItems].map((memo, index) => (
|
||||
<span className="memos-ticker-item" key={`${memo.id}-${index}`} style={{ "--memo-color": memo.color }}>
|
||||
{memo.text}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<MemosTicker items={tickerItems} label={textContent.tickerLabel || "Mémos"} />
|
||||
</div>
|
||||
|
||||
<div className="memos-list">
|
||||
|
|
|
|||
15
website/src/features/toolboxes/modules/MemosTicker.jsx
Normal file
15
website/src/features/toolboxes/modules/MemosTicker.jsx
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
// Rôle : affiche la bande déroulante partagée par l'outil Mémos et les pages associées.
|
||||
export function MemosTicker({ items, label = "Mémos", className = "" }) {
|
||||
if (!items?.length) return null;
|
||||
return (
|
||||
<div className={["memos-ticker", className].filter(Boolean).join(" ")} aria-label={label}>
|
||||
<div className="memos-ticker-track">
|
||||
{[...items, ...items].map((memo, index) => (
|
||||
<span className="memos-ticker-item" key={`${memo.id}-${index}`} style={{ "--memo-color": memo.color }}>
|
||||
{memo.text}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue