# IP lookup
> A field that looks up where an IP address is located and shows the result on a small map.
- React: `import { GeoIp } from "@/components/lumesec/geo-ip"`
- Collection: Location (https://elements.lumesec.ai/components/location)
- Data: takes your data (`data`); shows demo data until you pass it
- Registry item: https://elements.lumesec.ai/r/geo-ip.json
- Page: https://elements.lumesec.ai/components/location/ip



Live preview: https://elements.lumesec.ai/view/geo-ip

Demo source:

```tsx
"use client";

import * as React from "react";

import { GeoIp, type GeoIpHandle } from "@/components/lumesec/geo-ip";

/** Two documentation addresses (IPv4 and IPv6) and a private one, which is answered without a lookup. */
const EXAMPLES = ["203.0.113.42", "2001:db8::1", "192.168.1.20"];

export default function GeoIpDemo() {
  const lookupRef = React.useRef<GeoIpHandle>(null);
  return (
    <div className="grid w-full max-w-[380px] gap-3">
      <GeoIp ref={lookupRef} />
      <div className="flex flex-wrap items-center gap-1.5">
        {EXAMPLES.map((address) => (
          <button
            key={address}
            type="button"
            onClick={() => lookupRef.current?.lookup(address)}
            className="h-[30px] cursor-pointer rounded-lg border border-border bg-card px-[11px] font-mono text-[12px] font-medium text-foreground hover:border-[color-mix(in_srgb,var(--lumesec)_50%,var(--border))] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-solid focus-visible:outline-lumesec"
          >
            {address}
          </button>
        ))}
      </div>
      <p className="m-0 text-[12px] leading-[1.45] text-muted-foreground">
        Locations are invented from a hash of the address.
      </p>
    </div>
  );
}
```

## Installation

```bash
npx shadcn@latest add @lumesec/geo-ip
```

First time with the @lumesec registry? Register it once, or install by URL:

```bash
npx shadcn@latest registry add @lumesec=https://elements.lumesec.ai/r/{name}.json
npx shadcn@latest add https://elements.lumesec.ai/r/geo-ip.json
```

## Usage

React:

```tsx
"use client";

import { GeoIp, type GeoIpResult } from "@/components/lumesec/geo-ip";

async function resolve(address: string): Promise<GeoIpResult | null> {
  const response = await fetch(`/api/ip/${encodeURIComponent(address)}`);
  if (!response.ok) return null;
  const result: GeoIpResult = await response.json();
  return result;
}

export function Example() {
  return <GeoIp defaultValue="203.0.113.42" resolve={resolve} />;
}
```

## Behaviour

A field that looks up where an IP address is located and shows the result on a small map. While the lookup runs, a crosshair hops from land dot to land dot and slows down like a slot machine before it locks onto the result.

The coordinates roll into place, and the place, network and accuracy appear below. Private and reserved addresses are answered at once without a lookup. Bring your own `resolve` function; the built-in one invents a location and is only for demos.

## API reference

### Ref

`ref` points at the root `HTMLDivElement`.

## Theming

Styled with Tailwind classes on your shadcn theme tokens, so light and dark follow your theme. The accent comes from `--lumesec`. See [Theming](/docs/theming).


