Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
01c1d2e
Add action-tracker input schema definition
luanzeba Jan 24, 2026
1f1ea76
Add ActionTrackerInput component (MVP)
luanzeba Jan 24, 2026
7adaedb
Register ActionTrackerInput in ConfigurableInput
luanzeba Jan 24, 2026
cf38349
Update store to handle action-tracker dynamic fields
luanzeba Jan 24, 2026
15fee35
Add example action-tracker inputs for Auto and Teleop phases
luanzeba Jan 24, 2026
bda9b6e
Regenerate JSON schema with action-tracker type
luanzeba Jan 24, 2026
91be629
Fix Copy Column Names to use fieldValues codes for action-tracker sup…
luanzeba Jan 24, 2026
a5cee22
Delete .claude/settings.local.json
luanzeba Jan 25, 2026
6a30283
Delete CLAUDE.md
luanzeba Jan 25, 2026
50e45ef
Fix Copy Column Names to expand action-tracker with human-friendly names
luanzeba Jan 26, 2026
9ce9f91
Add optional icon property to action schema
luanzeba Jan 26, 2026
12277e6
Add DynamicIcon component for lazy-loaded Lucide icons in action buttons
luanzeba Jan 26, 2026
b1bed3c
Regenerate JSON schema with icon property in action definition
luanzeba Jan 26, 2026
f0c915d
Add example Lucide icons to action-tracker buttons in sample config
luanzeba Jan 26, 2026
467ff9c
fix: use min-height for action buttons to accommodate icons and wrapp…
luanzeba Jan 26, 2026
67064a6
perf: lazy-load DynamicIcon module to reduce main bundle size
luanzeba Jan 26, 2026
f91fb0a
fix: use h-auto on action buttons to prevent icon overflow
luanzeba Jan 26, 2026
1059bcc
feat: add mode option (tap/hold) to action-tracker schema
luanzeba Jan 28, 2026
db6cb2d
feat: implement hold mode for action-tracker with multi-touch support
luanzeba Jan 28, 2026
3752bcc
chore: add mode: hold to test config action-trackers
luanzeba Jan 28, 2026
f9dda07
fix: improve touch handling with intent delay and scroll detection
luanzeba Jan 28, 2026
5d07b55
Merge main into add-timed-action-input
luanzeba Feb 5, 2026
302e391
docs: add action-tracker documentation, remove example config
luanzeba Feb 5, 2026
0b99e17
docs: update README action-tracker example and clean up comment
luanzeba Feb 5, 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
55 changes: 26 additions & 29 deletions config/2026/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -149,15 +149,19 @@
"defaultValue": false
},
{
"title": "Fuel scored",
"description": "The amount of fuel scored in auto",
"type": "counter",
"title": "Auto Actions",
"description": "Track robot actions during autonomous. Press Start when auto begins, then tap actions as they happen.",
"type": "action-tracker",
"required": false,
"code": "FIA",
"code": "autoAct",
"formResetBehavior": "reset",
"defaultValue": 0,
"min": 0,
"step": 1
"timerDuration": 15,
"actions": [
{ "label": "Fuel Scored", "code": "fuel" },
{ "label": "Crossed Bump", "code": "bump" },
{ "label": "Through Trench", "code": "trench" },
{ "label": "Climb Started", "code": "climbStart" }

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are just examples, we'll review them on Monday

]
},
{
"title": "Climbed Tower",
Expand Down Expand Up @@ -190,6 +194,21 @@
{
"name": "Teleop",
"fields": [
{
"title": "Teleop Actions",
"description": "Track robot actions during teleop. Press Start when teleop begins, then tap actions as they happen.",
"type": "action-tracker",
"required": false,
"code": "teleopAct",
"formResetBehavior": "reset",
"timerDuration": 135,
"actions": [
{ "label": "Fuel Scored", "code": "fuel" },
{ "label": "Fuel Passed", "code": "pass" },
{ "label": "Defense Start", "code": "defStart" },
{ "label": "Defense End", "code": "defEnd" }
]
},
{
"title": "Fuel Collected From Ground",
"description": "Collected fuel from the ground",
Expand Down Expand Up @@ -217,28 +236,6 @@
"formResetBehavior": "reset",
"required": false
},
{
"title": "Robot Fuel Scored",
"description": "The amount of fuel scored in teleop (by the robot)",
"type": "counter",
"required": false,
"code": "FIT",
"formResetBehavior": "reset",
"defaultValue": 0,
"min": 0,
"step": 1
},
{
"title": "Human Fuel Scored",
"description": "The amount of fuel scored directly by the human player",
"type": "counter",
"required": false,
"code": "HFS",
"formResetBehavior": "reset",
"defaultValue": 0,
"min": 0,
"step": 1
},
{
"title": "Crossed Field/Played Defense?",
"type": "boolean",
Expand Down
74 changes: 73 additions & 1 deletion public/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@
"description": "Code of the form field to get this value from"
}
},
"description": "Whether or not to always show the selected team number at the top of the screen"
"required": [
"show",
"codeValue"
],
"additionalProperties": false,
"description": "Optional floating text box at the tob of the screen to show things like the team number. May be useful on small screens"
},
"theme": {
"type": "object",
Expand Down Expand Up @@ -662,6 +667,73 @@
"code"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"title": {
"$ref": "#/properties/sections/items/properties/fields/items/anyOf/0/properties/title"
},
"description": {
"$ref": "#/properties/sections/items/properties/fields/items/anyOf/0/properties/description"
},
"type": {
"type": "string",
"const": "action-tracker"
},
"required": {
"$ref": "#/properties/sections/items/properties/fields/items/anyOf/0/properties/required"
},
"code": {
"$ref": "#/properties/sections/items/properties/fields/items/anyOf/0/properties/code"
},
"disabled": {
"$ref": "#/properties/sections/items/properties/fields/items/anyOf/0/properties/disabled"
},
"formResetBehavior": {
"$ref": "#/properties/sections/items/properties/fields/items/anyOf/0/properties/formResetBehavior"
},
"defaultValue": {
"type": "null",
"default": null,
"description": "Default value (null, as this input generates multiple fields)"
},
"actions": {
"type": "array",
"items": {
"type": "object",
"properties": {
"label": {
"type": "string",
"description": "The display label for this action button"
},
"code": {
"type": "string",
"description": "A unique code for this action (used in field names)"
}
},
"required": [
"label",
"code"
],
"additionalProperties": false
},
"minItems": 1,
"description": "The actions to track. Each action becomes a tappable button."
},
"timerDuration": {
"type": "number",
"description": "Expected duration in seconds (for UI reference, e.g., 15 for auto, 135 for teleop)"
}
},
"required": [
"title",
"type",
"required",
"code",
"actions"
],
"additionalProperties": false
}
]
}
Expand Down
74 changes: 73 additions & 1 deletion src/assets/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@
"description": "Code of the form field to get this value from"
}
},
"description": "Whether or not to always show the selected team number at the top of the screen"
"required": [
"show",
"codeValue"
],
"additionalProperties": false,
"description": "Optional floating text box at the tob of the screen to show things like the team number. May be useful on small screens"
},
"theme": {
"type": "object",
Expand Down Expand Up @@ -662,6 +667,73 @@
"code"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"title": {
"$ref": "#/properties/sections/items/properties/fields/items/anyOf/0/properties/title"
},
"description": {
"$ref": "#/properties/sections/items/properties/fields/items/anyOf/0/properties/description"
},
"type": {
"type": "string",
"const": "action-tracker"
},
"required": {
"$ref": "#/properties/sections/items/properties/fields/items/anyOf/0/properties/required"
},
"code": {
"$ref": "#/properties/sections/items/properties/fields/items/anyOf/0/properties/code"
},
"disabled": {
"$ref": "#/properties/sections/items/properties/fields/items/anyOf/0/properties/disabled"
},
"formResetBehavior": {
"$ref": "#/properties/sections/items/properties/fields/items/anyOf/0/properties/formResetBehavior"
},
"defaultValue": {
"type": "null",
"default": null,
"description": "Default value (null, as this input generates multiple fields)"
},
"actions": {
"type": "array",
"items": {
"type": "object",
"properties": {
"label": {
"type": "string",
"description": "The display label for this action button"
},
"code": {
"type": "string",
"description": "A unique code for this action (used in field names)"
}
},
"required": [
"label",
"code"
],
"additionalProperties": false
},
"minItems": 1,
"description": "The actions to track. Each action becomes a tappable button."
},
"timerDuration": {
"type": "number",
"description": "Expected duration in seconds (for UI reference, e.g., 15 for auto, 135 for teleop)"
}
},
"required": [
"title",
"type",
"required",
"code",
"actions"
],
"additionalProperties": false
}
]
}
Expand Down
8 changes: 2 additions & 6 deletions src/components/Sections/ConfigSection/ConfigSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { ThemeSelector } from './ThemeSelector';

export function ConfigSection() {
const [showEditor, setShowEditor] = useState(false);
const formData = useQRScoutState(state => state.formData);
const fieldValues = useQRScoutState(state => state.fieldValues);

return (
<Section>
Expand All @@ -24,11 +24,7 @@ export function ConfigSection() {
variant="secondary"
onClick={() =>
navigator.clipboard.writeText(
formData.sections
.map(s => s.fields)
.flat()
.map(f => f.title)
.join('\t'),
fieldValues.map(f => f.code).join('\t'),
Comment thread
luanzeba marked this conversation as resolved.
Outdated
)
}
>
Expand Down
Loading