Remove 'add item' button when array length validation is met
Unfortunately, Sanity Studio doesn't provide a built-in way to automatically hide the "Add Item" button when an array reaches its maximum validation length. The validation system will prevent publishing if the limit is exceeded, but the UI won't automatically adapt to disable or hide the add functionality.
However, you can achieve this with a custom input component that conditionally renders the array interface based on the current length. Here's the proper approach:
Solution: Custom Array Input Component
The key is to create a custom component that checks the array length against your validation rules and uses renderDefault with modified props to control the array's behavior:
// customArrayInput.js
import {ArrayOfObjectsInputProps} from 'sanity'
import {Stack, Text} from '@sanity/ui'
export function LimitedArrayInput(props: ArrayOfObjectsInputProps) {
const {value = [], schemaType} = props
// Extract max length from validation rules
const maxRule = schemaType.validation
?.flatMap(v => v._rules || [])
?.find(rule => rule.flag === 'max')
const maxLength = maxRule?.constraint
const currentLength = value.length
const isAtMax = maxLength && currentLength >= maxLength
// When at max, render with readOnly to prevent adding more items
if (isAtMax) {
return (
<Stack space={3}>
{props.renderDefault({
...props,
readOnly: true // This makes the entire array read-only
})}
<Text size={1} muted>
Maximum of {maxLength} items reached. Remove an item to add more.
</Text>
</Stack>
)
}
// Otherwise render normally
return props.renderDefault(props)
}Configure in Your Schema
Add the custom component to your array field definition using the components.input property:
import {defineField, defineArrayMember} from 'sanity'
import {LimitedArrayInput} from './customArrayInput'
export default defineField({
name: 'myArray',
type: 'array',
title: 'My Limited Array',
of: [
defineArrayMember({type: 'string'})
],
validation: Rule => Rule.max(2),
components: {
input: LimitedArrayInput
}
})Important Limitations
The approach above uses readOnly: true, which makes the entire array read-only when the limit is reached. This means:
- ✅ Users cannot add new items (the add button becomes disabled)
- ❌ Users also cannot edit or remove existing items while at the limit
If you need users to be able to remove items while at the max (so they can swap items), you'll need a more complex solution that fully reimplements the array input rather than using renderDefault.
Alternative: Conditional Field
Another approach is to use conditional fields to make the entire array field read-only based on its length:
defineField({
name: 'myArray',
type: 'array',
of: [{type: 'string'}],
validation: Rule => Rule.max(2),
readOnly: ({value}) => (value || []).length >= 2
})This has the same limitation as above – the entire field becomes read-only at the limit.
Why This Is Tricky
The reason there's no simple "hide add button" option is that Sanity's array input component is complex, handling drag-and-drop reordering, item editing, validation display, and more. The renderDefault function gives you the complete default component, but you can't easily modify just one aspect of it (like hiding a specific button) without reimplementing the entire component.
For most use cases, the read-only approach above strikes a good balance between customization effort and user experience – it clearly communicates that the limit has been reached while preventing further additions.
Show original thread25 replies
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.