# Table

A data-driven table from an array of records, with optional search, filtering, sorting, pagination and custom cell formatters.

**Category:** Components/Graphics/Table

**Import:** `import { Table } from '@reuters-graphics/graphics-components'`

## Props

| Prop | Type | Default | Required | Description |
|------|------|---------|:--------:|-------------|
| `data` | `T[]` | — | ✓ | Data for the table as an array. |
| `title` | `string` | — |  | A title that runs above the table. |
| `dek` | `string` | — |  | A block of text that runs above the table. |
| `notes` | `string` | — |  | A footnote that runs below the table. |
| `source` | `string` | — |  | A source line that runs below the table. |
| `includedFields` | `string[]` | `Object.keys(data[0]).filter((f) => f !== 'searchStr')` |  | List of the fields to include in the table. By default everything goes. |
| `truncated` | `boolean` | `false` |  | Whether or not the table is cutoff after a set number of rows. |
| `truncateLength` | `number` | `5` |  | If the table is truncated, how many rows to allow before the cutoff. |
| `paginated` | `boolean` | `false` |  | Whether or not the table is paginated after a set number of rows. |
| `pageSize` | `number` | `25` |  | The default page size. |
| `searchable` | `boolean` | `false` |  | Whether or not searches are allowed. |
| `searchPlaceholder` | `string` | `'Search in table'` |  | The placeholder text that appears in the search box. |
| `filterField` | `string` | `''` |  | A field to offer uses as an interactive filter. |
| `filterLabel` | `string` | — |  | The label to place above the filter box. |
| `sortable` | `boolean` | `false` |  | Whether or not sorts are allowed. |
| `sortField` | `string` | `Object.keys(data[0])[0]` |  | The column to sort by. By default it's the first header. |
| `sortableFields` | `string[]` | `Object.keys(data[0]).filter((f) => f !== 'searchStr')` |  | The columns that are allowed to sort. It's all of them by default. |
| `sortDirection` | `'ascending' \| 'descending'` | `$bindable('ascending')` |  | The direction of the sort. By default it's ascending. |
| `fieldFormatters` | `FieldFormatters<T>` | — |  | Custom field formatting functions. Should be keyed to the name of the field. |
| `width` | `'normal' \| 'wide' \| 'wider' \| 'widest' \| 'fluid'` | `'normal'` |  | Width of the component within the text well. Options: `normal`, `wide`, `wider`, `widest`, `fluid` |
| `id` | `string` | `''` |  | Add an ID to target with SCSS. |
| `class` | `string` | `''` |  | Add a class to target with SCSS. |

## Examples

### Demo

```svelte
<Table width="normal" data={/* homeRuns */} />
```

### Text elements

```svelte
<Table
  data={/* homeRuns */}
  title="Career home run leaders"
  dek="In baseball, a home run (also known as a "dinger" or "tater") occurs when a batter hits the ball over the outfield fence. When a home run is hit, the batter and any runners on base are able to score."
  notes="Note: As of Opening Day 2023"
  source="Source: Baseball Reference"
/>
```

### Truncated

```svelte
<Table data={/* homeRuns */} truncated={true} source="Source: Baseball Reference" />
```

### Paginated

```svelte
<Table
  data={/* pressFreedom */}
  paginated={true}
  title="Press Freedom Index"
  source="Source: Reporters Without Borders"
/>
```

### Search bar

```svelte
<Table
  data={/* pressFreedom */}
  searchable={true}
  paginated={true}
  searchPlaceholder="Search press freedom data"
  title="Press Freedom Index"
  source="Source: Reporters Without Borders"
/>
```

### Filter

```svelte
<Table
  data={/* pressFreedom */}
  paginated={true}
  filterField="Region"
  filterLabel="regions"
  title="Press Freedom Index"
  notes="Source: Reporters Without Borders"
/>
```

### Search and filter

```svelte
<Table
  data={/* pressFreedom */}
  searchable={true}
  paginated={true}
  filterField="Region"
  filterLabel="regions"
  title="Press Freedom Index"
  dek="Reporters Without Borders ranks countries based on their level of press freedom using criteria such as the degree of media pluralism and violence against journalists."
  source="Source: Reporters Without Borders"
/>
```

### Sort

```svelte
<Table
  data={/* pressFreedom */}
  sortable={true}
  paginated={true}
  sortField="Score"
  sortDirection="descending"
  title="Press Freedom Index"
  notes="Note: data as of 2018"
  source="Source: Reporters Without Borders"
/>
```

