Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
2e1a941
add storage strategies guide with animated diagrams
marcelosalloum Jul 15, 2026
a1fea20
codex worked oncorrecting Soroban storage strategies guide
marcelosalloum Jul 18, 2026
5440fd9
fix storage guide facts, diagram styling and animations
marcelosalloum Jul 20, 2026
dc78ebd
polish storage guide, add markdown-source plugin
marcelosalloum Jul 20, 2026
9279b48
fix ttl animation, clarify tier and cap wording
marcelosalloum Jul 20, 2026
ee0d6fc
clarify strategies 7-8, fix swap-and-pop diagram
marcelosalloum Jul 20, 2026
e0d7376
polish strategy titles, s9 wording and diagrams
marcelosalloum Jul 21, 2026
5df70cf
rework strategy 10 and its diagram, note cap-85
marcelosalloum Jul 21, 2026
f66e227
clarify decision path, cheatsheet, s11 diagram
marcelosalloum Jul 21, 2026
1d9a9fe
add checkpoints strategy as s10, renumber s10-11 to s11-12
marcelosalloum Jul 21, 2026
c322537
make d1/d3/d7 animations finite, show allowance deadline checks
marcelosalloum Jul 21, 2026
6d0e48d
drop the markdown-source dev middleware
marcelosalloum Jul 21, 2026
2bb068a
apply review wording and formatting feedback
marcelosalloum Jul 24, 2026
766eb90
correct snippet semantics and cost accounting
marcelosalloum Jul 24, 2026
22ce567
relabel d5 ttl diagram as not to scale
marcelosalloum Jul 24, 2026
19e1812
show bump-on-read via a balance getter
marcelosalloum Jul 24, 2026
7a4716a
show diagram final frames when javascript is off
marcelosalloum Jul 24, 2026
eab9e61
cite oz smart account instead of passkey-kit
marcelosalloum Jul 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
725 changes: 725 additions & 0 deletions docs/build/guides/storage/storage-strategies.mdx

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions routes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
/docs/build/guides/storage
/docs/build/guides/storage/choosing-the-right-storage
/docs/build/guides/storage/migrate-contract-storage
/docs/build/guides/storage/storage-strategies
/docs/build/guides/storage/use-instance
/docs/build/guides/storage/use-persistent
/docs/build/guides/storage/use-temporary
Expand Down
109 changes: 109 additions & 0 deletions src/components/StorageStrategies/AnimatedDiagram.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import React, { useEffect, useRef, useState } from "react";
import "./diagrams.css";

interface AnimatedDiagramProps {
id: string;
caption?: string;
children: React.ReactNode;
}

// Card that plays its CSS/SVG animations once it scrolls into view, with a
// replay button. Animations are gated behind the .play class (see diagrams.css).
export default function AnimatedDiagram({
id,
caption,
children,
}: AnimatedDiagramProps) {
const ref = useRef<HTMLDivElement>(null);
// .play must live in React state: it gates animation-play-state in CSS, and
// an imperatively added class would be dropped on the next re-render.
const [playing, setPlaying] = useState(false);
const [restored, setRestored] = useState({
instance: false,
persistent: false,
});

useEffect(() => {
const el = ref.current;
if (!el) {
return undefined;
}
const io = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setPlaying(true);
io.unobserve(el);
}
});
},
{ threshold: 0.45 },
);
io.observe(el);
return () => io.disconnect();
}, []);

const replay = () => {
const el = ref.current;
if (!el) {
return;
}
setRestored({ instance: false, persistent: false });
setPlaying(true);
// Toggling .play only pauses/resumes; to restart from frame 0 the
// animations themselves must be torn down and recreated.
const anims = el.querySelectorAll<HTMLElement | SVGElement>(".anim");
anims.forEach((a) => {
a.style.animation = "none";
});
void (el as HTMLElement).offsetWidth;
anims.forEach((a) => {
a.style.animation = "";
});
};

const className = [
"ssd",
playing ? "play" : "",
restored.instance ? "restored-instance" : "",
restored.persistent ? "restored-persistent" : "",
]
.filter(Boolean)
.join(" ");

return (
<div className={className} id={id} ref={ref}>
<div className="diagram-controls">
{id === "d0" ? (
<>
<button
className="restore"
type="button"
aria-pressed={restored.instance}
onClick={() =>
setRestored((current) => ({ ...current, instance: true }))
}
>
Restore instance
</button>
<button
className="restore"
type="button"
aria-pressed={restored.persistent}
onClick={() =>
setRestored((current) => ({ ...current, persistent: true }))
}
>
Restore persistent entry
</button>
</>
) : null}
<button className="replay" type="button" onClick={replay}>
{id === "d0" ? "↻ Replay expiry" : "↻ Replay"}
</button>
Comment thread
marcelosalloum marked this conversation as resolved.
</div>
{children}
{caption ? <p className="caption">{caption}</p> : null}
</div>
);
}
Loading