Skip to main content
durationField returns a Number field that stores a duration in whole seconds. The admin panel shows 5400 as 1:30:00 and edits durations in the same form, and agents and generated types are told that the number is seconds. You don’t name any components or write a formatter.
The result is a plain number field, so it works anywhere a field does, including inside groups, arrays, tabs and blocks.

Config options

A duration field holds one value, so hasMany, minRows and maxRows are not accepted. TypeScript rejects them, and setting any of them from JavaScript fails at startup. Invalid options fail when the config is built, with an error naming the field:
Every save checks the value, whether it comes from the admin panel, the REST API, GraphQL, the Local API or an agent. A fraction such as 90.5 fails with:

Admin options

Duration fields support the standard field admin options, plus these options: FrogBot stores the field’s format in admin.custom.frogbot.kind. Your own admin.custom keys, and other keys under admin.custom.frogbot, are kept.

Display and editing

h:mm:ss shows minutes and seconds under an hour, and hours, minutes and seconds from an hour. h:mm shows hours and minutes and rounds leftover seconds up, so a duration that isn’t zero never shows as 0:00. Hours keep counting past 24, and durations look the same in every admin language. An empty value shows nothing: no placeholder and no dash. A stored 0 shows as 0:00. A stored value that isn’t a whole number, for example one saved before the field became a duration, shows as the plain stored number. Durations look the same in the List, on Board cards and in Calendar events. If a duration field is the first List column, a row with an empty value has no link to open the document from that column. In the document view, an editable duration field is a text input. The rightmost part you type is the format’s smallest unit, and each part after the first must be from 0 to 59: When you leave the input, readable text is shown in the field’s format, so 90 in an h:mm field becomes 1:30. Clearing the input saves an empty value. Text the input can’t read, such as 1:75, 1.5 or 1:, shows “Enter a duration such as 1:30.” on the field when you leave it. That text is never saved: Save and Save Draft leave the field out of the request, so the stored value is kept, and after saving the input shows the stored value again. The label, description, validation errors, min, max, required and a custom validate work as on a Number field. When the field is read-only, because of admin.readOnly, because it is virtual, or because the user may not update it, the document view shows the formatted duration as text with no input.

Stored value

Durations are stored as whole seconds: 5400 means 1 hour 30 minutes. The REST API, GraphQL and the Local API read and write the number of seconds, and the generated TypeScript type is the same as a Number field’s, such as timeSpent?: number | null.
The API takes seconds as a number. As for any Number field, a string is read as a number, so writing "1:30" saves 1. Convert typed durations with parseDuration before writing them.
Filters and sorting use the stored seconds, so a filter for durations over an hour takes 3600.

Agents and generated types

A duration field describes itself to agents using FrogBot’s MCP tools and in generated types:
With a string admin.description, or a translated one with an en entry, the duration text is added after it in parentheses. The admin panel still shows only your description.
A function admin.description isn’t copied, so the duration text stands alone. The text is English only. Generated types show the text as a comment above the property. In the MCP plugin’s create and update tools, the value is an integer, and min and max also become its minimum and maximum, so agents see the allowed range. Generated types don’t include limits, and virtual fields don’t appear in MCP tool inputs. To change the text, add your own jsonSchema entry. It runs after the duration field’s entry, so it can adjust or replace the description:

Formatting in your code

formatDuration and parseDuration are the helpers duration fields use. Import them from frogbot/fields, which is safe to use in browser code:
Here seconds is 5400 and shown is '1:30'. formatDuration returns the formatted string, or '' for an empty value. A fraction of a second, such as an average, is rounded up to the format’s smallest unit. parseDuration reads text the way the duration input does. It returns the number of seconds, null for blank text, or undefined for text it can’t read. frogbot/fields also exports the DurationFormat, DurationKind, FormatDurationArgs and ParseDurationArgs types.

Custom components

The duration cell and input are DurationCell and DurationField from @frogbotai/ui/admin. Your own admin.components.Cell or admin.components.Field replaces them, and other components such as Label, Description, Error, beforeInput and afterInput work with the duration input as they do on a Number field. A custom Cell can draw the standard duration display inside its own markup with FieldCell, as shown for Money fields. As with any custom Cell, it appears only in the List view. Board cards and Calendar events keep the standard duration display.