### Format

```svelte
<Table
  data={/* richestWomen */}
  fieldFormatters={{
      'Net worth (in billions)': currencyFormat as Formatter<unknown>,
    }}
  sortable={true}
  sortField="Net worth (in billions)"
  sortDirection="descending"
  title="The Richest Women in the World"
  source="Source: Forbes"
/>
```

## Documentation

# Table

The `Table` component presents data as a table that you can make searchable, filtereable, sortable, or paginated.

```svelte
<script>
  import { Table } from '@reuters-graphics/graphics-components';

  import data from './data.json'; // Import your data
</script>

<Table {data} />
```

## Text elements

Set the `title`, `dek`, `notes` and `source` options to add supporting metadata above and below the table.

```svelte
<Table
  data={yourData}
  title="Career home run leaders"
  dek={`In baseball,
a home run (also known as a "dinger" or "tater") occurs when a batter hits the
ball over the outfield fence. When a home run is hit, the batter and any runners
on base are able to score.`}
  notes="Note: As of Opening Day 2023"
  source="Source: Baseball Reference"
/>
```

## Truncated

When your table has 10 or more rows, consider clipping it by setting the `truncated` option. When it is enabled, the table is clipped and readers must click a button below the table to see all rows.

By default, this configuration will limit the table to 5 records. Change the cutoff point by adjusting the `truncateLength` option.

This is a good option for simple tables with between 10 and 30 rows. It works best when the table doesn't require interactivity.

```svelte
<Table data={yourData} truncated={true} source="Source: Baseball Reference" />
```

## Paginated

When your table has many rows, you should consider breaking it up into pages by setting `paginated` to `true`. When it is enabled, readers can leaf through the data using a set of buttons below the table.

By default, there are 25 records per page. Change the number by adjusting the `pageSize` option.

This is a good option when publishing large tables for readers to explore. It works well with interactive features like searching and filters.

```svelte
<Table
  data={yourData}
  paginated={true}
  title="Press Freedom Index"
  source="Reporters Without Borders"
/>
```

## Search bar

Allow users to search the table by setting the optional `searchable` option to `true`. Modify the default text that appears in the box by setting `searchPlaceholder` to a different placeholder text.

```svelte
<Table
  data={yourData}
  searchable={true}
  paginated={true}
  searchPlaceholder="Search press freedom data"
  ,
  title="Press Freedom Index"
  notes="Source: Reporters Without Borders"
/>
```

## Filter

Allow users to filter the table by providing one of the attributes as the `filterField`. This works best with categorical columns.

Set `filterLabel` to make the category name more readable. For example, if the column is `Region`, set `filterLabel` to `regions` or `regions of the world`.

```svelte
<Table
  data={yourData}
  filterField="Region"
  filterLabel="regions"
  paginated={true}
  title="Press Freedom Index"
  notes="Source: Reporters Without Borders"
/>
```

## Search and filter

Feel free to both search and filter.

```svelte
<Table
  data={yourData}
  searchable={true}
  paginated={true}
  filterField="Region"
  filterLabel="regions"
  title="Press Freedom Index"
  dek="Reporters Without Borders ranks countries based on their level of press freedom using criteria such as the degree of media pluralism and violence against journalists."
  source="Source: Reporters Without Borders"
/>
```

````

## Sort

Allow users to sort the table by setting `sortable` to `true`. Specify the starting order by setting `sortField` to a column name and `sortDirection` to `ascending` or `descending`.

By default, all fields are sortable. If you'd like to limit the columns where sorting is allowed, provide a list to the `sortableFields` option.

```svelte
<Table
  data={yourData}
  sortable={true}
  paginated={true}
  sortField="Score"
  sortDirection="descending"
  title="Press Freedom Index"
  source="Source: Reporters Without Borders"
/>
````

## Format

Format column values by supplying functions keyed to field names with the `fieldFormatters` option. Columns are still sorted using the raw, underlying values.

Among other things, this feature can be used to provide a unit of measurement, such as `$` or `%`, with numeric fields.

```svelte
<script lang="ts">
  const fieldFormatters = {
    // The key must match the column name in the data exactly
    'Net worth (in billions)': (v) => '$' + v.toFixed(1),
  };
</script>

<Table
  data={yourData}
  {fieldFormatters}
  sortable={true}
  sortField="Net worth (in billions)"
  sortDirection="descending"
  title="The Richest Women in the World"
  source="Source: Forbes"
/>
```
