Skip to content

Commit dd83015

Browse files
committed
Add responsive grid layouts and block type tour story
- Convert character and choice lists to CSS Grid for responsive multi-column layouts - Add storyplay-import-block-type-tour.json, a test story demonstrating all supported block types (narrative, chat, trait picker, persuasion, choice weighting, and ending) - Update CharactersScreen styling class for consistency
1 parent 02733c8 commit dd83015

3 files changed

Lines changed: 255 additions & 2 deletions

File tree

src/components/entities/CharactersScreen.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export default function CharactersScreen({
4747
</p>
4848
</header>
4949

50-
<div className="variables-screen-body custom-scrollbar">
50+
<div className="variables-screen-body variables-screen-body--single custom-scrollbar">
5151
<div className="variables-screen-main">
5252
<CharacterManager
5353
characters={characters}

src/style.css

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1002,7 +1002,15 @@ select {
10021002
}
10031003

10041004
.variables-screen-main .choice-list {
1005-
max-width: 720px;
1005+
display: grid;
1006+
grid-template-columns: repeat(auto-fill, minmax(min(100%, 340px), 1fr));
1007+
gap: 14px;
1008+
align-items: start;
1009+
max-width: none;
1010+
}
1011+
1012+
.variables-screen-main .choice-row {
1013+
min-width: 0;
10061014
}
10071015

10081016
.variables-workspace-promo-meta {
@@ -3566,6 +3574,18 @@ mark {
35663574
gap: 12px;
35673575
}
35683576

3577+
.characters-screen .character-list {
3578+
display: grid;
3579+
grid-template-columns: repeat(auto-fill, minmax(min(100%, 360px), 1fr));
3580+
gap: 14px;
3581+
align-items: start;
3582+
}
3583+
3584+
.characters-screen .character-card {
3585+
min-width: 0;
3586+
height: fit-content;
3587+
}
3588+
35693589
.character-card {
35703590
border: 1px solid var(--border-default);
35713591
border-left: 2px solid var(--accent-warm-border);
Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
{
2+
"formatVersion": 1,
3+
"exportedAt": "2026-07-07T00:00:00.000Z",
4+
"meta": {
5+
"title": "Block Type Tour",
6+
"description": "Short test story with one of each block type for import and play testing.",
7+
"startNodeId": "tour-start"
8+
},
9+
"story": {
10+
"variables": {
11+
"reputation": 0,
12+
"coins": 5,
13+
"pitchScore": 0,
14+
"wonPitch": false,
15+
"buildFocus": [],
16+
"prepAllocation": {},
17+
"prep_focus": 0,
18+
"prep_speed": 0,
19+
"prep_mind": 0
20+
},
21+
"variableMeta": {
22+
"reputation": {
23+
"playerLabel": "Reputation",
24+
"playerDescription": "How the guild sees you"
25+
},
26+
"coins": {
27+
"playerLabel": "Coins"
28+
}
29+
},
30+
"characters": [
31+
{
32+
"id": "char_guide",
33+
"name": "Guide",
34+
"description": "Tutorial NPC for the block type tour",
35+
"aliases": ["Instructor"]
36+
}
37+
],
38+
"nodes": [
39+
{
40+
"id": "tour-start",
41+
"type": "storyNode",
42+
"position": { "x": 40, "y": 200 },
43+
"data": {
44+
"title": "Proving Ground",
45+
"content": "A chalkboard lists every scene type StoryPlay supports.\nYour job: walk the line once, touch each block, and reach an ending.",
46+
"blockType": "narrative",
47+
"choices": [
48+
{
49+
"id": "tour-c0",
50+
"label": "Talk to the guide",
51+
"targetNodeId": "tour-chat",
52+
"conditions": [],
53+
"effects": []
54+
}
55+
],
56+
"enterEffects": [],
57+
"graphIssues": []
58+
}
59+
},
60+
{
61+
"id": "tour-chat",
62+
"type": "storyNode",
63+
"position": { "x": 360, "y": 200 },
64+
"data": {
65+
"title": "Guide's Booth",
66+
"content": "Guide: Welcome to the tour. Reply below, then pick where to go next.",
67+
"blockType": "chat",
68+
"choices": [
69+
{
70+
"id": "tour-c1a",
71+
"choiceKind": "chatReply",
72+
"label": "What comes first?",
73+
"playerMessage": "What should I try first?",
74+
"npcResponse": "Guide: Pick your strengths, then persuade me you belong here.",
75+
"targetNodeId": "",
76+
"conditions": [],
77+
"effects": []
78+
},
79+
{
80+
"id": "tour-c1b",
81+
"choiceKind": "chatReply",
82+
"label": "Sounds good.",
83+
"playerMessage": "Sounds good.",
84+
"npcResponse": "Guide: Trait picker is next on the path.",
85+
"targetNodeId": "",
86+
"conditions": [],
87+
"effects": []
88+
},
89+
{
90+
"id": "tour-c1c",
91+
"choiceKind": "goTo",
92+
"label": "Continue to trait picker",
93+
"targetNodeId": "tour-traits",
94+
"conditions": [],
95+
"effects": [{ "variable": "reputation", "action": "add", "value": 1 }]
96+
}
97+
],
98+
"enterEffects": [],
99+
"graphIssues": []
100+
}
101+
},
102+
{
103+
"id": "tour-traits",
104+
"type": "storyNode",
105+
"position": { "x": 680, "y": 200 },
106+
"data": {
107+
"title": "Trait Picker",
108+
"content": "Choose up to two focuses for this run.",
109+
"blockType": "traitPicker",
110+
"continueNodeId": "tour-persuasion",
111+
"minSelections": 1,
112+
"maxSelections": 2,
113+
"traitListVariable": "buildFocus",
114+
"options": [
115+
{
116+
"id": "focus",
117+
"label": "Focus",
118+
"description": "Steady attention under pressure.",
119+
"effects": { "reputation": 1 }
120+
},
121+
{
122+
"id": "speed",
123+
"label": "Speed",
124+
"description": "Quick reads and fast answers.",
125+
"effects": { "reputation": 1 }
126+
},
127+
{
128+
"id": "mind",
129+
"label": "Mind",
130+
"description": "Patterns, lore, and clever angles.",
131+
"effects": { "reputation": 1 }
132+
}
133+
],
134+
"choices": [],
135+
"enterEffects": [],
136+
"graphIssues": []
137+
}
138+
},
139+
{
140+
"id": "tour-persuasion",
141+
"type": "storyNode",
142+
"position": { "x": 1000, "y": 200 },
143+
"data": {
144+
"title": "Persuasion",
145+
"content": "Guide: Convince me you are ready for the weighting exercise.",
146+
"blockType": "persuasion",
147+
"targetName": "Guide",
148+
"startScore": 45,
149+
"minScore": 0,
150+
"maxScore": 100,
151+
"threshold": 70,
152+
"maxTurns": 3,
153+
"visibleMeter": true,
154+
"scoreVariable": "pitchScore",
155+
"successVariable": "wonPitch",
156+
"successNodeId": "tour-weight",
157+
"failureNodeId": "tour-ending-fail",
158+
"choices": [
159+
{
160+
"id": "p1",
161+
"text": "Name a concrete skill you will bring.",
162+
"delta": 15,
163+
"response": "Guide: Specific. I like specific."
164+
},
165+
{
166+
"id": "p2",
167+
"text": "Offer to take the hardest task first.",
168+
"delta": 10,
169+
"response": "Guide: Brave—or reckless. Either can work."
170+
},
171+
{
172+
"id": "p3",
173+
"text": "Recite the tour steps from memory.",
174+
"delta": 6,
175+
"response": "Guide: You paid attention. Barely enough."
176+
}
177+
],
178+
"enterEffects": [],
179+
"graphIssues": []
180+
}
181+
},
182+
{
183+
"id": "tour-weight",
184+
"type": "storyNode",
185+
"position": { "x": 1320, "y": 200 },
186+
"data": {
187+
"title": "Choice Weighting",
188+
"content": "Spend exactly 6 preparation points across the tracks below.",
189+
"blockType": "choiceWeighting",
190+
"continueNodeId": "tour-ending-win",
191+
"totalPoints": 6,
192+
"lockExactTotal": true,
193+
"variablePrefix": "prep_",
194+
"resultVariable": "prepAllocation",
195+
"options": [
196+
{ "id": "focus", "label": "Focus drills", "min": 0, "max": 6 },
197+
{ "id": "speed", "label": "Speed drills", "min": 0, "max": 6 },
198+
{ "id": "mind", "label": "Mind drills", "min": 0, "max": 6 }
199+
],
200+
"choices": [],
201+
"enterEffects": [],
202+
"graphIssues": []
203+
}
204+
},
205+
{
206+
"id": "tour-ending-win",
207+
"type": "storyNode",
208+
"position": { "x": 1640, "y": 120 },
209+
"data": {
210+
"title": "Tour Complete",
211+
"content": "You cleared every block type on the happy path:\nnarrative → chat → trait picker → persuasion → choice weighting → ending.\nImport test passed.",
212+
"blockType": "ending",
213+
"choices": [],
214+
"enterEffects": [],
215+
"graphIssues": []
216+
}
217+
},
218+
{
219+
"id": "tour-ending-fail",
220+
"type": "storyNode",
221+
"position": { "x": 1640, "y": 320 },
222+
"data": {
223+
"title": "Tour Incomplete",
224+
"content": "Persuasion failed—you still reached an ending block.\nReset play and try a stronger pitch to see the weighting scene.",
225+
"blockType": "ending",
226+
"choices": [],
227+
"enterEffects": [],
228+
"graphIssues": []
229+
}
230+
}
231+
]
232+
}
233+
}

0 commit comments

Comments
 (0)