# GeoList

> Top countries with a flag, the localised country name, a bar, share and change. Built on BreakdownTable.

Source: https://docs.nasaqui.com/components/geo-list

## Install

```bash
npx shadcn@latest add https://docs.nasaqui.com/r/geo-list.json
```

GeoList turns ISO country codes into rows with a flag and the country's name in the active language (via `Intl.DisplayNames`), then hands them to `BreakdownTable`. Unknown codes fall back to the code and an "Unknown" label.

## When to use

- Audience by country in analytics, search and video reports.
- Any ranking of ISO 3166-1 alpha-2 regions.

## When not to use

- Cities or regions without ISO codes: use [`BreakdownTable`](https://docs.nasaqui.com/components/breakdown-table).
- A map: this is a list.

## Import

```tsx
import { GeoList } from "@fadymondy/nasaq/web";
```

## Quick start

```tsx
import { GeoList } from "@fadymondy/nasaq/web";

export function Audience() {
  return (
    <GeoList
      valueLabel="Users"
      rows={[
        { code: "SA", value: 12400, previous: 11200 },
        { code: "EG", value: 8100, previous: 8600 },
      ]}
    />
  );
}
```

## Anatomy

```
GeoList                data-slot="breakdown-table"  (BreakdownTable underneath)
  row label            flag + country name
```

## API

### GeoList

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `rows` | `readonly GeoRow[]` | required | `{ code, value, previous? }`; `code` is ISO alpha-2. |
| `valueLabel` | `ReactNode` | required | Heading of the value column. |
| `title / description` | `ReactNode` | `Countries` | Card header. |
| `format` | `FormatNumberOptions` | none | Intl options for values. |
| `limit` | `number` | `8` | Rows before "Show all". |
| `invert` | `boolean` | `false` | Down is good. |
| `color` | `string` | `var(--primary)` | Bar colour, a token. |
| `loading` | `boolean` | `false` | Skeleton. |
| `className` | `string` | none | Extra classes on the root. |
| `labels` | `Partial<GeoListLabels> & { table? }` | none | Own strings plus `table` for the BreakdownTable strings. |

## Examples

Arabic country names:

```tsx
import { GeoList, NasaqProvider } from "@fadymondy/nasaq/web";

export const Ar = () => (
  <NasaqProvider locale="ar">
    <GeoList valueLabel="المستخدمون" rows={[{ code: "SA", value: 12400 }, { code: "AE", value: 5200 }]} />
  </NasaqProvider>
);
```

Unknown code:

```tsx
import { GeoList } from "@fadymondy/nasaq/web";

export const Unknown = () => <GeoList valueLabel="Users" rows={[{ code: "ZZ", value: 310 }]} />;
```

## Accessibility

Same as `BreakdownTable`. The flag is an emoji shown with the country name beside it, so the name is always readable.

## RTL & i18n

- Country names come from `Intl.DisplayNames` in the active locale.
- Flags never mirror.
- Every figure uses the active locale with Western digits and is bidi-isolated (`Num`), so `+12.4%` keeps its order in Arabic.

## Styling & tokens

- Colours come from tokens (`--primary`, `--nq-success`, `--nq-warning`, `--nq-danger`, `--nq-tag-*`); never pass raw hex.
- Inherits the `BreakdownTable` slots.

## Do / Don't

- Do pass ISO alpha-2 codes.
- Don't pass country names; they cannot be localised.

## Related

- [`breakdown-table`](https://docs.nasaqui.com/components/breakdown-table)
- [`metric-tiles`](https://docs.nasaqui.com/components/metric-tiles)
- [`google-analytics-page`](https://docs.nasaqui.com/components/google-analytics-page)

## Lab

https://docs.nasaqui.com/?path=/docs/components-analytics-geo-list--docs

## Code

### React

```tsx
import { GeoList } from "@fadymondy/nasaq/web";

export function Audience() {
  return (
    <GeoList
      valueLabel="Users"
      rows={[
        { code: "SA", value: 12400, previous: 11200 },
        { code: "EG", value: 8100, previous: 8600 },
      ]}
    />
  );
}
```

### shadcn

```tsx
import { GeoList } from "@/components/ui/geo-list";

export function Audience() {
  return (
    <GeoList
      valueLabel="Users"
      rows={[
        { code: "SA", value: 12400, previous: 11200 },
        { code: "EG", value: 8100, previous: 8600 },
      ]}
    />
  );
}
```

### Vue

```vue
<script setup lang="ts">
import { NqGeoList } from "@fadymondy/nasaq/vue";
</script>

<template>
  <NqGeoList
    value-label="Users"
    :rows="[
      { code: 'SA', value: 12400, previous: 11200 },
      { code: 'EG', value: 8100, previous: 8600 },
    ]"
  />
</template>
```

### Blade

```blade
<x-nq::geo-list
    value-label="Users"
    :rows="[
        ['code' => 'SA', 'value' => 12400, 'previous' => 11200],
        ['code' => 'EG', 'value' => 8100, 'previous' => 8600],
    ]"
/>
```

### HTML + Alpine

```html
<div data-slot="breakdown-table"      class="flex flex-col gap-4 rounded-card border border-border bg-card py-4 text-card-foreground">
            <div data-slot="card-header" class="grid auto-rows-min items-start gap-1 px-4 has-data-[slot=card-action]:grid-cols-[1fr_auto]"><h3 data-slot="card-title" class="text-label text-foreground">Countries</h3></div>
        <div data-slot="card-content" class="px-0"><div data-slot="table-container" role="region" tabindex="0"  aria-label="Countries"     class="relative w-full overflow-x-auto outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-nq-focus">
    <table data-slot="table" data-density="default"
                  class="w-full caption-bottom border-collapse text-body-sm">
        <thead data-slot="table-header" class="[&_tr]:border-b [&_tr]:hover:bg-transparent [&_tr]:even:bg-transparent"><tr data-slot="table-row"     class="border-b border-border transition-colors duration-150 ease-nq hover:bg-nq-hover data-[state=selected]:bg-nq-selected"><th data-slot="table-head" scope="col" class="h-row text-start align-middle text-caption font-medium whitespace-nowrap text-muted-foreground px-4 py-3">Country</th>
                        <th data-slot="table-head" scope="col" class="h-row align-middle text-caption font-medium whitespace-nowrap text-muted-foreground px-4 py-3 text-end">Users</th>
                        <th data-slot="table-head" scope="col" class="h-row align-middle text-caption font-medium whitespace-nowrap text-muted-foreground px-4 py-3 hidden text-end sm:table-cell">Share</th>
                        <th data-slot="table-head" scope="col" class="h-row align-middle text-caption font-medium whitespace-nowrap text-muted-foreground px-4 py-3 text-end">Change</th></tr></thead>
                <tbody data-slot="table-body" class="[&_tr:last-child]:border-0"><tr data-slot="table-row"     data-row="SA" class="border-b border-border transition-colors duration-150 ease-nq hover:bg-nq-hover data-[state=selected]:bg-nq-selected"><td data-slot="table-cell" class="h-row align-middle whitespace-nowrap px-4 py-3 min-w-40 max-w-0 sm:min-w-56"><span class="block truncate" dir="auto"><span class="inline-flex items-center gap-2"><span aria-hidden="true" class="text-base leading-none">🇸🇦</span>Saudi Arabia</span></span>
                                                                                                <span aria-hidden="true" data-slot="breakdown-bar" class="mt-1.5 block h-1.5 rounded-full bg-nq-surface-soft">
                                    <span class="block h-full rounded-full bg-[var(--bar)]" style="--bar: var(--primary); width: 100%"></span>
                                </span></td>
                            <td data-slot="table-cell" class="h-row align-middle whitespace-nowrap px-4 py-3 text-end tabular-nums"><bdi data-slot="num" data-numeric="" class="tabular-nums">12,400</bdi></td>
                                                            <td data-slot="table-cell" class="h-row align-middle whitespace-nowrap px-4 py-3 hidden text-end tabular-nums text-muted-foreground sm:table-cell"><bdi data-slot="num" data-numeric="" class="tabular-nums">60.5%</bdi></td>
                                                                                        <td data-slot="table-cell" class="h-row align-middle whitespace-nowrap px-4 py-3 text-end tabular-nums text-nq-success-text"><bdi data-slot="num" data-numeric="">+10.7%</bdi></td></tr>
                                                                    <tr data-slot="table-row"     data-row="EG" class="border-b border-border transition-colors duration-150 ease-nq hover:bg-nq-hover data-[state=selected]:bg-nq-selected"><td data-slot="table-cell" class="h-row align-middle whitespace-nowrap px-4 py-3 min-w-40 max-w-0 sm:min-w-56"><span class="block truncate" dir="auto"><span class="inline-flex items-center gap-2"><span aria-hidden="true" class="text-base leading-none">🇪🇬</span>Egypt</span></span>
                                                                                                <span aria-hidden="true" data-slot="breakdown-bar" class="mt-1.5 block h-1.5 rounded-full bg-nq-surface-soft">
                                    <span class="block h-full rounded-full bg-[var(--bar)]" style="--bar: var(--primary); width: 65.3226%"></span>
                                </span></td>
                            <td data-slot="table-cell" class="h-row align-middle whitespace-nowrap px-4 py-3 text-end tabular-nums"><bdi data-slot="num" data-numeric="" class="tabular-nums">8,100</bdi></td>
                                                            <td data-slot="table-cell" class="h-row align-middle whitespace-nowrap px-4 py-3 hidden text-end tabular-nums text-muted-foreground sm:table-cell"><bdi data-slot="num" data-numeric="" class="tabular-nums">39.5%</bdi></td>
                                                                                        <td data-slot="table-cell" class="h-row align-middle whitespace-nowrap px-4 py-3 text-end tabular-nums text-nq-danger-text"><bdi data-slot="num" data-numeric="">-5.8%</bdi></td></tr></tbody>
    </table>
</div></div>
</div>
```
