# Custom properties for builders

Custom properties let you expose settings for your extension in the Interface Designer sidebar—so builders can change how your extension behaves without writing any code.

These settings could be things like:
* A label or title for a section
* A toggle for turning a feature on or off

They’re useful for making your extension flexible and reusable across different bases or interfaces.

## Using [useCustomProperties](https://airtable.com/developers/interface-extensions/api/ui/hooks/usecustomproperties.md)

The `useCustomProperties` hook is the main API for defining and reading custom properties in Interface Extensions. It updates in real time as builders change property values in the UI.
Here’s the basic idea:
1. You define the settings your extension needs.
2. They show up in the Interface Designer’s sidebar.
3. You use the values in your UI logic.

## How to use it
1. Define your properties in a function. This function receives the current [`base`](https://airtable.com/developers/interface-extensions/api/models/base.md) and returns an array of [`BlockPageElementCustomProperty`](https://airtable.com/developers/interface-extensions/api/blockpageelementcustomproperty.md) objects.
2. **Important**: wrap the function in `useCallback` or define it outside of the component. This ensures a stable identity, which is important for memoization and for subscribing to schema changes correctly.
3. Call `useCustomProperties` with your function. It returns an object with:
    * `customPropertyValueByKey`: a mapping of each property’s key to its current value.
    * `errorState`: if present, contains an error from trying to set up custom properties.

For instance, let’s say you’re building a chart extension. You want builders to be able to pick which fields to use on the X and Y axes, set a title, and choose whether to show a legend.

Here’s what that might look like:
```
import { useCustomProperties } from '@airtable/blocks/interface/ui';
import { useCallback } from 'react';

function MyChartExtension() {
  const getCustomProperties = useCallback((base) => {
    const table = base.tables[0];
    const numberFields = table.fields.filter(field => field.type === 'number');

    return [
      { key: 'title', label: 'Title', type: 'string', defaultValue: 'My Chart' },
      { key: 'xAxis', label: 'X Axis', type: 'field', table, possibleValues: numberFields },
      { key: 'yAxis', label: 'Y Axis', type: 'field', table, possibleValues: numberFields },
      { key: 'color', label: 'Color', type: 'enum', possibleValues: ['red', 'blue', 'green'], defaultValue: 'blue' },
      { key: 'showLegend', label: 'Show legend', type: 'boolean', defaultValue: true },
    ];
  }, []);

  const { customPropertyValueByKey } = useCustomProperties(getCustomProperties);

  return (
    <div>
      <h2>{customPropertyValueByKey.title}</h2>
      {customPropertyValueByKey.showLegend && <Legend />}
      {/* Use xAxis, yAxis, and color to render the chart */}
    </div>
  );
}
```

## How it works
* Your custom properties are defined in a function and passed to `useCustomProperties`.
* These settings show up in the right-hand sidebar when someone selects your extension in the Interface Designer.
* You use the values (like `customPropertyValueByKey.title`) in your component logic.

