# Conditional logic

Show a field or a whole page only when earlier answers match. Conditions live in the schema and are evaluated by the components and by the server, so a hidden field is never required and never stored.

```ts
{ key: 'role', type: 'dropdown', label: 'Role', options: ['Founder', 'Researcher', 'Other'], required: true },
{ key: 'role_other', type: 'short_text', label: 'Which role?', required: true,
  showWhen: { field: 'role', op: 'eq', value: 'Other' } },
```

Page-level:

```ts
{ title: 'Your team', showWhen: { field: 'role', op: 'in', value: ['Founder', 'Researcher'] }, fields: [ … ] }
```

Groups:

```ts
showWhen: { all: [ { field: 'team_size', op: 'gte', value: 10 }, { any: [ { field: 'interest', op: 'contains', value: 'surveys' }, { field: 'timeline', op: 'neq', value: 'Just looking' } ] } ] }
```

Operators: `eq`, `neq`, `in`, `notIn`, `contains`, `notContains` (strings and multiple choice), `gt`, `gte`, `lt`, `lte` (numbers, dates), `empty`, `notEmpty`.

Rules:

- A condition may reference fields on the same page or earlier pages, never later ones. `defineForm` checks this.
- A page with no visible fields is skipped; the progress indicator counts visible pages only.
- Hidden values are dropped before a partial save or a submit, and the server drops them again.
- Conditions are part of the schema version, so changing one creates a new version.

Explicit jumps and calculated fields are not supported. If `showWhen` turns out not to be enough, [tell us](https://kibbleforms.com/contact).
