# Icon Column

Canonical page: https://www.adaptabletools.com/docs/handbook-styled-column-icon

- The Icon Column Style maps each cell value to a single visual — an emoji, a system icon, or an image URL
- Mappings are simple key → icon pairs; you can supply your own, pick a built-in preset, or do both
- Built-in presets ship for `Flags`, `Currencies`, `Trend` and `Status`
- Unmatched values can be hidden, shown as raw text, or replaced by a fallback icon
- Optionally pair the icon with companion text (the cell value, the mapping's description, or both)

The Icon Column Style renders each cell as a single icon (e.g. flag, symbol, custom icon etc.)

This is done by looking up the cell's value in a list of **key → icon mappings**.

- Use an Icon Column for one-glyph-per-cell visual recognition
- i.e. when each value should map to exactly one glyph (e.g. flag for country, traffic-light for status)

An Icon Style cell can additionally display the cell's value (e.g. "🇺🇸 US" rather than just "🇺🇸").

Icon Columns work with **scalar** column values (of any data type) that can be matched as a discrete key.

Icon Styles do not work on Array Columns - as they perform one lookup per cell, against the cell’s `value` as a whole

### Icon Column vs Badge Style: What are the differences and which should you use?

Another Styled Column - the [Badge Style](https://www.adaptabletools.com/docs/handbook-styled-column-badge/index.md) - can also put a small visual in a cell.

However despite this piece of overlapping functionality the Icon Style and the Badge Style answer different questions:

|                | Icon Column                                     | Badge                                             |
| -------------- | ----------------------------------------------- | ------------------------------------------------- |
| Trigger        | value → key lookup                              | expression rules (or unconditional)               |
| Items per cell | one glyph                                       | one or more pills (per element for array columns) |
| Chrome         | none — just the glyph (optional companion text) | pill background, border, padding, optional icon   |
| Presets        | `Flags`, `Currencies`, `Trend`, `Status`        | none — badges are always user-defined             |
| Best for       | flags, currencies, trend arrows, status         | rule-based labels with text and / or icon         |

- Use **Icon Column** when each value should map to a single, fixed glyph and you want zero chrome
- Use **Badge** when you need rule-based, label-like markers (often with text) and/or multiple badges per cell

## Anatomy

An Icon Style cell consists of just 2 elements:

- A single **icon** chosen by the first mapping whose `Key` matches the cell value
- Optional **companion text** rendered alongside the icon (`CellTextProperties.CellText`)

- You can also configure [Fallback Behaviour](#fallback-behaviour) for when there are no mapping matches
- AdapTable uses the mapping list built from preset + custom rows to render the column

**Example: Icon Style: Showcase**

Three Icon Styles side-by-side, each driven by a different built-in preset

- **Country** — `Preset: 'Flags'` with the country code shown as companion text after the flag
- **Direction** — `Preset: 'Trend'` (up / down arrows) with the mapping's description as companion text
- **Status** — `Preset: 'Status'` (workflow icons) with the raw status value shown after the icon
- Non-icon columns (`desk`, `currency`, `region`) sit between the icon columns as visual separators
- Each preset and its mapping / fallback options are explained in the sections below

Demo project (Vanilla); the files without a marker are shown below:

```text
src/
  adaptableOptions.ts
  agGridModules.ts     [template]
  columnDefs.ts
  gridOptions.ts       [template]
  index.ts             [template]
  onAdaptableReady.ts  [template]
  rowData.ts
  styles.css           [template]
index.html             [template]
package.json           [template]
tsconfig.json          [template]
```

Files marked `[template]` are the same in every demo; see the [demo template](https://www.adaptabletools.com/llms/demo-template.md#vanilla).

**`src/adaptableOptions.ts`**

```ts
import {AdaptableOptions} from '@adaptabletools/adaptable';
import {TradeDesk} from './rowData';

export const adaptableOptions: AdaptableOptions<TradeDesk> = {
  primaryKey: 'id',
  adaptableId: 'Icon Style Showcase',
  initialState: {
    Dashboard: {
      ModuleButtons: ['StyledColumn'],
    },
    Theme: {CurrentTheme: 'dark'},
    Layout: {
      CurrentLayout: 'Standard Layout',
      Layouts: [
        {
          Name: 'Standard Layout',
          TableColumns: [
            'desk',
            'country',
            'currency',
            'direction',
            'region',
            'status',
          ],
          AutoSizeColumns: true,
        },
      ],
    },
    StyledColumn: {
      StyledColumns: [
        {
          ColumnId: 'country',
          Name: 'Country flags',
          IconStyle: {
            Preset: 'Flags',
            MatchMode: 'CaseInsensitive',
            CellTextProperties: {
              CellText: ['CellValue'],
              CellTextPosition: 'After',
            },
            ToolTipText: ['IconDescription'],
            Size: 20,
            Gap: 6,
            FallbackProperties: {Mode: 'ShowText'},
          },
        },
        {
          ColumnId: 'direction',
          Name: 'Trade direction',
          IconStyle: {
            Preset: 'Trend',
            CellTextProperties: {
              CellText: ['IconDescription'],
              CellTextPosition: 'After',
            },
            ToolTipText: ['CellValue'],
            Size: 22,
            Gap: 6,
          },
        },
        {
          ColumnId: 'status',
          Name: 'Workflow status',
          IconStyle: {
            Preset: 'Status',
            MatchMode: 'CaseInsensitive',
            CellTextProperties: {
              CellText: ['CellValue'],
              CellTextPosition: 'After',
            },
            ToolTipText: ['IconDescription'],
            Size: 16,
            Gap: 6,
            FallbackProperties: {Mode: 'ShowText'},
          },
        },
      ],
    },
  },
};
```

**`src/rowData.ts`**

```ts
export interface TradeDesk {
  id: number;
  desk: string;
  country: string;
  currency: string;
  direction: 'Buy' | 'Sell';
  status: string;
  region: string;
  riskLevel: 'High' | 'Medium' | 'Low';
}

export const rowData: TradeDesk[] = [
  {
    id: 1,
    desk: 'NY FX',
    country: 'US',
    currency: 'USD',
    direction: 'Buy',
    status: 'Completed',
    region: 'AMER',
    riskLevel: 'Low',
  },
  {
    id: 2,
    desk: 'London Rates',
    country: 'United Kingdom',
    currency: 'gbp',
    direction: 'Sell',
    status: 'Pending',
    region: 'EMEA',
    riskLevel: 'Medium',
  },
  {
    id: 3,
    desk: 'Tokyo Equity',
    country: 'JP',
    currency: 'JPY',
    direction: 'Buy',
    status: 'Rejected',
    region: 'APAC',
    riskLevel: 'High',
  },
  {
    id: 4,
    desk: 'Paris Credit',
    country: 'France',
    currency: 'EUR',
    direction: 'Sell',
    status: 'In Progress',
    region: 'EMEA',
    riskLevel: 'Medium',
  },
  {
    id: 5,
    desk: 'Zurich PM',
    country: 'CH',
    currency: 'CHF',
    direction: 'Buy',
    status: 'Booked',
    region: 'EMEA',
    riskLevel: 'Low',
  },
  {
    id: 6,
    desk: 'Sydney',
    country: 'AU',
    currency: 'AUD',
    direction: 'Sell',
    status: 'Pass',
    region: 'APAC',
    riskLevel: 'Low',
  },
  {
    id: 7,
    desk: 'Toronto',
    country: 'CA',
    currency: 'CAD',
    direction: 'Buy',
    status: 'Fail',
    region: 'AMER',
    riskLevel: 'High',
  },
  {
    id: 8,
    desk: 'Frankfurt',
    country: 'DE',
    currency: 'IRD',
    direction: 'Sell',
    status: 'Warn',
    region: 'LATAM',
    riskLevel: 'Medium',
  },
];
```

**`src/columnDefs.ts`**

```ts
import {ColDef} from 'ag-grid-enterprise';
import {TradeDesk} from './rowData';

export const columnDefs: ColDef<TradeDesk>[] = [
  {field: 'id', hide: true, cellDataType: 'number'},
  {field: 'desk', headerName: 'Desk', cellDataType: 'text'},
  {field: 'country', headerName: 'Country', cellDataType: 'text'},
  {field: 'currency', headerName: 'Currency', cellDataType: 'text'},
  {field: 'direction', headerName: 'Direction', cellDataType: 'text'},
  {field: 'region', headerName: 'Region', cellDataType: 'text'},
  {field: 'status', headerName: 'Status', cellDataType: 'text'},
];
```

## Mappings

The base of the Icon Style are the Mappings between cell value (key) and Icon.

Each entry in `IconStyle.Mappings` has three properties:

| Property      | Type                          | Description                                                                                     |
| ------------- | ----------------------------- | ----------------------------------------------------------------------------------------------- |
| `Key`         | `string \| number \| boolean` | Cell value that triggers this mapping. Compared using `MatchMode`.                              |
| `Icon`        | `string \| AdaptableIcon`     | What to render — plain string (for emoji) or an `AdaptableIcon` (either a system icon or a URL) |
| `Description` | `string` (optional)           | Human-readable description (e.g. currency if `Key` is ISO code)                                 |

A simple emoji mapping is just `{ Key: 'GB', Icon: '🇬🇧', Description: 'United Kingdom' }`.

You can also point at AdapTable's system icons `{name: 'alert'}` or `{src: 'https://flagcdn.com/24x18/us.png'}`

### Preset Mappings

AdapTable provides 4 preset Mappings as a convenience function for users.

AdapTable users can seed an Icon Column from a **built-in preset** by simply setting `Preset` to one of:

| Preset         | Description                                                      | Icon                 |
| -------------- | ---------------------------------------------------------------- | -------------------- |
| `'Flags'`      | Common ISO 3166 alpha-2 codes (and country names)                | emoji flag           |
| `'Currencies'` | ISO 4217 flag codes                                              | issuing country flag |
| `'Trend'`      | `'Up'` / `'Down'` / `'Flat'` (and `'Buy'` / `'Sell'` / `'Hold'`) | arrow glyphs         |
| `'Status'`     | `'Pass'` / `'Warn'` / `'Fail'` (and common synonyms)             | traffic light dots   |

#### Flags

Use the **Flags** preset when the column holds ISO country codes or country names.

**Example: Icon Style: Flags**

Country flags with code beside the glyph

- **Country** — `Preset: 'Flags'`, `MatchMode: 'CaseInsensitive'` (codes like **US** and names like **United Kingdom**)
- **Cell Value** after the flag; tooltip shows the preset **Description** (country name)
- Unmatched values use **`ShowText`** fallback

Demo project (Vanilla); the files without a marker are shown below:

```text
src/
  adaptableOptions.ts
  agGridModules.ts     [template]
  columnDefs.ts
  gridOptions.ts       [template]
  index.ts             [template]
  onAdaptableReady.ts  [template]
  rowData.ts
  styles.css           [template]
index.html             [template]
package.json           [template]
tsconfig.json          [template]
```

Files marked `[template]` are the same in every demo; see the [demo template](https://www.adaptabletools.com/llms/demo-template.md#vanilla).

**`src/adaptableOptions.ts`**

```ts
import {AdaptableOptions} from '@adaptabletools/adaptable';
import {TradeDesk} from './rowData';

export const adaptableOptions: AdaptableOptions<TradeDesk> = {
  primaryKey: 'id',
  adaptableId: 'Icon Style Flags',
  initialState: {
    Dashboard: {
      ModuleButtons: ['StyledColumn'],
    },
    Theme: {CurrentTheme: 'dark'},
    Layout: {
      CurrentLayout: 'Standard Layout',
      Layouts: [
        {
          Name: 'Standard Layout',
          TableColumns: ['desk', 'country', 'currency', 'direction'],
          AutoSizeColumns: true,
        },
      ],
    },
    StyledColumn: {
      StyledColumns: [
        {
          ColumnId: 'country',
          Name: 'Country flags',
          IconStyle: {
            Preset: 'Flags',
            MatchMode: 'CaseInsensitive',
            CellTextProperties: {
              CellText: ['CellValue'],
              CellTextPosition: 'After',
            },
            ToolTipText: ['IconDescription'],
            Size: 20,
            Gap: 6,
            FallbackProperties: { Mode: 'ShowText' },
          },
        },
      ],
    },
  },
};
```

**`src/columnDefs.ts`**

```ts
import {ColDef} from 'ag-grid-enterprise';
import {TradeDesk} from './rowData';

export const columnDefs: ColDef<TradeDesk>[] = [
  {field: 'id', hide: true, cellDataType: 'number'},
  {field: 'desk', headerName: 'Desk', cellDataType: 'text'},
  {field: 'country', headerName: 'Country', cellDataType: 'text'},
  {field: 'currency', headerName: 'Currency', cellDataType: 'text'},
  {field: 'direction', headerName: 'Direction', cellDataType: 'text'},
  {field: 'status', headerName: 'Status', cellDataType: 'text'},
];
```

**`src/rowData.ts`**

```ts
export interface TradeDesk {
  id: number;
  desk: string;
  country: string;
  currency: string;
  direction: 'Buy' | 'Sell';
  status: string;
  region: string;
  riskLevel: 'High' | 'Medium' | 'Low';
}

export const rowData: TradeDesk[] = [
  {
    id: 1,
    desk: 'NY FX',
    country: 'US',
    currency: 'USD',
    direction: 'Buy',
    status: 'Completed',
    region: 'AMER',
    riskLevel: 'Low',
  },
  {
    id: 2,
    desk: 'London Rates',
    country: 'United Kingdom',
    currency: 'gbp',
    direction: 'Sell',
    status: 'Pending',
    region: 'EMEA',
    riskLevel: 'Medium',
  },
  {
    id: 3,
    desk: 'Tokyo Equity',
    country: 'JP',
    currency: 'JPY',
    direction: 'Buy',
    status: 'Rejected',
    region: 'APAC',
    riskLevel: 'High',
  },
  {
    id: 4,
    desk: 'Paris Credit',
    country: 'France',
    currency: 'EUR',
    direction: 'Sell',
    status: 'In Progress',
    region: 'EMEA',
    riskLevel: 'Medium',
  },
  {
    id: 5,
    desk: 'Zurich PM',
    country: 'CH',
    currency: 'CHF',
    direction: 'Buy',
    status: 'Booked',
    region: 'EMEA',
    riskLevel: 'Low',
  },
  {
    id: 6,
    desk: 'Sydney',
    country: 'AU',
    currency: 'AUD',
    direction: 'Sell',
    status: 'Pass',
    region: 'APAC',
    riskLevel: 'Low',
  },
  {
    id: 7,
    desk: 'Toronto',
    country: 'CA',
    currency: 'CAD',
    direction: 'Buy',
    status: 'Fail',
    region: 'AMER',
    riskLevel: 'High',
  },
  {
    id: 8,
    desk: 'Frankfurt',
    country: 'DE',
    currency: 'IRD',
    direction: 'Sell',
    status: 'Warn',
    region: 'LATAM',
    riskLevel: 'Medium',
  },
];
```

#### Currencies

Use **Currencies** to display ISO 4217 codes.

- Each code maps to the issuing country's **flag**
- This means that each currency gets a unique glyph (unlike `$` which is shared by USD / AUD / CAD)

**Example: Icon Style: Currencies**

Preset plus custom overrides

- This example shows how to use the **Currency** preset (on the `Currency` column) 
- We **override** the default flag for `gbp` with a custom icon (💷)
- We provide a **custom mapping** for `IRD` (🪙) as it is not included in the preset
- We set `CaseInsensitive` matching and for the `Description` to be shown after the icon

Demo project (Vanilla); the files without a marker are shown below:

```text
src/
  adaptableOptions.ts
  agGridModules.ts     [template]
  columnDefs.ts
  gridOptions.ts       [template]
  index.ts             [template]
  onAdaptableReady.ts  [template]
  rowData.ts
  styles.css           [template]
index.html             [template]
package.json           [template]
tsconfig.json          [template]
```

Files marked `[template]` are the same in every demo; see the [demo template](https://www.adaptabletools.com/llms/demo-template.md#vanilla).

**`src/adaptableOptions.ts`**

```ts
import {AdaptableOptions} from '@adaptabletools/adaptable';
import {TradeDesk} from './rowData';

export const adaptableOptions: AdaptableOptions<TradeDesk> = {
  primaryKey: 'id',
  adaptableId: 'Icon Style Currencies',
  initialState: {
    Dashboard: {
      ModuleButtons: ['StyledColumn'],
    },
    Theme: {CurrentTheme: 'dark'},
    Layout: {
      CurrentLayout: 'Standard Layout',
      Layouts: [
        {
          Name: 'Standard Layout',
          TableColumns: ['desk', 'currency', 'country'],
          AutoSizeColumns: true,
          ColumnSizing: {
            currency: {Width: 250},
            country: {Width: 250},
          },
        },
      ],
    },
    StyledColumn: {
      StyledColumns: [
        {
          ColumnId: 'currency',
          Name: 'Currency flags',
          IconStyle: {
            Preset: 'Currencies',
            Mappings: [
              {
                Key: 'IRD',
                Icon: '🪙',
                Description: 'Internal redemption deposit',
              },
              {
                Key: 'gbp',
                Icon: '💷',
                Description: 'Pound sterling',
              },
            ],
            MatchMode: 'CaseInsensitive',
            CellTextProperties: {
              CellText: ['IconDescription'],
              CellTextPosition: 'After',
            },
            ToolTipText: ['CellValue', 'IconDescription'],
            Size: 20,
            Gap: 6,
            FallbackProperties: { Mode: 'ShowText' },
          },
        },
      ],
    },
  },
};
```

**`src/columnDefs.ts`**

```ts
import {ColDef} from 'ag-grid-enterprise';
import {TradeDesk} from './rowData';

export const columnDefs: ColDef<TradeDesk>[] = [
  {field: 'id', hide: true, cellDataType: 'number'},
  {field: 'desk', headerName: 'Desk', cellDataType: 'text'},
  {field: 'currency', headerName: 'Currency', cellDataType: 'text'},
  {field: 'country', headerName: 'Country', cellDataType: 'text'},
];
```

**`src/rowData.ts`**

```ts
export interface TradeDesk {
  id: number;
  desk: string;
  country: string;
  currency: string;
  direction: 'Buy' | 'Sell';
  status: string;
  region: string;
  riskLevel: 'High' | 'Medium' | 'Low';
}

export const rowData: TradeDesk[] = [
  {
    id: 1,
    desk: 'NY FX',
    country: 'US',
    currency: 'USD',
    direction: 'Buy',
    status: 'Completed',
    region: 'AMER',
    riskLevel: 'Low',
  },
  {
    id: 2,
    desk: 'London Rates',
    country: 'United Kingdom',
    currency: 'gbp',
    direction: 'Sell',
    status: 'Pending',
    region: 'EMEA',
    riskLevel: 'Medium',
  },
  {
    id: 3,
    desk: 'Tokyo Equity',
    country: 'JP',
    currency: 'JPY',
    direction: 'Buy',
    status: 'Rejected',
    region: 'APAC',
    riskLevel: 'High',
  },
  {
    id: 4,
    desk: 'Paris Credit',
    country: 'France',
    currency: 'EUR',
    direction: 'Sell',
    status: 'In Progress',
    region: 'EMEA',
    riskLevel: 'Medium',
  },
  {
    id: 5,
    desk: 'Zurich PM',
    country: 'CH',
    currency: 'CHF',
    direction: 'Buy',
    status: 'Booked',
    region: 'EMEA',
    riskLevel: 'Low',
  },
  {
    id: 6,
    desk: 'Sydney',
    country: 'AU',
    currency: 'AUD',
    direction: 'Sell',
    status: 'Pass',
    region: 'APAC',
    riskLevel: 'Low',
  },
  {
    id: 7,
    desk: 'Toronto',
    country: 'CA',
    currency: 'CAD',
    direction: 'Buy',
    status: 'Fail',
    region: 'AMER',
    riskLevel: 'High',
  },
  {
    id: 8,
    desk: 'Frankfurt',
    country: 'DE',
    currency: 'IRD',
    direction: 'Sell',
    status: 'Warn',
    region: 'LATAM',
    riskLevel: 'Medium',
  },
  {
    id: 9,
    desk: 'Rome FX',
    country: 'IT',
    currency: 'EUR',
    direction: 'Sell',
    status: 'Warn',
    region: 'EMEA',
    riskLevel: 'High',
  },
];
```

#### Trend

Use **Trend** for direction columns (`Buy` / `Sell` map to up / down arrows).

**Example: Icon Style: Trend**

Buy and Sell arrows from the Trend preset

- **Direction** — `Preset: 'Trend'` (`Buy` → ⬆, `Sell` → ⬇)
- Arrow **Description** after the glyph; tooltip shows the raw cell value

Demo project (Vanilla); the files without a marker are shown below:

```text
src/
  adaptableOptions.ts
  agGridModules.ts     [template]
  columnDefs.ts
  gridOptions.ts       [template]
  index.ts             [template]
  onAdaptableReady.ts  [template]
  rowData.ts
  styles.css           [template]
index.html             [template]
package.json           [template]
tsconfig.json          [template]
```

Files marked `[template]` are the same in every demo; see the [demo template](https://www.adaptabletools.com/llms/demo-template.md#vanilla).

**`src/adaptableOptions.ts`**

```ts
import {AdaptableOptions} from '@adaptabletools/adaptable';
import {TradeDesk} from './rowData';

export const adaptableOptions: AdaptableOptions<TradeDesk> = {
  primaryKey: 'id',
  adaptableId: 'Icon Style Trend',
  initialState: {
    Dashboard: {
      ModuleButtons: ['StyledColumn'],
    },
    Theme: {CurrentTheme: 'dark'},
    Layout: {
      CurrentLayout: 'Standard Layout',
      Layouts: [
        {
          Name: 'Standard Layout',
          TableColumns: ['desk', 'direction', 'currency'],
          AutoSizeColumns: true,
        },
      ],
    },
    StyledColumn: {
      StyledColumns: [
        {
          ColumnId: 'direction',
          Name: 'Trade direction',
          IconStyle: {
            Preset: 'Trend',
            CellTextProperties: {
              CellText: ['IconDescription'],
              CellTextPosition: 'After',
            },
            ToolTipText: ['CellValue'],
            Size: 22,
            Gap: 6,
          },
        },
      ],
    },
  },
};
```

**`src/columnDefs.ts`**

```ts
import {ColDef} from 'ag-grid-enterprise';
import {TradeDesk} from './rowData';

export const columnDefs: ColDef<TradeDesk>[] = [
  {field: 'id', hide: true, cellDataType: 'number'},
  {field: 'desk', headerName: 'Desk', cellDataType: 'text'},
  {field: 'direction', headerName: 'Direction', cellDataType: 'text'},
  {field: 'currency', headerName: 'Currency', cellDataType: 'text'},
];
```

**`src/rowData.ts`**

```ts
export interface TradeDesk {
  id: number;
  desk: string;
  country: string;
  currency: string;
  direction: 'Buy' | 'Sell';
  status: string;
  region: string;
  riskLevel: 'High' | 'Medium' | 'Low';
}

export const rowData: TradeDesk[] = [
  {
    id: 1,
    desk: 'NY FX',
    country: 'US',
    currency: 'USD',
    direction: 'Buy',
    status: 'Completed',
    region: 'AMER',
    riskLevel: 'Low',
  },
  {
    id: 2,
    desk: 'London Rates',
    country: 'United Kingdom',
    currency: 'gbp',
    direction: 'Sell',
    status: 'Pending',
    region: 'EMEA',
    riskLevel: 'Medium',
  },
  {
    id: 3,
    desk: 'Tokyo Equity',
    country: 'JP',
    currency: 'JPY',
    direction: 'Buy',
    status: 'Rejected',
    region: 'APAC',
    riskLevel: 'High',
  },
  {
    id: 4,
    desk: 'Paris Credit',
    country: 'France',
    currency: 'EUR',
    direction: 'Sell',
    status: 'In Progress',
    region: 'EMEA',
    riskLevel: 'Medium',
  },
  {
    id: 5,
    desk: 'Zurich PM',
    country: 'CH',
    currency: 'CHF',
    direction: 'Buy',
    status: 'Booked',
    region: 'EMEA',
    riskLevel: 'Low',
  },
  {
    id: 6,
    desk: 'Sydney',
    country: 'AU',
    currency: 'AUD',
    direction: 'Sell',
    status: 'Pass',
    region: 'APAC',
    riskLevel: 'Low',
  },
  {
    id: 7,
    desk: 'Toronto',
    country: 'CA',
    currency: 'CAD',
    direction: 'Buy',
    status: 'Fail',
    region: 'AMER',
    riskLevel: 'High',
  },
  {
    id: 8,
    desk: 'Frankfurt',
    country: 'DE',
    currency: 'IRD',
    direction: 'Sell',
    status: 'Warn',
    region: 'LATAM',
    riskLevel: 'Medium',
  },
];
```

#### Status

Use **Status** for traffic-light style pass / warn / fail values (and common workflow synonyms).

**Example: Icon Style: Status**

Traffic-light preset on a status column

- **Status** — `Preset: 'Status'` (`Pass`, `Warn`, `Fail`, `Completed`, `Pending`, etc.)
- **Cell Value** after the icon; **`ShowText`** for values outside the preset

Demo project (Vanilla); the files without a marker are shown below:

```text
src/
  adaptableOptions.ts
  agGridModules.ts     [template]
  columnDefs.ts
  gridOptions.ts       [template]
  index.ts             [template]
  onAdaptableReady.ts  [template]
  rowData.ts
  styles.css           [template]
index.html             [template]
package.json           [template]
tsconfig.json          [template]
```

Files marked `[template]` are the same in every demo; see the [demo template](https://www.adaptabletools.com/llms/demo-template.md#vanilla).

**`src/adaptableOptions.ts`**

```ts
import {AdaptableOptions} from '@adaptabletools/adaptable';
import {TradeDesk} from './rowData';

export const adaptableOptions: AdaptableOptions<TradeDesk> = {
  primaryKey: 'id',
  adaptableId: 'Icon Style Status',
  initialState: {
    Dashboard: {
      ModuleButtons: ['StyledColumn'],
    },
    Theme: {CurrentTheme: 'dark'},
    Layout: {
      CurrentLayout: 'Standard Layout',
      Layouts: [
        {
          Name: 'Standard Layout',
          TableColumns: ['desk', 'status', 'currency'],
          AutoSizeColumns: true,
        },
      ],
    },
    StyledColumn: {
      StyledColumns: [
        {
          ColumnId: 'status',
          Name: 'Workflow status',
          IconStyle: {
            Preset: 'Status',
            MatchMode: 'CaseInsensitive',
            CellTextProperties: {
              CellText: ['CellValue'],
              CellTextPosition: 'After',
            },
            ToolTipText: ['IconDescription'],
            Size: 16,
            Gap: 6,
            FallbackProperties: { Mode: 'ShowText' },
          },
        },
      ],
    },
  },
};
```

**`src/columnDefs.ts`**

```ts
import {ColDef} from 'ag-grid-enterprise';
import {TradeDesk} from './rowData';

export const columnDefs: ColDef<TradeDesk>[] = [
  {field: 'id', hide: true, cellDataType: 'number'},
  {field: 'desk', headerName: 'Desk', cellDataType: 'text'},
  {field: 'status', headerName: 'Status', cellDataType: 'text'},
  {field: 'currency', headerName: 'Currency', cellDataType: 'text'},
];
```

**`src/rowData.ts`**

```ts
export interface TradeDesk {
  id: number;
  desk: string;
  country: string;
  currency: string;
  direction: 'Buy' | 'Sell';
  status: string;
  region: string;
  riskLevel: 'High' | 'Medium' | 'Low';
}

export const rowData: TradeDesk[] = [
  {
    id: 1,
    desk: 'NY FX',
    country: 'US',
    currency: 'USD',
    direction: 'Buy',
    status: 'Completed',
    region: 'AMER',
    riskLevel: 'Low',
  },
  {
    id: 2,
    desk: 'London Rates',
    country: 'United Kingdom',
    currency: 'gbp',
    direction: 'Sell',
    status: 'Pending',
    region: 'EMEA',
    riskLevel: 'Medium',
  },
  {
    id: 3,
    desk: 'Tokyo Equity',
    country: 'JP',
    currency: 'JPY',
    direction: 'Buy',
    status: 'Rejected',
    region: 'APAC',
    riskLevel: 'High',
  },
  {
    id: 4,
    desk: 'Paris Credit',
    country: 'France',
    currency: 'EUR',
    direction: 'Sell',
    status: 'In Progress',
    region: 'EMEA',
    riskLevel: 'Medium',
  },
  {
    id: 5,
    desk: 'Zurich PM',
    country: 'CH',
    currency: 'CHF',
    direction: 'Buy',
    status: 'Booked',
    region: 'EMEA',
    riskLevel: 'Low',
  },
  {
    id: 6,
    desk: 'Sydney',
    country: 'AU',
    currency: 'AUD',
    direction: 'Sell',
    status: 'Pass',
    region: 'APAC',
    riskLevel: 'Low',
  },
  {
    id: 7,
    desk: 'Toronto',
    country: 'CA',
    currency: 'CAD',
    direction: 'Buy',
    status: 'Fail',
    region: 'AMER',
    riskLevel: 'High',
  },
  {
    id: 8,
    desk: 'Frankfurt',
    country: 'DE',
    currency: 'IRD',
    direction: 'Sell',
    status: 'Warn',
    region: 'LATAM',
    riskLevel: 'Medium',
  },
];
```

- Presets are resolved **at runtime** — supplying `Preset` alone is enough to get a working icon column
- You do not need to mirror the preset entries into `Mappings`

### Custom Mappings

If required, additional, Custom Mappings can be provided - by both developers and end users.

This is useful when you have mappings the preset doesn't ship, (e.g. an obscure currency code, or internal status value)

These Custom Mappings are then **layered on top** of the preset (if one is provided), which means you can:

- **Add** entries the preset does not ship (e.g. an internal status value), or
- **Override** a preset entry by re-using its `Key`

At runtime AdapTable merges preset and custom mappings.

This ensures that both sets of Mappings are available when rendering the Column.

The **Currencies** demo above shows preset + override; the demo below uses **custom mappings only** (no preset).

**Example: Icon Style: Custom Mappings**

Hand-built key → icon rows

- **Status** — emoji mappings only (no preset): Completed / Pending / Rejected etc.
- Same pattern as the trade demo; **`ShowText`** when a value has no mapping

Demo project (Vanilla); the files without a marker are shown below:

```text
src/
  adaptableOptions.ts
  agGridModules.ts     [template]
  columnDefs.ts
  gridOptions.ts       [template]
  index.ts             [template]
  onAdaptableReady.ts  [template]
  rowData.ts
  styles.css           [template]
index.html             [template]
package.json           [template]
tsconfig.json          [template]
```

Files marked `[template]` are the same in every demo; see the [demo template](https://www.adaptabletools.com/llms/demo-template.md#vanilla).

**`src/adaptableOptions.ts`**

```ts
import {AdaptableOptions} from '@adaptabletools/adaptable';
import {TradeDesk} from './rowData';

export const adaptableOptions: AdaptableOptions<TradeDesk> = {
  primaryKey: 'id',
  adaptableId: 'Icon Style Custom Mappings',
  initialState: {
    Dashboard: {
      ModuleButtons: ['StyledColumn'],
    },
    Theme: {CurrentTheme: 'dark'},
    Layout: {
      CurrentLayout: 'Standard Layout',
      Layouts: [
        {
          Name: 'Standard Layout',
          TableColumns: ['desk', 'status'],
          AutoSizeColumns: true,
        },
      ],
    },
    StyledColumn: {
      StyledColumns: [
        {
          ColumnId: 'status',
          Name: 'Desk status icons',
          IconStyle: {
            MatchMode: 'CaseInsensitive',
            Mappings: [
              {Key: 'Completed', Icon: '🟢', Description: 'Completed'},
              {Key: 'Booked', Icon: '🟢', Description: 'Booked'},
              {Key: 'Pending', Icon: '🟡', Description: 'Pending'},
              {Key: 'In Progress', Icon: '🟡', Description: 'In Progress'},
              {Key: 'Rejected', Icon: '🔴', Description: 'Rejected'},
            ],
            CellTextProperties: {
              CellText: ['CellValue'],
              CellTextPosition: 'After',
            },
            ToolTipText: ['CellValue', 'IconDescription'],
            Size: 16,
            Gap: 6,
            FallbackProperties: { Mode: 'ShowText' },
          },
        },
      ],
    },
  },
};
```

**`src/columnDefs.ts`**

```ts
import {ColDef} from 'ag-grid-enterprise';
import {TradeDesk} from './rowData';

export const columnDefs: ColDef<TradeDesk>[] = [
  {field: 'id', hide: true, cellDataType: 'number'},
  {field: 'desk', headerName: 'Desk', cellDataType: 'text'},
  {field: 'status', headerName: 'Status', cellDataType: 'text'},
];
```

**`src/rowData.ts`**

```ts
export interface TradeDesk {
  id: number;
  desk: string;
  country: string;
  currency: string;
  direction: 'Buy' | 'Sell';
  status: string;
  region: string;
  riskLevel: 'High' | 'Medium' | 'Low';
}

export const rowData: TradeDesk[] = [
  {
    id: 1,
    desk: 'NY FX',
    country: 'US',
    currency: 'USD',
    direction: 'Buy',
    status: 'Completed',
    region: 'AMER',
    riskLevel: 'Low',
  },
  {
    id: 2,
    desk: 'London Rates',
    country: 'United Kingdom',
    currency: 'gbp',
    direction: 'Sell',
    status: 'Pending',
    region: 'EMEA',
    riskLevel: 'Medium',
  },
  {
    id: 3,
    desk: 'Tokyo Equity',
    country: 'JP',
    currency: 'JPY',
    direction: 'Buy',
    status: 'Rejected',
    region: 'APAC',
    riskLevel: 'High',
  },
  {
    id: 4,
    desk: 'Paris Credit',
    country: 'France',
    currency: 'EUR',
    direction: 'Sell',
    status: 'In Progress',
    region: 'EMEA',
    riskLevel: 'Medium',
  },
  {
    id: 5,
    desk: 'Zurich PM',
    country: 'CH',
    currency: 'CHF',
    direction: 'Buy',
    status: 'Booked',
    region: 'EMEA',
    riskLevel: 'Low',
  },
  {
    id: 6,
    desk: 'Sydney',
    country: 'AU',
    currency: 'AUD',
    direction: 'Sell',
    status: 'Pass',
    region: 'APAC',
    riskLevel: 'Low',
  },
  {
    id: 7,
    desk: 'Toronto',
    country: 'CA',
    currency: 'CAD',
    direction: 'Buy',
    status: 'Fail',
    region: 'AMER',
    riskLevel: 'High',
  },
  {
    id: 8,
    desk: 'Frankfurt',
    country: 'DE',
    currency: 'IRD',
    direction: 'Sell',
    status: 'Warn',
    region: 'LATAM',
    riskLevel: 'Medium',
  },
];
```

Custom keys **replace** matching preset keys so if you provide a key of the same name as a preset entry, that will be used

### Match Mode

Icon Style supports case **sensitivity** matching via the `MatchMode` property.

This controls how `Key` is compared with the cell value and can be one of two values:

- `Exact` (default) — strict equality for numbers, booleans and strings
- `CaseInsensitive` — string cell values are matched with **case-insensitive string keys**; **number / boolean** mapping keys are compared **textually** to the string cell value (e.g. `Key: 1` can match the string `'1'`).

`'CaseInsensitive'` is useful for free-typed columns where the same logical value can appear as `'GBP'` or `'gbp'`

- The `Flags` and `Status` presets default to `'CaseInsensitive'` in the Styled Column wizard
- This is because they include both code (`'GB'`) and name (`'United Kingdom'`) synonyms

### Fallback Behaviour

AdapTable allows to configure what to render when **no mapping matches** the cell value.

This is done using `FallbackProperties` object, which has 2 properties:

- `Mode` — what to render when no mapping matches the cell value (`'Hide'`, `'ShowText'` or `'Icon'`)
- `Icon` — the icon to render when `Mode: 'Icon'` (emoji, an `AdaptableIcon` or URL)

The 3 values that `Mode` can take are:

| Mode               | Behaviour                                              |
| ------------------ | ------------------------------------------------------ |
| `'Hide'` (default) | Render nothing.                                        |
| `'ShowText'`       | Render the raw (formatted) cell value as plain text.   |
| `'Icon'`           | Render `FallbackProperties.Icon` (string or icon spec) |

- Fallback is independent of `CellTextProperties.CellText` - when no mapping matches, the Fallback decision wins
- Empty cells (`null` / `undefined`) always render nothing, regardless of `FallbackProperties.Mode`

**Example: Icon Style: Fallback**

Hide, raw text, or fallback icon on miss

- This example contains 3 Regions which are not in the Flags preset (`AMER`, `EMEA`, `LATAM`) and each  fallback option is shown:
  - **Region (hide)** — `FallbackProperties: { Mode: 'Hide' }` (empty cell when unmatched)
  - **Region (text)** — `FallbackProperties: { Mode: 'ShowText' }` (raw value, e.g. **LATAM**)
  - **Region (icon)** — `FallbackProperties: { Mode: 'Icon', Icon: '❓' }` (renders **❓** when unmatched)

Demo project (Vanilla); the files without a marker are shown below:

```text
src/
  adaptableOptions.ts
  agGridModules.ts     [template]
  columnDefs.ts
  gridOptions.ts       [template]
  index.ts             [template]
  onAdaptableReady.ts  [template]
  rowData.ts
  styles.css           [template]
index.html             [template]
package.json           [template]
tsconfig.json          [template]
```

Files marked `[template]` are the same in every demo; see the [demo template](https://www.adaptabletools.com/llms/demo-template.md#vanilla).

**`src/adaptableOptions.ts`**

```ts
import {AdaptableOptions} from '@adaptabletools/adaptable';
import {TradeDesk} from './rowData';

export const adaptableOptions: AdaptableOptions<TradeDesk> = {
  primaryKey: 'id',
  adaptableId: 'Icon Style Fallback',
  initialState: {
    Dashboard: {
      ModuleButtons: ['StyledColumn'],
    },
    Theme: {CurrentTheme: 'dark'},
    Layout: {
      CurrentLayout: 'Standard Layout',
      Layouts: [
        {
          Name: 'Standard Layout',
          TableColumns: ['desk', 'region', 'region_hide', 'region_text', 'region_icon'],
          AutoSizeColumns: true,
        },
      ],
    },
    StyledColumn: {
      StyledColumns: [
        {
          ColumnId: 'region_hide',
          Name: 'Region hide fallback',
          IconStyle: {
            Preset: 'Flags',
            FallbackProperties: { Mode: 'Hide' },
            Size: 20,
          },
        },
        {
          ColumnId: 'region_text',
          Name: 'Region show text fallback',
          IconStyle: {
            Preset: 'Flags',
            FallbackProperties: { Mode: 'ShowText' },
            Size: 20,
          },
        },
        {
          ColumnId: 'region_icon',
          Name: 'Region fallback icon',
          IconStyle: {
            Preset: 'Flags',
            FallbackProperties: { Mode: 'Icon', Icon: '❓' },
            Size: 20,
          },
        },
      ],
    },
  },
};
```

**`src/columnDefs.ts`**

```ts
import {ColDef} from 'ag-grid-enterprise';
import {TradeDesk} from './rowData';

export const columnDefs: ColDef<TradeDesk>[] = [
  {field: 'id', hide: true, cellDataType: 'number'},
  {field: 'desk', headerName: 'Desk', cellDataType: 'text'},
  {
    field: 'region',
    headerName: 'Region',
    cellDataType: 'text',
  },
  {
    colId: 'region_hide',
    headerName: 'Region (hide)',
    cellDataType: 'text',
    valueGetter: params => params.data?.region,
  },
  {
    colId: 'region_text',
    headerName: 'Region (text)',
    cellDataType: 'text',
    valueGetter: params => params.data?.region,
  },
  {
    colId: 'region_icon',
    headerName: 'Region (icon)',
    cellDataType: 'text',
    valueGetter: params => params.data?.region,
  },
];
```

**`src/rowData.ts`**

```ts
export interface TradeDesk {
  id: number;
  desk: string;
  country: string;
  currency: string;
  direction: 'Buy' | 'Sell';
  status: string;
  region: string;
  riskLevel: 'High' | 'Medium' | 'Low';
}

export const rowData: TradeDesk[] = [
  {
    id: 1,
    desk: 'NY FX',
    country: 'US',
    currency: 'USD',
    direction: 'Buy',
    status: 'Completed',
    region: 'AMER',
    riskLevel: 'Low',
  },
  {
    id: 2,
    desk: 'London Rates',
    country: 'United Kingdom',
    currency: 'gbp',
    direction: 'Sell',
    status: 'Pending',
    region: 'EMEA',
    riskLevel: 'Medium',
  },
  {
    id: 3,
    desk: 'Tokyo Equity',
    country: 'JP',
    currency: 'JPY',
    direction: 'Buy',
    status: 'Rejected',
    region: 'APAC',
    riskLevel: 'High',
  },
  {
    id: 4,
    desk: 'Paris Credit',
    country: 'France',
    currency: 'EUR',
    direction: 'Sell',
    status: 'In Progress',
    region: 'EMEA',
    riskLevel: 'Medium',
  },
  {
    id: 5,
    desk: 'Zurich PM',
    country: 'CH',
    currency: 'CHF',
    direction: 'Buy',
    status: 'Booked',
    region: 'EMEA',
    riskLevel: 'Low',
  },
  {
    id: 6,
    desk: 'Sydney',
    country: 'AU',
    currency: 'AUD',
    direction: 'Sell',
    status: 'Pass',
    region: 'APAC',
    riskLevel: 'Low',
  },
  {
    id: 7,
    desk: 'Toronto',
    country: 'CA',
    currency: 'CAD',
    direction: 'Buy',
    status: 'Fail',
    region: 'AMER',
    riskLevel: 'High',
  },
  {
    id: 8,
    desk: 'Frankfurt',
    country: 'DE',
    currency: 'IRD',
    direction: 'Sell',
    status: 'Warn',
    region: 'LATAM',
    riskLevel: 'Medium',
  },
];
```

## Row Scope

Users can decide which kinds of Rows will include the Icon Style.

See  [Styled Column Row Scope](https://www.adaptabletools.com/docs/handbook-styled-column-overview/index.md#row-scope) for details of the types of Rows which can be included / excluded from a Styled Column

- If the current row is **excluded** (e.g. no Group rows) but the cell has a value, the Grid shows that value as plain text
- i.e. we do not use the Icon renderer, nor `FallbackProperties` nor any Format styling for that path

## Styling the Cell

There are various configurable properties available allowing you full control of the look and feel of each cell in an Icon Styled Column.

### Cell Text

Users can elect to display companion text alongside a matched Icon (e.g. "🇺🇸 US" or "USD 🇺🇸").

This is configured through the `CellTextProperties` group, which has 2 properties:

- `CellText` — either a formatted `CellValue` or the key's `IconDescription`
- `CellTextPosition` — where the text sits relative to the icon

### Cell Position

`CellTextProperties.CellTextPosition` controls where the text sits in the Cell.

The available values are: `'Before'`, `'After'` (default), `'Above'`, `'Below'`.

- It is possible to enable both `CellValue` and `IconDescription` in `CellTextProperties.CellText`
- When this happens, companion text parts are joined with **` · `** (middle dot with spaces)

### Tooltip

A tooltip can be enabled in the cell using the `ToolTipText` property.

This works similarly to Cells, allowing you to render either the Cell Value or Description in the Tooltip.

The only difference with Cell is that the Tooltip shows the **raw** (not formatted) value of the Cell

- The `CellTextProperties` object allows a richness of rendering possibilities; some common patterns include:
  - **Flag + ISO code** — `{ CellText: ['CellValue'], CellTextPosition: 'After' }`
  - **Flag + country name** — `{ CellText: ['IconDescription'], CellTextPosition: 'After' }`
  - **Compact icon, full description on hover** — `CellTextProperties` unset and `ToolTipText: ['IconDescription']`

**Example: Icon Style: Companion Text**

Flag + code vs flag + country name

- **Country (code)** — `CellTextProperties.CellText: ['CellValue']` after the flag (e.g. **US**, **France**)
- **Country (name)** — `CellTextProperties.CellText: ['IconDescription']` after the flag (e.g. **United States**); tooltip shows description only

Demo project (Vanilla); the files without a marker are shown below:

```text
src/
  adaptableOptions.ts
  agGridModules.ts     [template]
  columnDefs.ts
  gridOptions.ts       [template]
  index.ts             [template]
  onAdaptableReady.ts  [template]
  rowData.ts
  styles.css           [template]
index.html             [template]
package.json           [template]
tsconfig.json          [template]
```

Files marked `[template]` are the same in every demo; see the [demo template](https://www.adaptabletools.com/llms/demo-template.md#vanilla).

**`src/adaptableOptions.ts`**

```ts
import {AdaptableOptions} from '@adaptabletools/adaptable';
import {TradeDesk} from './rowData';

export const adaptableOptions: AdaptableOptions<TradeDesk> = {
  primaryKey: 'id',
  adaptableId: 'Icon Style Companion Text',
  initialState: {
    Dashboard: {
      ModuleButtons: ['StyledColumn'],
    },
    Theme: {CurrentTheme: 'dark'},
    Layout: {
      CurrentLayout: 'Standard Layout',
      Layouts: [
        {
          Name: 'Standard Layout',
          TableColumns: ['desk', 'country_code', 'country_name'],
          AutoSizeColumns: true,
        },
      ],
    },
    StyledColumn: {
      StyledColumns: [
        {
          ColumnId: 'country_code',
          Name: 'Flag + ISO / code',
          IconStyle: {
            Preset: 'Flags',
            MatchMode: 'CaseInsensitive',
            CellTextProperties: {
              CellText: ['CellValue'],
              CellTextPosition: 'After',
            },
            Size: 20,
            Gap: 6,
          },
        },
        {
          ColumnId: 'country_name',
          Name: 'Flag + country name',
          IconStyle: {
            Preset: 'Flags',
            MatchMode: 'CaseInsensitive',
            CellTextProperties: {
              CellText: ['IconDescription'],
              CellTextPosition: 'After',
            },
            ToolTipText: ['IconDescription'],
            Size: 20,
            Gap: 6,
          },
        },
      ],
    },
  },
};
```

**`src/columnDefs.ts`**

```ts
import {ColDef} from 'ag-grid-enterprise';
import {TradeDesk} from './rowData';

export const columnDefs: ColDef<TradeDesk>[] = [
  {field: 'id', hide: true, cellDataType: 'number'},
  {field: 'desk', headerName: 'Desk', cellDataType: 'text'},
  {
    colId: 'country_code',
    headerName: 'Country (code)',
    cellDataType: 'text',
    valueGetter: params => params.data?.country,
  },
  {
    colId: 'country_name',
    headerName: 'Country (name)',
    cellDataType: 'text',
    valueGetter: params => params.data?.country,
  },
];
```

**`src/rowData.ts`**

```ts
export interface TradeDesk {
  id: number;
  desk: string;
  country: string;
  currency: string;
  direction: 'Buy' | 'Sell';
  status: string;
  region: string;
  riskLevel: 'High' | 'Medium' | 'Low';
}

export const rowData: TradeDesk[] = [
  {
    id: 1,
    desk: 'NY FX',
    country: 'US',
    currency: 'USD',
    direction: 'Buy',
    status: 'Completed',
    region: 'AMER',
    riskLevel: 'Low',
  },
  {
    id: 2,
    desk: 'London Rates',
    country: 'United Kingdom',
    currency: 'gbp',
    direction: 'Sell',
    status: 'Pending',
    region: 'EMEA',
    riskLevel: 'Medium',
  },
  {
    id: 3,
    desk: 'Tokyo Equity',
    country: 'JP',
    currency: 'JPY',
    direction: 'Buy',
    status: 'Rejected',
    region: 'APAC',
    riskLevel: 'High',
  },
  {
    id: 4,
    desk: 'Paris Credit',
    country: 'France',
    currency: 'EUR',
    direction: 'Sell',
    status: 'In Progress',
    region: 'EMEA',
    riskLevel: 'Medium',
  },
  {
    id: 5,
    desk: 'Zurich PM',
    country: 'CH',
    currency: 'CHF',
    direction: 'Buy',
    status: 'Booked',
    region: 'EMEA',
    riskLevel: 'Low',
  },
  {
    id: 6,
    desk: 'Sydney',
    country: 'AU',
    currency: 'AUD',
    direction: 'Sell',
    status: 'Pass',
    region: 'APAC',
    riskLevel: 'Low',
  },
  {
    id: 7,
    desk: 'Toronto',
    country: 'CA',
    currency: 'CAD',
    direction: 'Buy',
    status: 'Fail',
    region: 'AMER',
    riskLevel: 'High',
  },
  {
    id: 8,
    desk: 'Frankfurt',
    country: 'DE',
    currency: 'IRD',
    direction: 'Sell',
    status: 'Warn',
    region: 'LATAM',
    riskLevel: 'Medium',
  },
];
```

Besides emoji and image URLs, each mapping's `Icon` can reference AdapTable's bundled **system icons**.

This is doing using `{ name: '…' }` and are the same names as elsewhere in the product (e.g. `alert`, `check`)

**Example: Icon Style: System Icons**

Bundled AdapTable icons instead of emoji

- **Risk Level** — `Icon: { name: 'alert' | 'warning' | 'check' }` per **High** / **Medium** / **Low**
- **Description** after the icon; tooltip shows value and description

Demo project (Vanilla); the files without a marker are shown below:

```text
src/
  adaptableOptions.ts
  agGridModules.ts     [template]
  columnDefs.ts
  gridOptions.ts       [template]
  index.ts             [template]
  onAdaptableReady.ts  [template]
  rowData.ts
  styles.css           [template]
index.html             [template]
package.json           [template]
tsconfig.json          [template]
```

Files marked `[template]` are the same in every demo; see the [demo template](https://www.adaptabletools.com/llms/demo-template.md#vanilla).

**`src/adaptableOptions.ts`**

```ts
import {AdaptableOptions} from '@adaptabletools/adaptable';
import {TradeDesk} from './rowData';

export const adaptableOptions: AdaptableOptions<TradeDesk> = {
  primaryKey: 'id',
  adaptableId: 'Icon Style System Icons',
  initialState: {
    Dashboard: {
      ModuleButtons: ['StyledColumn'],
    },
    Theme: {CurrentTheme: 'dark'},
    Layout: {
      CurrentLayout: 'Standard Layout',
      Layouts: [
        {
          Name: 'Standard Layout',
          TableColumns: ['desk', 'riskLevel', 'currency'],
          AutoSizeColumns: true,
        },
      ],
    },
    StyledColumn: {
      StyledColumns: [
        {
          ColumnId: 'riskLevel',
          Name: 'Risk system icons',
          IconStyle: {
            Mappings: [
              {Key: 'High', Icon: {name: 'alert'}, Description: 'High risk'},
              {Key: 'Medium', Icon: {name: 'warning'}, Description: 'Medium risk'},
              {Key: 'Low', Icon: {name: 'check'}, Description: 'Low risk'},
            ],
            CellTextProperties: {
              CellText: ['IconDescription'],
              CellTextPosition: 'After',
            },
            ToolTipText: ['CellValue', 'IconDescription'],
            Size: 20,
            Gap: 6,
          },
        },
      ],
    },
  },
};
```

**`src/columnDefs.ts`**

```ts
import {ColDef} from 'ag-grid-enterprise';
import {TradeDesk} from './rowData';

export const columnDefs: ColDef<TradeDesk>[] = [
  {field: 'id', hide: true, cellDataType: 'number'},
  {field: 'desk', headerName: 'Desk', cellDataType: 'text'},
  {field: 'riskLevel', headerName: 'Risk Level', cellDataType: 'text'},
  {field: 'currency', headerName: 'Currency', cellDataType: 'text'},
];
```

**`src/rowData.ts`**

```ts
export interface TradeDesk {
  id: number;
  desk: string;
  country: string;
  currency: string;
  direction: 'Buy' | 'Sell';
  status: string;
  region: string;
  riskLevel: 'High' | 'Medium' | 'Low';
}

export const rowData: TradeDesk[] = [
  {
    id: 1,
    desk: 'NY FX',
    country: 'US',
    currency: 'USD',
    direction: 'Buy',
    status: 'Completed',
    region: 'AMER',
    riskLevel: 'Low',
  },
  {
    id: 2,
    desk: 'London Rates',
    country: 'United Kingdom',
    currency: 'gbp',
    direction: 'Sell',
    status: 'Pending',
    region: 'EMEA',
    riskLevel: 'Medium',
  },
  {
    id: 3,
    desk: 'Tokyo Equity',
    country: 'JP',
    currency: 'JPY',
    direction: 'Buy',
    status: 'Rejected',
    region: 'APAC',
    riskLevel: 'High',
  },
  {
    id: 4,
    desk: 'Paris Credit',
    country: 'France',
    currency: 'EUR',
    direction: 'Sell',
    status: 'In Progress',
    region: 'EMEA',
    riskLevel: 'Medium',
  },
  {
    id: 5,
    desk: 'Zurich PM',
    country: 'CH',
    currency: 'CHF',
    direction: 'Buy',
    status: 'Booked',
    region: 'EMEA',
    riskLevel: 'Low',
  },
  {
    id: 6,
    desk: 'Sydney',
    country: 'AU',
    currency: 'AUD',
    direction: 'Sell',
    status: 'Pass',
    region: 'APAC',
    riskLevel: 'Low',
  },
  {
    id: 7,
    desk: 'Toronto',
    country: 'CA',
    currency: 'CAD',
    direction: 'Buy',
    status: 'Fail',
    region: 'AMER',
    riskLevel: 'High',
  },
  {
    id: 8,
    desk: 'Frankfurt',
    country: 'DE',
    currency: 'IRD',
    direction: 'Sell',
    status: 'Warn',
    region: 'LATAM',
    riskLevel: 'Medium',
  },
];
```

### Icon Sizing

There are 2 useful properties available for configuring Icon Sizing.

These can be used to set the size and gap of the Icon in the Icon Style:

| Property | Default | Description                                       |
| -------- | ------- | ------------------------------------------------- |
| `Size`   | `18`    | Pixel size of the icon glyph (square)             |
| `Gap`    | `4`     | Pixel gap between the icon and the companion text |

- When setting `Size`, emojis and inline strings scale via `font-size`
- System / URL icons are calculated as: width = height = `Size`

### Style Precedence with Format Columns

The Icon Style objects contains 2 main (optional) sets of properties:

- `Font` - deals with companion text styling, e.g. colour, weight, alignment etc.
- `Cell` - deals with the cell behind the icon e.g. background, border, border-radius etc.

Both slices, when set, **take precedence** over any matching [Format Column](https://www.adaptabletools.com/docs/handbook-column-formatting/index.md) for the same properties.

Anything left unset still inherits normally.

## Defining Icon Styles

Icon Styles are defined as part of the Styled Column Initial State.

### Providing a Icon Style in Styled Column State

- Supply a unique **`Name`** and **`ColumnId`** for the Styled Column
- Add an `IconStyle` object
- Optional: **`IsSuspended: true`** on the Styled Column suspends this style **without deleting** it (column reverts to normal cell rendering)

- `Preset` seeds the renderer with a shipped set of mappings at runtime
- `Mappings` adds custom entries (or overrides preset entries by re-using the `Key`)

- `MatchMode` — `'Exact'` (default) or `'CaseInsensitive'`
- `FallbackProperties` — `Mode: 'Hide'` (default), `'ShowText'`, or `'Icon'` (with `FallbackProperties.Icon`)

- `CellTextProperties.CellText` — `'CellValue'` and/or `'IconDescription'`
- `CellTextProperties.CellTextPosition` — `'Before'`, `'After'` (default), `'Above'`, `'Below'`
- `ToolTipText` — same tokens as `CellTextProperties.CellText`

- `Size`, `Gap` for layout
- `Font` for text appearance, `Cell` for cell box (background / border / radius)

```js [[1, 6, "ColumnId"], [1, 7, "IconStyle"], [2, 8, "Preset"], [2, 9, "Mappings"], [3, 21, "MatchMode"], [3, 22, "FallbackProperties"], [4, 23, "CellTextProperties"], [5, 27, "Size"], [5, 28, "Gap"]]
const initialState: InitialState = {
  StyledColumn: {
    StyledColumns: [
      {
        Name: 'Currency Icons',
        ColumnId: 'currency',
        IconStyle: {
          Preset: 'Currencies',
          Mappings: [
            {
              Key: 'IRD',
              Icon: '🪙',
              Description: 'Internal redemption deposit',
            },
            {
              Key: 'gbp',
              Icon: '💷',
              Description: 'Pound sterling (overridden)',
            },
          ],
          MatchMode: 'CaseInsensitive',
          FallbackProperties: { Mode: 'ShowText' },
          CellTextProperties: {
            CellText: ['IconDescription'],
            CellTextPosition: 'After',
          },
          Size: 18,
          Gap: 6,
        },
      },
    ],
  },
};
```

## Creating Icon Styles

Icon Styles can be created at run-time using the Styled Column UI Wizard.

### Creating an Icon Column Style using the Styled Column Wizard

The Wizard guides you through the following steps:

In the **Settings** step:

- Enter a **Name** for the Styled Column (must be unique within the Grid)
- Pick **Icon** from the list of Styled Column Types (shown in the summary as **Icon**)

The **Scope** step is shared by every Styled Column. Use it to:

- Pick the **Column** whose cell values will be looked up — any column whose values you can treat as discrete keys (strings, numbers, booleans, etc.)
- Choose which **row kinds** the icons render on: **Data**, **Group**, **Summary** and **Total**.

By default **Data**, **Summary** and **Total** are included, and **Group** rows are excluded. On **excluded** row kinds with a value, the cell shows plain text — see [Row Scope](#row-scope).

The **Mappings** step has three card sections:

- **Presets** — press one of **Flags**, **Currencies**, **Trend** or **Status** to attach that built-in mapping set at runtime. **Clear preset** removes the preset while keeping your **Custom mappings**. The card shows how many mappings ship with the preset and a small preview strip.

- **Custom mappings** — **Add Mapping** appends a row; set **Key** (the cell value to match), **Description** (optional), and **Icon** (click the preview button to open **Edit icon**):
  - Choose **Emoji / text**, **System** (AdapTable icon picker), or **Image URL**
  - **Done** closes the editor

- **Matching** — **Match mode**: **Exact** (`===`) or **Case-insensitive** (strings). **Fallback**: **Show No Value**, **Show Raw Value**, or **Show Fallback Icon**; when the fallback is an icon, use the icon button to pick emoji, system icon, or URL.

- You must **either** select a **preset** **or** add **at least one** custom mapping
- The wizard blocks finishing until one of those is true

The **Style** step configures layout and text around the glyph:

- **Sizing** — **Icon Size (px)** (minimum 8) and **Gap (px)** between icon and companion text

- **Cell Text** — optional checkboxes for **Cell Value** and **Description**; **Position**. When at least one text option is on, the shared **Font** editor styles that companion text (disabled when no text is selected)

- **Tooltip** — same **Cell Value** / **Description** choices for hover; **`Cell Value` in the tooltip** uses the raw value string and may **differ slightly** from the in-cell companion line when the grid applies **value formatting** (see [Cell Text](#cell-text) and [Tooltip](#tooltip)).

- **Cell** — optional cell **box** styling; overrides matching [Format Column](https://www.adaptabletools.com/docs/handbook-column-formatting/index.md) where set.

Two further wizard steps — **Tags** (when the workspace has tags enabled) and **Summary** (a read-only review of every previous step) — are shared by all AdapTable modules and not specific to Icon Columns.

### FAQ

**Do I have to list mappings if I use a Preset?**
No. Presets are resolved at runtime — `Preset` alone is enough. `Mappings` is only needed for additions or overrides.

**Why does my `FallbackProperties: { Mode: 'Hide' }` still render text for unmatched values?**
It should not. `FallbackProperties.Mode` is consulted before `CellTextProperties.CellText`, so an unmatched cell renders exactly what the fallback mode says.

If a value still renders, check that the cell isn't being matched by a stale mapping (e.g. case differences with `MatchMode: 'Exact'`).

**Can the icon be a system icon or a URL rather than an emoji?**
Yes. `Icon` accepts a plain string (emoji or any text glyph) or an `AdaptableIcon` — `{ name: 'flag' }` for a bundled system icon, `{ src: '/img/us.svg' }` for a URL.

**Can I show the icon with the original cell value next to it?**
Yes — set `CellTextProperties: { CellText: ['CellValue'] }` (and add `CellTextPosition` inside `CellTextProperties` if you want it before / above / below the icon).

**Why does case matter for some of my keys but not others?**
`MatchMode` is per-column. `'Exact'` (the default) uses strict equality; `'CaseInsensitive'` lowercases string keys for string cells. The `Flags` and `Status` presets default to case-insensitive because they ship synonyms like `'GB'` and `'United Kingdom'`. For `'CaseInsensitive'` and **non-string** mapping keys, numeric / boolean keys may match string cell values by **string comparison** — see [Match Mode](#match-mode).

**Why do I see plain text on Group (or other) rows instead of icons?**
Those row kinds have likely been excluded when setting [Row scope](#row-scope).
When the Icon renderer does not apply, the cell falls back to **`String(value)`** as plain text — not `FallbackProperties`.

**Can I use Icon Style on an array column for one icon per element?**
No — Icon does a **single** lookup on the whole cell value; array column types are unsupported and not offered in the UI. Use [Badge Style](https://www.adaptabletools.com/docs/handbook-styled-column-badge/index.md) for **per-element** visuals.

**What happens if the Styled Column is suspended?**
When `IsSuspended` is `true`, AdapTable stops using the Icon renderer for that column (as with other Styled Columns).
