Component Standards & Developer Checklist
This document defines the visual, behavioural, and structural standards for Form Builder components, along with a developer pre-QA checklist to ensure consistency, usability, and clarity before release.
Summarised Checklist
Each item below corresponds to the detailed section of the same number. The order follows the sequence a developer works through when building or refactoring a component: lay out the properties panel, establish where values are inherited from, get the component rendering, wire up runtime behaviour, and finally handle the canvas behaviour that applies to containers.
1. General Component Properties Ordering
- Components use the standard three tabs: Main, Events, Appearance. Do not add further tabs.
- Main contains only essential properties needed to make the component usable on first drop.
- Properties appear in this order: Identity → Visibility/State → Core Behaviour → Primary Visuals.
- Visibility/State items (Visible, then Interaction Mode, each with its JS toggle and permission padlock) are always placed before behaviour and styling, and are added via
stdVisibleEditableInputs. - Core behaviour properties (e.g., binding / action / key config) are placed before non-essential styling options.
- Non-essential or advanced properties are not placed in Main (they go to Appearance or a collapsible panel).
2. Interaction Mode on Components
- The component uses the single Interaction Mode property. There is no separate
Enabledproperty. - Values are
editable/readOnly/disabled/inherited, stored onmodel.editMode. - Data components declare
interactionType: 'full'(four options). Buttons and actions declare'disabling'(three options — the first is labelled Enabled, not Editable, andreadOnlyis not offered). - The component implements both
model.readOnlyandmodel.disabled; the two booleans are derived from the single setting, never configured independently. editableallows data changes and non-mutating interaction;readOnlyallows non-mutating interaction only;disabledallows neither.- Disabled and read-only styling is consistent across all component types.
inheritedcorrectly resolves from the parent container, and ultimately from the form mode.
3. Permissions Rework (Visibility & Interaction Mode)
- Permissions moved from Security tab → padlock buttons on the Visible & Interaction Mode properties.
- Permissions are stored per property:
visiblePermissionsandeditModePermissions. The legacy flatpermissionsarray is migrated viamigratePermissionsToVisiblePermissions. - Clicking padlock opens the permissions dialog.
- Padlock icon turns primary colour when permissions are applied.
- Permissions act as a restriction layer only (can restrict, never promote).
- Permissions are evaluated after Explicit / Inherited / JS values resolve.
- Visibility icons appear correctly on the component:
- Eye = manually hidden
- Padlock = hidden by permissions
- FX = hidden by custom logic
- Users can re-open the dialog to edit/remove permissions.
4. Entity Configuration Inheritance (Formatting Defaults)
- Components bound to entity properties must inherit formatting defaults from the Entity Configuration layer by default.
- Inheritance must be visible in the Properties Panel and use the same inheritance model as Theme → Component values.
- The panel must clearly distinguish Theme inherited, Entity inherited, and Custom / overridden values, and allow users to override or resume inheritance without accidentally changing the current value.
- The inheritance popup replaces the old tooltip, appears consistently across supported property types, and shows the source, actions, and any relevant update information.
- If an inherited value is intentionally empty, the entire input must still show the inherited/custom state so the user can see that the value is not plain default text.
- If the upstream inherited value changes after a form was configured, the component must inherit the new value automatically and show an information/update indicator to notify the user.
5. Theme-Level Component Specific Settings
- Components must support theme-level component specific settings.
- Theme defaults must apply consistently across Form Builder and Runtime.
- Components must not rely on hardcoded values when theme-level configuration exists.
6. WYSIWYG Rendering & Fallbacks
- Component renders in true WYSIWYG form by default.
- When data/config is missing, component renders a clean fallback that still looks like the real component.
- No visible error blocks, warnings, or layout distortions.
- Placeholder/dummy values appear clean and intentional.
- Builder view visually matches final rendered form.
7. Misconfiguration Indicators
- Misconfigured components show an orange “i” icon (
#faad14) in the top-right with a helpful tooltip. - Errors are raised through
SheshaErrorhelpers and surfaced byErrorIconPopover— never by ad-hoc rendering. - Design-time configuration checks are declared on the component via
validateModel. - Containers/Data Context show orange background + orange dotted border (no icon).
- Indicators only appear when configuration is missing or invalid.
- No intrusive warnings or layout-shifting UI.
- Tooltips need to all be clear and understandable, and link to the component's documentation page.
- Misconfigured properties must show red on their border in the Properties Panel, just like a validation check.
8. Component API
- The component registers its API via
useComponentApi()+updateApi(...)and removes it on unmount. - Its API shape is declared in
componentsApi/componentApi.ts, extendingCommonComponentApiorInputComponentApi<T>. - Components are reached through
form.components, addressed by camel-cased component name. - Standard members are inherited, not re-implemented:
componentName,context,propertyName,visible,interactionMode,style(+value,required,focus,isValid,getErrors,resetfor inputs). - Component-specific members are registered at
level: 3with matched getter/setter pairs. focus()is wired in the component (it needs a live DOM ref), not in the common layer.- Every member has a JSDoc comment, since the file is served verbatim as IntelliSense to the JS editors.
- Members that must not be mutated at runtime are declared
readonly. - API writes may set a member in either direction, but cannot exceed the user's permissions — a write beyond
visiblePermissionsoreditModePermissionsis refused and logged.
9. Configurable Events
onClickandonDoubleClickare configured through a configurable action, in place of the code editor.- Action properties follow the
on{Event}Actionnaming and are typedIConfigurableActionConfiguration. allowedActionsrestricts the list wherever only a subset of actions is valid.- A migration wraps any existing script in an
Execute Scriptaction, so nothing configured is lost. - The remaining events keep their code editors.
10. Runtime Error Diagnostics
- Every exception is logged with enough context to diagnose it without reproducing it: form name, component name, and the event or action that was running.
- The three runtime error classes are each covered: exceptions from component code, from an event script, and from a chain of configured actions.
eventNameis passed tohandleEventat every call site, including the component's own inlineonChange.- The original error object is logged, preserving the stack trace.
- No exception is silently swallowed, and no local error boundary is added over the framework's.
- Runtime errors never break the UI — components always fall back to a stable, visible state.
- Misconfiguration is raised through
SheshaErrorand surfaced per item 3, not through runtime logging.
11. Updated Container Look & Feel
- Standalone containers show icon + text until they are small enough to show only Icon.
- Nested containers show icon only.
- On drag-over (any container):
- Primary-coloured dotted border appears
- 10% primary background fill appears
- Icon/text hide while dragging over
- If container contains components, the drop indicator appears correctly while keeping the above styling.
12. Updated Drop Indicators
- Dragged component shows primary-coloured rounded rectangle with its name.
- A clear drop indicator line appears where the new component will land.
- Horizontal line appears for vertically stacked layouts.
- Vertical line appears for horizontally stacked layouts.
- Indicator updates dynamically as the component moves.
- Indicator disappears immediately after drop.
- Component lands exactly where the indicator showed.
1. General Component Properties Ordering
Tab Structure
Components use exactly three tabs, in this order:
| Tab | Contains |
|---|---|
| Main | Identity, visibility & state, core behaviour, primary visual identity, validations |
| Events | Event handler scripts, added via stdEventHandlers |
| Appearance | Font, dimensions, border, background, shadow, margin & padding, custom styles — added via stdAppearancePanels |
We are purposefully keeping tabs to a minimum, so please ensure the properties you are adding fit an existing tab. Please do not create a new tab for one property.
The first tab is named Main, because it is the tab every component inherits from the master component. Some settings forms currently declare it as
key: 'common', title: 'Common'; that is incorrect and should be corrected tomain/Mainwhen the component is refactored.
The Main tab contains the essential properties required to make a component usable immediately after being added to the form.
Only include properties here that impact:
- Component identity
- Visibility & interactive state
- Core behaviour
- Primary visual identity
Everything else belongs in Appearance or in a collapsible panel. The Properties also follow a 'Progressive Disclosure' pattern, so only show things which are needed right now. If the user enables a toggle and there's additional options, only show them when the toggle is enabled. Don't overwhelm the user with options if they are not mandatory to a property. Use visibleJs on an input row to disclose progressively, and stdCollapsiblePanel to group a related set such as Format or Validations.
Main Tab General Guideline
1. Identity
Properties that tell the user what the component is.
- Component Name
- Property Name / Context / Binding
These always appear first.
If the user can’t identify the component at a glance, it’s unusable.
2. Visibility & State
Properties that determine whether the component appears and can be interacted with.
- Visible — a switch, defaulting to on
- Interaction Mode —
editable/readOnly/disabled/inherited(see Section 2)
Both are added together by stdVisibleEditableInputs, which places them on one row in this order and attaches the JS toggle and permission padlock to each. Do not add them individually.
These must be placed before behaviour or styling so users can establish basic access rules immediately.
There is no separate Enabled property. Interaction Mode covers both concerns.
3. Core Behaviour
Properties required for the component to perform its primary purpose.
Examples:
- Field / Data
- On Click (for buttons)
- Main Data Source or Key (for display components)
These define what the component “does” if not set, the component is incomplete.
4. Primary Visual Identity
Only include high-level visuals that affect clarity or recognisability.
Examples:
- Icon
- Style / Variant
- Tooltip
- Basic Dimensions (width/size only if essential)
Do not include detailed styling here, just enough to make the component feel correct in the form.
When deciding if a property belongs in Main, ask:
Is this property essential for the component to be understandable, visible, usable, or recognisable on first drop?
If YES, put it in Main in the order above.
If NO, move it to Appearance or into a collapsible panel.
Always remember to reference other components to get a general feel of their layouts if you need additional guidance. numberField/settingsForm.ts is the reference implementation.